r5825: Fix one more DISK_FREE call - spotted by Ying Li <ying.li2@hp.com>.
[Samba.git] / source / smbd / reply.c
blobe8ee9ffe92067dd9d7783aa821a1945213453d4f
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 outsize += DIR_STRUCT_SIZE*numentries;
985 smb_setlen(outbuf,outsize - 4);
987 if ((! *directory) && dptr_path(dptr_num))
988 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
990 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
991 smb_fn_name(CVAL(inbuf,smb_com)),
992 mask, directory, dirtype, numentries, maxentries ) );
994 END_PROFILE(SMBsearch);
995 return(outsize);
998 /****************************************************************************
999 Reply to a fclose (stop directory search).
1000 ****************************************************************************/
1002 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1004 int outsize = 0;
1005 int status_len;
1006 pstring path;
1007 char status[21];
1008 int dptr_num= -2;
1009 char *p;
1010 NTSTATUS err;
1012 START_PROFILE(SMBfclose);
1014 outsize = set_message(outbuf,1,0,True);
1015 p = smb_buf(inbuf) + 1;
1016 p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err, True);
1017 if (!NT_STATUS_IS_OK(err)) {
1018 END_PROFILE(SMBfclose);
1019 return ERROR_NT(err);
1021 p++;
1022 status_len = SVAL(p,0);
1023 p += 2;
1025 if (status_len == 0) {
1026 END_PROFILE(SMBfclose);
1027 return ERROR_DOS(ERRSRV,ERRsrverror);
1030 memcpy(status,p,21);
1032 if(dptr_fetch(status+12,&dptr_num)) {
1033 /* Close the dptr - we know it's gone */
1034 dptr_close(&dptr_num);
1037 SSVAL(outbuf,smb_vwv0,0);
1039 DEBUG(3,("search close\n"));
1041 END_PROFILE(SMBfclose);
1042 return(outsize);
1045 /****************************************************************************
1046 Reply to an open.
1047 ****************************************************************************/
1049 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1051 pstring fname;
1052 int outsize = 0;
1053 int fmode=0;
1054 int share_mode;
1055 SMB_OFF_T size = 0;
1056 time_t mtime=0;
1057 int rmode=0;
1058 SMB_STRUCT_STAT sbuf;
1059 BOOL bad_path = False;
1060 files_struct *fsp;
1061 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1062 uint16 dos_attr = SVAL(inbuf,smb_vwv1);
1063 NTSTATUS status;
1064 START_PROFILE(SMBopen);
1066 share_mode = SVAL(inbuf,smb_vwv0);
1068 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status, False);
1069 if (!NT_STATUS_IS_OK(status)) {
1070 END_PROFILE(SMBopen);
1071 return ERROR_NT(status);
1074 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1076 unix_convert(fname,conn,0,&bad_path,&sbuf);
1077 if (bad_path) {
1078 END_PROFILE(SMBopen);
1079 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1082 fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1083 (uint32)dos_attr, oplock_request,&rmode,NULL);
1085 if (!fsp) {
1086 END_PROFILE(SMBopen);
1087 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1088 /* We have re-scheduled this call. */
1089 clear_cached_errors();
1090 return -1;
1092 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1095 size = sbuf.st_size;
1096 fmode = dos_mode(conn,fname,&sbuf);
1097 mtime = sbuf.st_mtime;
1099 if (fmode & aDIR) {
1100 DEBUG(3,("attempt to open a directory %s\n",fname));
1101 close_file(fsp,False);
1102 END_PROFILE(SMBopen);
1103 return ERROR_DOS(ERRDOS,ERRnoaccess);
1106 outsize = set_message(outbuf,7,0,True);
1107 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1108 SSVAL(outbuf,smb_vwv1,fmode);
1109 if(lp_dos_filetime_resolution(SNUM(conn)) )
1110 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1111 else
1112 put_dos_date3(outbuf,smb_vwv2,mtime);
1113 SIVAL(outbuf,smb_vwv4,(uint32)size);
1114 SSVAL(outbuf,smb_vwv6,rmode);
1116 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1117 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1119 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1120 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1121 END_PROFILE(SMBopen);
1122 return(outsize);
1125 /****************************************************************************
1126 Reply to an open and X.
1127 ****************************************************************************/
1129 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1131 pstring fname;
1132 int smb_mode = SVAL(inbuf,smb_vwv3);
1133 int smb_attr = SVAL(inbuf,smb_vwv5);
1134 /* Breakout the oplock request bits so we can set the
1135 reply bits separately. */
1136 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1137 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1138 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1139 #if 0
1140 int open_flags = SVAL(inbuf,smb_vwv2);
1141 int smb_sattr = SVAL(inbuf,smb_vwv4);
1142 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1143 #endif
1144 int smb_ofun = SVAL(inbuf,smb_vwv8);
1145 SMB_OFF_T size=0;
1146 int fmode=0,mtime=0,rmode=0;
1147 SMB_STRUCT_STAT sbuf;
1148 int smb_action = 0;
1149 BOOL bad_path = False;
1150 files_struct *fsp;
1151 NTSTATUS status;
1152 START_PROFILE(SMBopenX);
1154 /* If it's an IPC, pass off the pipe handler. */
1155 if (IS_IPC(conn)) {
1156 if (lp_nt_pipe_support()) {
1157 END_PROFILE(SMBopenX);
1158 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1159 } else {
1160 END_PROFILE(SMBopenX);
1161 return ERROR_DOS(ERRSRV,ERRaccess);
1165 /* XXXX we need to handle passed times, sattr and flags */
1166 srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status, False);
1167 if (!NT_STATUS_IS_OK(status)) {
1168 END_PROFILE(SMBopenX);
1169 return ERROR_NT(status);
1172 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1174 unix_convert(fname,conn,0,&bad_path,&sbuf);
1175 if (bad_path) {
1176 END_PROFILE(SMBopenX);
1177 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1180 fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,(uint32)smb_attr,
1181 oplock_request, &rmode,&smb_action);
1183 if (!fsp) {
1184 END_PROFILE(SMBopenX);
1185 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1186 /* We have re-scheduled this call. */
1187 clear_cached_errors();
1188 return -1;
1190 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1193 size = sbuf.st_size;
1194 fmode = dos_mode(conn,fname,&sbuf);
1195 mtime = sbuf.st_mtime;
1196 if (fmode & aDIR) {
1197 close_file(fsp,False);
1198 END_PROFILE(SMBopenX);
1199 return ERROR_DOS(ERRDOS,ERRnoaccess);
1202 /* If the caller set the extended oplock request bit
1203 and we granted one (by whatever means) - set the
1204 correct bit for extended oplock reply.
1207 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn)))
1208 smb_action |= EXTENDED_OPLOCK_GRANTED;
1210 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1211 smb_action |= EXTENDED_OPLOCK_GRANTED;
1213 /* If the caller set the core oplock request bit
1214 and we granted one (by whatever means) - set the
1215 correct bit for core oplock reply.
1218 if (core_oplock_request && lp_fake_oplocks(SNUM(conn)))
1219 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1221 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1222 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1224 set_message(outbuf,15,0,True);
1225 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1226 SSVAL(outbuf,smb_vwv3,fmode);
1227 if(lp_dos_filetime_resolution(SNUM(conn)) )
1228 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1229 else
1230 put_dos_date3(outbuf,smb_vwv4,mtime);
1231 SIVAL(outbuf,smb_vwv6,(uint32)size);
1232 SSVAL(outbuf,smb_vwv8,rmode);
1233 SSVAL(outbuf,smb_vwv11,smb_action);
1235 END_PROFILE(SMBopenX);
1236 return chain_reply(inbuf,outbuf,length,bufsize);
1239 /****************************************************************************
1240 Reply to a SMBulogoffX.
1241 ****************************************************************************/
1243 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1245 uint16 vuid = SVAL(inbuf,smb_uid);
1246 user_struct *vuser = get_valid_user_struct(vuid);
1247 START_PROFILE(SMBulogoffX);
1249 if(vuser == 0)
1250 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1252 /* in user level security we are supposed to close any files
1253 open by this user */
1254 if ((vuser != 0) && (lp_security() != SEC_SHARE))
1255 file_close_user(vuid);
1257 invalidate_vuid(vuid);
1259 set_message(outbuf,2,0,True);
1261 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1263 END_PROFILE(SMBulogoffX);
1264 return chain_reply(inbuf,outbuf,length,bufsize);
1267 /****************************************************************************
1268 Reply to a mknew or a create.
1269 ****************************************************************************/
1271 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1273 pstring fname;
1274 int com;
1275 int outsize = 0;
1276 int createmode;
1277 int ofun = 0;
1278 BOOL bad_path = False;
1279 files_struct *fsp;
1280 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1281 SMB_STRUCT_STAT sbuf;
1282 NTSTATUS status;
1283 START_PROFILE(SMBcreate);
1285 com = SVAL(inbuf,smb_com);
1287 createmode = SVAL(inbuf,smb_vwv0);
1288 srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status, False);
1289 if (!NT_STATUS_IS_OK(status)) {
1290 END_PROFILE(SMBcreate);
1291 return ERROR_NT(status);
1294 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1296 unix_convert(fname,conn,0,&bad_path,&sbuf);
1297 if (bad_path) {
1298 END_PROFILE(SMBcreate);
1299 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1302 if (createmode & aVOLID)
1303 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1305 if(com == SMBmknew) {
1306 /* We should fail if file exists. */
1307 ofun = FILE_CREATE_IF_NOT_EXIST;
1308 } else {
1309 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1310 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1313 /* Open file in dos compatibility share mode. */
1314 fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1315 ofun, (uint32)createmode, oplock_request, NULL, NULL);
1317 if (!fsp) {
1318 END_PROFILE(SMBcreate);
1319 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1320 /* We have re-scheduled this call. */
1321 clear_cached_errors();
1322 return -1;
1324 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1327 outsize = set_message(outbuf,1,0,True);
1328 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1330 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1331 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1333 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1334 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1336 DEBUG( 2, ( "new file %s\n", fname ) );
1337 DEBUG( 3, ( "mknew %s fd=%d dmode=%d\n", fname, fsp->fd, createmode ) );
1339 END_PROFILE(SMBcreate);
1340 return(outsize);
1343 /****************************************************************************
1344 Reply to a create temporary file.
1345 ****************************************************************************/
1347 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1349 pstring fname;
1350 int outsize = 0;
1351 int createattr;
1352 BOOL bad_path = False;
1353 files_struct *fsp;
1354 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1355 int tmpfd;
1356 SMB_STRUCT_STAT sbuf;
1357 char *p, *s;
1358 NTSTATUS status;
1359 unsigned int namelen;
1361 START_PROFILE(SMBctemp);
1363 createattr = SVAL(inbuf,smb_vwv0);
1364 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status, False);
1365 if (!NT_STATUS_IS_OK(status)) {
1366 END_PROFILE(SMBctemp);
1367 return ERROR_NT(status);
1369 if (*fname) {
1370 pstrcat(fname,"/TMXXXXXX");
1371 } else {
1372 pstrcat(fname,"TMXXXXXX");
1375 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1377 unix_convert(fname,conn,0,&bad_path,&sbuf);
1378 if (bad_path) {
1379 END_PROFILE(SMBctemp);
1380 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1383 tmpfd = smb_mkstemp(fname);
1384 if (tmpfd == -1) {
1385 END_PROFILE(SMBctemp);
1386 return(UNIXERROR(ERRDOS,ERRnoaccess));
1389 SMB_VFS_STAT(conn,fname,&sbuf);
1391 /* Open file in dos compatibility share mode. */
1392 /* We should fail if file does not exist. */
1393 fsp = open_file_shared(conn,fname,&sbuf,
1394 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1395 FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
1396 (uint32)createattr, oplock_request, NULL, NULL);
1398 /* close fd from smb_mkstemp() */
1399 close(tmpfd);
1401 if (!fsp) {
1402 END_PROFILE(SMBctemp);
1403 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1404 /* We have re-scheduled this call. */
1405 clear_cached_errors();
1406 return -1;
1408 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1411 outsize = set_message(outbuf,1,0,True);
1412 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1414 /* the returned filename is relative to the directory */
1415 s = strrchr_m(fname, '/');
1416 if (!s)
1417 s = fname;
1418 else
1419 s++;
1421 p = smb_buf(outbuf);
1422 #if 0
1423 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
1424 thing in the byte section. JRA */
1425 SSVALS(p, 0, -1); /* what is this? not in spec */
1426 #endif
1427 namelen = srvstr_push(outbuf, p, s, -1, STR_ASCII|STR_TERMINATE);
1428 p += namelen;
1429 outsize = set_message_end(outbuf, p);
1431 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1432 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1434 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1435 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1437 DEBUG( 2, ( "created temp file %s\n", fname ) );
1438 DEBUG( 3, ( "ctemp %s fd=%d umode=%o\n",
1439 fname, fsp->fd, sbuf.st_mode ) );
1441 END_PROFILE(SMBctemp);
1442 return(outsize);
1445 /*******************************************************************
1446 Check if a user is allowed to rename a file.
1447 ********************************************************************/
1449 static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, SMB_STRUCT_STAT *pst)
1451 int smb_action;
1452 int access_mode;
1453 files_struct *fsp;
1454 uint16 fmode;
1456 if (!CAN_WRITE(conn))
1457 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1459 fmode = dos_mode(conn,fname,pst);
1460 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1461 return NT_STATUS_NO_SUCH_FILE;
1463 if (S_ISDIR(pst->st_mode))
1464 return NT_STATUS_OK;
1466 /* We need a better way to return NT status codes from open... */
1467 unix_ERR_class = 0;
1468 unix_ERR_code = 0;
1470 fsp = open_file_shared1(conn, fname, pst, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1471 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action);
1473 if (!fsp) {
1474 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1475 if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1476 ret = NT_STATUS_SHARING_VIOLATION;
1477 unix_ERR_class = 0;
1478 unix_ERR_code = 0;
1479 unix_ERR_ntstatus = NT_STATUS_OK;
1480 return ret;
1482 close_file(fsp,False);
1483 return NT_STATUS_OK;
1486 /*******************************************************************
1487 Check if a user is allowed to delete a file.
1488 ********************************************************************/
1490 NTSTATUS can_delete(connection_struct *conn, char *fname, int dirtype, BOOL bad_path, BOOL check_is_at_open)
1492 SMB_STRUCT_STAT sbuf;
1493 int fmode;
1494 int smb_action;
1495 int access_mode;
1496 files_struct *fsp;
1498 DEBUG(10,("can_delete: %s, dirtype = %d\n",
1499 fname, dirtype ));
1501 if (!CAN_WRITE(conn))
1502 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1504 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
1505 if(errno == ENOENT) {
1506 if (bad_path)
1507 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1508 else
1509 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1511 return map_nt_error_from_unix(errno);
1514 fmode = dos_mode(conn,fname,&sbuf);
1516 /* Can't delete a directory. */
1517 if (fmode & aDIR)
1518 return NT_STATUS_FILE_IS_A_DIRECTORY;
1519 #if 0 /* JRATEST */
1520 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
1521 return NT_STATUS_OBJECT_NAME_INVALID;
1522 #endif /* JRATEST */
1524 if (!lp_delete_readonly(SNUM(conn))) {
1525 if (fmode & aRONLY)
1526 return NT_STATUS_CANNOT_DELETE;
1528 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1529 return NT_STATUS_NO_SUCH_FILE;
1531 if (check_is_at_open) {
1532 if (!can_delete_file_in_directory(conn, fname)) {
1533 return NT_STATUS_ACCESS_DENIED;
1535 } else {
1536 /* On open checks the open itself will check the share mode, so
1537 don't do it here as we'll get it wrong. */
1539 /* We need a better way to return NT status codes from open... */
1540 unix_ERR_class = 0;
1541 unix_ERR_code = 0;
1543 fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1544 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action);
1546 if (!fsp) {
1547 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1548 if (!NT_STATUS_IS_OK(unix_ERR_ntstatus))
1549 ret = unix_ERR_ntstatus;
1550 else if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1551 ret = NT_STATUS_SHARING_VIOLATION;
1552 unix_ERR_class = 0;
1553 unix_ERR_code = 0;
1554 unix_ERR_ntstatus = NT_STATUS_OK;
1555 return ret;
1557 close_file(fsp,False);
1559 return NT_STATUS_OK;
1562 /****************************************************************************
1563 The guts of the unlink command, split out so it may be called by the NT SMB
1564 code.
1565 ****************************************************************************/
1567 NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
1569 pstring directory;
1570 pstring mask;
1571 char *p;
1572 int count=0;
1573 NTSTATUS error = NT_STATUS_OK;
1574 BOOL has_wild;
1575 BOOL bad_path = False;
1576 BOOL rc = True;
1577 SMB_STRUCT_STAT sbuf;
1579 *directory = *mask = 0;
1581 /* We must check for wildcards in the name given
1582 * directly by the client - before any unmangling.
1583 * This prevents an unmangling of a UNIX name containing
1584 * a DOS wildcard like '*' or '?' from unmangling into
1585 * a wildcard delete which was not intended.
1586 * FIX for #226. JRA.
1589 has_wild = ms_has_wild(name);
1591 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1593 p = strrchr_m(name,'/');
1594 if (!p) {
1595 pstrcpy(directory,".");
1596 pstrcpy(mask,name);
1597 } else {
1598 *p = 0;
1599 pstrcpy(directory,name);
1600 pstrcpy(mask,p+1);
1604 * We should only check the mangled cache
1605 * here if unix_convert failed. This means
1606 * that the path in 'mask' doesn't exist
1607 * on the file system and so we need to look
1608 * for a possible mangle. This patch from
1609 * Tine Smukavec <valentin.smukavec@hermes.si>.
1612 if (!rc && mangle_is_mangled(mask))
1613 mangle_check_cache( mask, sizeof(pstring)-1 );
1615 if (!has_wild) {
1616 pstrcat(directory,"/");
1617 pstrcat(directory,mask);
1618 error = can_delete(conn,directory,dirtype,bad_path,False);
1619 if (!NT_STATUS_IS_OK(error))
1620 return error;
1622 if (SMB_VFS_UNLINK(conn,directory) == 0) {
1623 count++;
1625 } else {
1626 struct smb_Dir *dir_hnd = NULL;
1627 const char *dname;
1629 if (check_name(directory,conn))
1630 dir_hnd = OpenDir(conn, directory);
1632 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1633 the pattern matches against the long name, otherwise the short name
1634 We don't implement this yet XXXX
1637 if (dir_hnd) {
1638 long offset = 0;
1639 error = NT_STATUS_NO_SUCH_FILE;
1641 if (strequal(mask,"????????.???"))
1642 pstrcpy(mask,"*");
1644 while ((dname = ReadDirName(dir_hnd, &offset))) {
1645 SMB_STRUCT_STAT st;
1646 pstring fname;
1647 BOOL sys_direntry = False;
1648 pstrcpy(fname,dname);
1650 if (!is_visible_file(conn, directory, dname, &st, True)) {
1651 continue;
1654 /* Quick check for "." and ".." */
1655 if (fname[0] == '.') {
1656 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
1657 if ((dirtype & FILE_ATTRIBUTE_DIRECTORY) && (dirtype & FILE_ATTRIBUTE_SYSTEM)) {
1658 sys_direntry = True;
1659 } else {
1660 continue;
1665 if(!mask_match(fname, mask, conn->case_sensitive))
1666 continue;
1668 if (sys_direntry) {
1669 error = NT_STATUS_OBJECT_NAME_INVALID;
1670 DEBUG(3,("unlink_internals: system directory delete denied [%s] mask [%s]\n",
1671 fname, mask));
1672 break;
1675 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1676 error = can_delete(conn,fname,dirtype,bad_path,False);
1677 if (!NT_STATUS_IS_OK(error)) {
1678 continue;
1680 if (SMB_VFS_UNLINK(conn,fname) == 0)
1681 count++;
1682 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
1684 CloseDir(dir_hnd);
1688 if (count == 0 && NT_STATUS_IS_OK(error)) {
1689 error = map_nt_error_from_unix(errno);
1692 return error;
1695 /****************************************************************************
1696 Reply to a unlink
1697 ****************************************************************************/
1699 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
1700 int dum_buffsize)
1702 int outsize = 0;
1703 pstring name;
1704 int dirtype;
1705 NTSTATUS status;
1706 START_PROFILE(SMBunlink);
1708 dirtype = SVAL(inbuf,smb_vwv0);
1710 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, True);
1711 if (!NT_STATUS_IS_OK(status)) {
1712 END_PROFILE(SMBunlink);
1713 return ERROR_NT(status);
1716 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1718 DEBUG(3,("reply_unlink : %s\n",name));
1720 status = unlink_internals(conn, dirtype, name);
1721 if (!NT_STATUS_IS_OK(status)) {
1722 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1723 /* We have re-scheduled this call. */
1724 clear_cached_errors();
1725 return -1;
1727 return ERROR_NT(status);
1731 * Win2k needs a changenotify request response before it will
1732 * update after a rename..
1734 process_pending_change_notify_queue((time_t)0);
1736 outsize = set_message(outbuf,0,0,True);
1738 END_PROFILE(SMBunlink);
1739 return outsize;
1742 /****************************************************************************
1743 Fail for readbraw.
1744 ****************************************************************************/
1746 static void fail_readraw(void)
1748 pstring errstr;
1749 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
1750 strerror(errno) );
1751 exit_server(errstr);
1754 #if defined(WITH_SENDFILE)
1755 /****************************************************************************
1756 Fake (read/write) sendfile. Returns -1 on read or write fail.
1757 ****************************************************************************/
1759 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread, char *buf, int bufsize)
1761 ssize_t ret=0;
1763 /* Paranioa check... */
1764 if (nread > bufsize) {
1765 fail_readraw();
1768 if (nread > 0) {
1769 ret = read_file(fsp,buf,startpos,nread);
1770 if (ret == -1) {
1771 return -1;
1775 /* If we had a short read, fill with zeros. */
1776 if (ret < nread) {
1777 memset(buf, '\0', nread - ret);
1780 if (write_data(smbd_server_fd(),buf,nread) != nread) {
1781 return -1;
1784 return (ssize_t)nread;
1786 #endif
1788 /****************************************************************************
1789 Use sendfile in readbraw.
1790 ****************************************************************************/
1792 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
1793 ssize_t mincount, char *outbuf, int out_buffsize)
1795 ssize_t ret=0;
1797 #if defined(WITH_SENDFILE)
1799 * We can only use sendfile on a non-chained packet
1800 * but we can use on a non-oplocked file. tridge proved this
1801 * on a train in Germany :-). JRA.
1802 * reply_readbraw has already checked the length.
1805 if (chain_size ==0 && (nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) && lp_use_sendfile(SNUM(conn)) ) {
1806 DATA_BLOB header;
1808 _smb_setlen(outbuf,nread);
1809 header.data = outbuf;
1810 header.length = 4;
1811 header.free = NULL;
1813 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) {
1814 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
1815 if (errno == ENOSYS) {
1816 goto normal_readbraw;
1820 * Special hack for broken Linux with no working sendfile. If we
1821 * return EINTR we sent the header but not the rest of the data.
1822 * Fake this up by doing read/write calls.
1824 if (errno == EINTR) {
1825 /* Ensure we don't do this again. */
1826 set_use_sendfile(SNUM(conn), False);
1827 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
1829 if (fake_sendfile(fsp, startpos, nread, outbuf + 4, out_buffsize - 4) == -1) {
1830 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
1831 fsp->fsp_name, strerror(errno) ));
1832 exit_server("send_file_readbraw fake_sendfile failed");
1834 return;
1837 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
1838 fsp->fsp_name, strerror(errno) ));
1839 exit_server("send_file_readbraw sendfile failed");
1844 normal_readbraw:
1846 #endif
1848 if (nread > 0) {
1849 ret = read_file(fsp,outbuf+4,startpos,nread);
1850 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1851 if (ret < mincount)
1852 ret = 0;
1853 #else
1854 if (ret < nread)
1855 ret = 0;
1856 #endif
1859 _smb_setlen(outbuf,ret);
1860 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
1861 fail_readraw();
1864 /****************************************************************************
1865 Reply to a readbraw (core+ protocol).
1866 ****************************************************************************/
1868 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int out_buffsize)
1870 extern struct current_user current_user;
1871 ssize_t maxcount,mincount;
1872 size_t nread = 0;
1873 SMB_OFF_T startpos;
1874 char *header = outbuf;
1875 files_struct *fsp;
1876 START_PROFILE(SMBreadbraw);
1878 if (srv_is_signing_active()) {
1879 exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
1883 * Special check if an oplock break has been issued
1884 * and the readraw request croses on the wire, we must
1885 * return a zero length response here.
1888 if(global_oplock_break) {
1889 _smb_setlen(header,0);
1890 if (write_data(smbd_server_fd(),header,4) != 4)
1891 fail_readraw();
1892 DEBUG(5,("readbraw - oplock break finished\n"));
1893 END_PROFILE(SMBreadbraw);
1894 return -1;
1897 fsp = file_fsp(inbuf,smb_vwv0);
1899 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1901 * fsp could be NULL here so use the value from the packet. JRA.
1903 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
1904 _smb_setlen(header,0);
1905 if (write_data(smbd_server_fd(),header,4) != 4)
1906 fail_readraw();
1907 END_PROFILE(SMBreadbraw);
1908 return(-1);
1911 CHECK_FSP(fsp,conn);
1913 flush_write_cache(fsp, READRAW_FLUSH);
1915 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
1916 if(CVAL(inbuf,smb_wct) == 10) {
1918 * This is a large offset (64 bit) read.
1920 #ifdef LARGE_SMB_OFF_T
1922 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
1924 #else /* !LARGE_SMB_OFF_T */
1927 * Ensure we haven't been sent a >32 bit offset.
1930 if(IVAL(inbuf,smb_vwv8) != 0) {
1931 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
1932 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
1933 _smb_setlen(header,0);
1934 if (write_data(smbd_server_fd(),header,4) != 4)
1935 fail_readraw();
1936 END_PROFILE(SMBreadbraw);
1937 return(-1);
1940 #endif /* LARGE_SMB_OFF_T */
1942 if(startpos < 0) {
1943 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
1944 _smb_setlen(header,0);
1945 if (write_data(smbd_server_fd(),header,4) != 4)
1946 fail_readraw();
1947 END_PROFILE(SMBreadbraw);
1948 return(-1);
1951 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
1952 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
1954 /* ensure we don't overrun the packet size */
1955 maxcount = MIN(65535,maxcount);
1957 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
1958 SMB_OFF_T size = fsp->size;
1959 SMB_OFF_T sizeneeded = startpos + maxcount;
1961 if (size < sizeneeded) {
1962 SMB_STRUCT_STAT st;
1963 if (SMB_VFS_FSTAT(fsp,fsp->fd,&st) == 0)
1964 size = st.st_size;
1965 if (!fsp->can_write)
1966 fsp->size = size;
1969 if (startpos >= size)
1970 nread = 0;
1971 else
1972 nread = MIN(maxcount,(size - startpos));
1975 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1976 if (nread < mincount)
1977 nread = 0;
1978 #endif
1980 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
1981 (int)maxcount, (int)mincount, (int)nread ) );
1983 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf, out_buffsize);
1985 DEBUG(5,("readbraw finished\n"));
1986 END_PROFILE(SMBreadbraw);
1987 return -1;
1990 /****************************************************************************
1991 Reply to a lockread (core+ protocol).
1992 ****************************************************************************/
1994 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
1996 ssize_t nread = -1;
1997 char *data;
1998 int outsize = 0;
1999 SMB_OFF_T startpos;
2000 size_t numtoread;
2001 NTSTATUS status;
2002 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2003 BOOL my_lock_ctx = False;
2004 START_PROFILE(SMBlockread);
2006 CHECK_FSP(fsp,conn);
2007 CHECK_READ(fsp);
2009 release_level_2_oplocks_on_change(fsp);
2011 numtoread = SVAL(inbuf,smb_vwv1);
2012 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2014 outsize = set_message(outbuf,5,3,True);
2015 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2016 data = smb_buf(outbuf) + 3;
2019 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2020 * protocol request that predates the read/write lock concept.
2021 * Thus instead of asking for a read lock here we need to ask
2022 * for a write lock. JRA.
2023 * Note that the requested lock size is unaffected by max_recv.
2026 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid),
2027 (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, &my_lock_ctx);
2029 if (NT_STATUS_V(status)) {
2030 #if 0
2032 * We used to make lockread a blocking lock. It turns out
2033 * that this isn't on W2k. Found by the Samba 4 RAW-READ torture
2034 * tester. JRA.
2037 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
2039 * A blocking lock was requested. Package up
2040 * this smb into a queued request and push it
2041 * onto the blocking lock queue.
2043 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)startpos,
2044 (SMB_BIG_UINT)numtoread)) {
2045 END_PROFILE(SMBlockread);
2046 return -1;
2049 #endif
2050 END_PROFILE(SMBlockread);
2051 return ERROR_NT(status);
2055 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
2058 if (numtoread > max_recv) {
2059 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
2060 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2061 (unsigned int)numtoread, (unsigned int)max_recv ));
2062 numtoread = MIN(numtoread,max_recv);
2064 nread = read_file(fsp,data,startpos,numtoread);
2066 if (nread < 0) {
2067 END_PROFILE(SMBlockread);
2068 return(UNIXERROR(ERRDOS,ERRnoaccess));
2071 outsize += nread;
2072 SSVAL(outbuf,smb_vwv0,nread);
2073 SSVAL(outbuf,smb_vwv5,nread+3);
2074 SSVAL(smb_buf(outbuf),1,nread);
2076 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
2077 fsp->fnum, (int)numtoread, (int)nread));
2079 END_PROFILE(SMBlockread);
2080 return(outsize);
2083 /****************************************************************************
2084 Reply to a read.
2085 ****************************************************************************/
2087 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2089 size_t numtoread;
2090 ssize_t nread = 0;
2091 char *data;
2092 SMB_OFF_T startpos;
2093 int outsize = 0;
2094 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2095 START_PROFILE(SMBread);
2097 CHECK_FSP(fsp,conn);
2098 CHECK_READ(fsp);
2100 numtoread = SVAL(inbuf,smb_vwv1);
2101 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2103 outsize = set_message(outbuf,5,3,True);
2104 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2106 * The requested read size cannot be greater than max_recv. JRA.
2108 if (numtoread > max_recv) {
2109 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
2110 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2111 (unsigned int)numtoread, (unsigned int)max_recv ));
2112 numtoread = MIN(numtoread,max_recv);
2115 data = smb_buf(outbuf) + 3;
2117 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2118 END_PROFILE(SMBread);
2119 return ERROR_DOS(ERRDOS,ERRlock);
2122 if (numtoread > 0)
2123 nread = read_file(fsp,data,startpos,numtoread);
2125 if (nread < 0) {
2126 END_PROFILE(SMBread);
2127 return(UNIXERROR(ERRDOS,ERRnoaccess));
2130 outsize += nread;
2131 SSVAL(outbuf,smb_vwv0,nread);
2132 SSVAL(outbuf,smb_vwv5,nread+3);
2133 SCVAL(smb_buf(outbuf),0,1);
2134 SSVAL(smb_buf(outbuf),1,nread);
2136 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2137 fsp->fnum, (int)numtoread, (int)nread ) );
2139 END_PROFILE(SMBread);
2140 return(outsize);
2143 /****************************************************************************
2144 Reply to a read and X - possibly using sendfile.
2145 ****************************************************************************/
2147 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length, int len_outbuf,
2148 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
2150 int outsize = 0;
2151 ssize_t nread = -1;
2152 char *data = smb_buf(outbuf);
2154 #if defined(WITH_SENDFILE)
2156 * We can only use sendfile on a non-chained packet
2157 * but we can use on a non-oplocked file. tridge proved this
2158 * on a train in Germany :-). JRA.
2161 if (chain_size ==0 && (CVAL(inbuf,smb_vwv0) == 0xFF) && lp_use_sendfile(SNUM(conn)) &&
2162 (lp_write_cache_size(SNUM(conn)) == 0) ) {
2163 SMB_STRUCT_STAT sbuf;
2164 DATA_BLOB header;
2166 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1)
2167 return(UNIXERROR(ERRDOS,ERRnoaccess));
2169 if (startpos > sbuf.st_size)
2170 goto normal_read;
2172 if (smb_maxcnt > (sbuf.st_size - startpos))
2173 smb_maxcnt = (sbuf.st_size - startpos);
2175 if (smb_maxcnt == 0)
2176 goto normal_read;
2179 * Set up the packet header before send. We
2180 * assume here the sendfile will work (get the
2181 * correct amount of data).
2184 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2185 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
2186 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2187 SSVAL(outbuf,smb_vwv7,((smb_maxcnt >> 16) & 1));
2188 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
2189 SCVAL(outbuf,smb_vwv0,0xFF);
2190 set_message(outbuf,12,smb_maxcnt,False);
2191 header.data = outbuf;
2192 header.length = data - outbuf;
2193 header.free = NULL;
2195 if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt)) == -1) {
2196 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2197 if (errno == ENOSYS) {
2198 goto normal_read;
2202 * Special hack for broken Linux with no working sendfile. If we
2203 * return EINTR we sent the header but not the rest of the data.
2204 * Fake this up by doing read/write calls.
2207 if (errno == EINTR) {
2208 /* Ensure we don't do this again. */
2209 set_use_sendfile(SNUM(conn), False);
2210 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
2212 if ((nread = fake_sendfile(fsp, startpos, smb_maxcnt, data,
2213 len_outbuf - (data-outbuf))) == -1) {
2214 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
2215 fsp->fsp_name, strerror(errno) ));
2216 exit_server("send_file_readX: fake_sendfile failed");
2218 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
2219 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2220 /* Returning -1 here means successful sendfile. */
2221 return -1;
2224 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2225 fsp->fsp_name, strerror(errno) ));
2226 exit_server("send_file_readX sendfile failed");
2229 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2230 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2231 /* Returning -1 here means successful sendfile. */
2232 return -1;
2235 normal_read:
2237 #endif
2239 nread = read_file(fsp,data,startpos,smb_maxcnt);
2241 if (nread < 0) {
2242 END_PROFILE(SMBreadX);
2243 return(UNIXERROR(ERRDOS,ERRnoaccess));
2246 outsize = set_message(outbuf,12,nread,False);
2247 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2248 SSVAL(outbuf,smb_vwv5,nread);
2249 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2250 SSVAL(outbuf,smb_vwv7,((nread >> 16) & 1));
2251 SSVAL(smb_buf(outbuf),-2,nread);
2253 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2254 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2256 /* Returning the number of bytes we want to send back - including header. */
2257 return outsize;
2260 /****************************************************************************
2261 Reply to a read and X.
2262 ****************************************************************************/
2264 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2266 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2267 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2268 ssize_t nread = -1;
2269 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2270 #if 0
2271 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2272 #endif
2274 START_PROFILE(SMBreadX);
2276 /* If it's an IPC, pass off the pipe handler. */
2277 if (IS_IPC(conn)) {
2278 END_PROFILE(SMBreadX);
2279 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2282 CHECK_FSP(fsp,conn);
2283 CHECK_READ(fsp);
2285 set_message(outbuf,12,0,True);
2287 if (global_client_caps & CAP_LARGE_READX) {
2288 if (SVAL(inbuf,smb_vwv7) == 1) {
2289 smb_maxcnt |= (1<<16);
2291 if (smb_maxcnt > BUFFER_SIZE) {
2292 DEBUG(0,("reply_read_and_X - read too large (%u) for reply buffer %u\n",
2293 (unsigned int)smb_maxcnt, (unsigned int)BUFFER_SIZE));
2294 END_PROFILE(SMBreadX);
2295 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2299 if(CVAL(inbuf,smb_wct) == 12) {
2300 #ifdef LARGE_SMB_OFF_T
2302 * This is a large offset (64 bit) read.
2304 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2306 #else /* !LARGE_SMB_OFF_T */
2309 * Ensure we haven't been sent a >32 bit offset.
2312 if(IVAL(inbuf,smb_vwv10) != 0) {
2313 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2314 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2315 END_PROFILE(SMBreadX);
2316 return ERROR_DOS(ERRDOS,ERRbadaccess);
2319 #endif /* LARGE_SMB_OFF_T */
2323 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2324 END_PROFILE(SMBreadX);
2325 return ERROR_DOS(ERRDOS,ERRlock);
2328 nread = send_file_readX(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt);
2329 if (nread != -1)
2330 nread = chain_reply(inbuf,outbuf,length,bufsize);
2332 END_PROFILE(SMBreadX);
2333 return nread;
2336 /****************************************************************************
2337 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2338 ****************************************************************************/
2340 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2342 ssize_t nwritten=0;
2343 ssize_t total_written=0;
2344 size_t numtowrite=0;
2345 size_t tcount;
2346 SMB_OFF_T startpos;
2347 char *data=NULL;
2348 BOOL write_through;
2349 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2350 int outsize = 0;
2351 START_PROFILE(SMBwritebraw);
2353 if (srv_is_signing_active()) {
2354 exit_server("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2357 CHECK_FSP(fsp,conn);
2358 CHECK_WRITE(fsp);
2360 tcount = IVAL(inbuf,smb_vwv1);
2361 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2362 write_through = BITSETW(inbuf+smb_vwv7,0);
2364 /* We have to deal with slightly different formats depending
2365 on whether we are using the core+ or lanman1.0 protocol */
2367 if(Protocol <= PROTOCOL_COREPLUS) {
2368 numtowrite = SVAL(smb_buf(inbuf),-2);
2369 data = smb_buf(inbuf);
2370 } else {
2371 numtowrite = SVAL(inbuf,smb_vwv10);
2372 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2375 /* force the error type */
2376 SCVAL(inbuf,smb_com,SMBwritec);
2377 SCVAL(outbuf,smb_com,SMBwritec);
2379 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2380 END_PROFILE(SMBwritebraw);
2381 return(ERROR_DOS(ERRDOS,ERRlock));
2384 if (numtowrite>0)
2385 nwritten = write_file(fsp,data,startpos,numtowrite);
2387 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2388 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2390 if (nwritten < (ssize_t)numtowrite) {
2391 END_PROFILE(SMBwritebraw);
2392 return(UNIXERROR(ERRHRD,ERRdiskfull));
2395 total_written = nwritten;
2397 /* Return a message to the redirector to tell it to send more bytes */
2398 SCVAL(outbuf,smb_com,SMBwritebraw);
2399 SSVALS(outbuf,smb_vwv0,-1);
2400 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2401 if (!send_smb(smbd_server_fd(),outbuf))
2402 exit_server("reply_writebraw: send_smb failed.");
2404 /* Now read the raw data into the buffer and write it */
2405 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2406 exit_server("secondary writebraw failed");
2409 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2410 numtowrite = smb_len(inbuf);
2412 /* Set up outbuf to return the correct return */
2413 outsize = set_message(outbuf,1,0,True);
2414 SCVAL(outbuf,smb_com,SMBwritec);
2415 SSVAL(outbuf,smb_vwv0,total_written);
2417 if (numtowrite != 0) {
2419 if (numtowrite > BUFFER_SIZE) {
2420 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2421 (unsigned int)numtowrite ));
2422 exit_server("secondary writebraw failed");
2425 if (tcount > nwritten+numtowrite) {
2426 DEBUG(3,("Client overestimated the write %d %d %d\n",
2427 (int)tcount,(int)nwritten,(int)numtowrite));
2430 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2431 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2432 strerror(errno) ));
2433 exit_server("secondary writebraw failed");
2436 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2438 if (nwritten < (ssize_t)numtowrite) {
2439 SCVAL(outbuf,smb_rcls,ERRHRD);
2440 SSVAL(outbuf,smb_err,ERRdiskfull);
2443 if (nwritten > 0)
2444 total_written += nwritten;
2447 if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn)))
2448 sync_file(conn,fsp);
2450 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2451 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2453 /* we won't return a status if write through is not selected - this follows what WfWg does */
2454 END_PROFILE(SMBwritebraw);
2455 if (!write_through && total_written==tcount) {
2457 #if RABBIT_PELLET_FIX
2459 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2460 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2462 if (!send_keepalive(smbd_server_fd()))
2463 exit_server("reply_writebraw: send of keepalive failed");
2464 #endif
2465 return(-1);
2468 return(outsize);
2471 /****************************************************************************
2472 Reply to a writeunlock (core+).
2473 ****************************************************************************/
2475 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
2476 int size, int dum_buffsize)
2478 ssize_t nwritten = -1;
2479 size_t numtowrite;
2480 SMB_OFF_T startpos;
2481 char *data;
2482 NTSTATUS status = NT_STATUS_OK;
2483 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2484 int outsize = 0;
2485 START_PROFILE(SMBwriteunlock);
2487 CHECK_FSP(fsp,conn);
2488 CHECK_WRITE(fsp);
2490 numtowrite = SVAL(inbuf,smb_vwv1);
2491 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2492 data = smb_buf(inbuf) + 3;
2494 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2495 END_PROFILE(SMBwriteunlock);
2496 return ERROR_DOS(ERRDOS,ERRlock);
2499 /* The special X/Open SMB protocol handling of
2500 zero length writes is *NOT* done for
2501 this call */
2502 if(numtowrite == 0)
2503 nwritten = 0;
2504 else
2505 nwritten = write_file(fsp,data,startpos,numtowrite);
2507 if (lp_syncalways(SNUM(conn)))
2508 sync_file(conn,fsp);
2510 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2511 END_PROFILE(SMBwriteunlock);
2512 return(UNIXERROR(ERRHRD,ERRdiskfull));
2515 if (numtowrite) {
2516 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite,
2517 (SMB_BIG_UINT)startpos);
2518 if (NT_STATUS_V(status)) {
2519 END_PROFILE(SMBwriteunlock);
2520 return ERROR_NT(status);
2524 outsize = set_message(outbuf,1,0,True);
2526 SSVAL(outbuf,smb_vwv0,nwritten);
2528 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2529 fsp->fnum, (int)numtowrite, (int)nwritten));
2531 END_PROFILE(SMBwriteunlock);
2532 return outsize;
2535 /****************************************************************************
2536 Reply to a write.
2537 ****************************************************************************/
2539 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2541 size_t numtowrite;
2542 ssize_t nwritten = -1;
2543 SMB_OFF_T startpos;
2544 char *data;
2545 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2546 int outsize = 0;
2547 START_PROFILE(SMBwrite);
2549 /* If it's an IPC, pass off the pipe handler. */
2550 if (IS_IPC(conn)) {
2551 END_PROFILE(SMBwrite);
2552 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2555 CHECK_FSP(fsp,conn);
2556 CHECK_WRITE(fsp);
2558 numtowrite = SVAL(inbuf,smb_vwv1);
2559 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2560 data = smb_buf(inbuf) + 3;
2562 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2563 END_PROFILE(SMBwrite);
2564 return ERROR_DOS(ERRDOS,ERRlock);
2568 * X/Open SMB protocol says that if smb_vwv1 is
2569 * zero then the file size should be extended or
2570 * truncated to the size given in smb_vwv[2-3].
2573 if(numtowrite == 0) {
2575 * This is actually an allocate call, and set EOF. JRA.
2577 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2578 if (nwritten < 0) {
2579 END_PROFILE(SMBwrite);
2580 return ERROR_NT(NT_STATUS_DISK_FULL);
2582 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2583 if (nwritten < 0) {
2584 END_PROFILE(SMBwrite);
2585 return ERROR_NT(NT_STATUS_DISK_FULL);
2587 } else
2588 nwritten = write_file(fsp,data,startpos,numtowrite);
2590 if (lp_syncalways(SNUM(conn)))
2591 sync_file(conn,fsp);
2593 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2594 END_PROFILE(SMBwrite);
2595 return(UNIXERROR(ERRHRD,ERRdiskfull));
2598 outsize = set_message(outbuf,1,0,True);
2600 SSVAL(outbuf,smb_vwv0,nwritten);
2602 if (nwritten < (ssize_t)numtowrite) {
2603 SCVAL(outbuf,smb_rcls,ERRHRD);
2604 SSVAL(outbuf,smb_err,ERRdiskfull);
2607 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2609 END_PROFILE(SMBwrite);
2610 return(outsize);
2613 /****************************************************************************
2614 Reply to a write and X.
2615 ****************************************************************************/
2617 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2619 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2620 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2621 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2622 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2623 ssize_t nwritten = -1;
2624 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2625 unsigned int smblen = smb_len(inbuf);
2626 char *data;
2627 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2628 START_PROFILE(SMBwriteX);
2630 /* If it's an IPC, pass off the pipe handler. */
2631 if (IS_IPC(conn)) {
2632 END_PROFILE(SMBwriteX);
2633 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2636 CHECK_FSP(fsp,conn);
2637 CHECK_WRITE(fsp);
2639 /* Deal with possible LARGE_WRITEX */
2640 if (large_writeX)
2641 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2643 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2644 END_PROFILE(SMBwriteX);
2645 return ERROR_DOS(ERRDOS,ERRbadmem);
2648 data = smb_base(inbuf) + smb_doff;
2650 if(CVAL(inbuf,smb_wct) == 14) {
2651 #ifdef LARGE_SMB_OFF_T
2653 * This is a large offset (64 bit) write.
2655 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2657 #else /* !LARGE_SMB_OFF_T */
2660 * Ensure we haven't been sent a >32 bit offset.
2663 if(IVAL(inbuf,smb_vwv12) != 0) {
2664 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2665 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2666 END_PROFILE(SMBwriteX);
2667 return ERROR_DOS(ERRDOS,ERRbadaccess);
2670 #endif /* LARGE_SMB_OFF_T */
2673 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2674 END_PROFILE(SMBwriteX);
2675 return ERROR_DOS(ERRDOS,ERRlock);
2678 /* X/Open SMB protocol says that, unlike SMBwrite
2679 if the length is zero then NO truncation is
2680 done, just a write of zero. To truncate a file,
2681 use SMBwrite. */
2683 if(numtowrite == 0)
2684 nwritten = 0;
2685 else
2686 nwritten = write_file(fsp,data,startpos,numtowrite);
2688 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2689 END_PROFILE(SMBwriteX);
2690 return(UNIXERROR(ERRHRD,ERRdiskfull));
2693 set_message(outbuf,6,0,True);
2695 SSVAL(outbuf,smb_vwv2,nwritten);
2696 if (large_writeX)
2697 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2699 if (nwritten < (ssize_t)numtowrite) {
2700 SCVAL(outbuf,smb_rcls,ERRHRD);
2701 SSVAL(outbuf,smb_err,ERRdiskfull);
2704 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2705 fsp->fnum, (int)numtowrite, (int)nwritten));
2707 if (lp_syncalways(SNUM(conn)) || write_through)
2708 sync_file(conn,fsp);
2710 END_PROFILE(SMBwriteX);
2711 return chain_reply(inbuf,outbuf,length,bufsize);
2714 /****************************************************************************
2715 Reply to a lseek.
2716 ****************************************************************************/
2718 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2720 SMB_OFF_T startpos;
2721 SMB_OFF_T res= -1;
2722 int mode,umode;
2723 int outsize = 0;
2724 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2725 START_PROFILE(SMBlseek);
2727 CHECK_FSP(fsp,conn);
2729 flush_write_cache(fsp, SEEK_FLUSH);
2731 mode = SVAL(inbuf,smb_vwv1) & 3;
2732 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
2733 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
2735 switch (mode) {
2736 case 0:
2737 umode = SEEK_SET;
2738 res = startpos;
2739 break;
2740 case 1:
2741 umode = SEEK_CUR;
2742 res = fsp->pos + startpos;
2743 break;
2744 case 2:
2745 umode = SEEK_END;
2746 break;
2747 default:
2748 umode = SEEK_SET;
2749 res = startpos;
2750 break;
2753 if (umode == SEEK_END) {
2754 if((res = SMB_VFS_LSEEK(fsp,fsp->fd,startpos,umode)) == -1) {
2755 if(errno == EINVAL) {
2756 SMB_OFF_T current_pos = startpos;
2757 SMB_STRUCT_STAT sbuf;
2759 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) {
2760 END_PROFILE(SMBlseek);
2761 return(UNIXERROR(ERRDOS,ERRnoaccess));
2764 current_pos += sbuf.st_size;
2765 if(current_pos < 0)
2766 res = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_SET);
2770 if(res == -1) {
2771 END_PROFILE(SMBlseek);
2772 return(UNIXERROR(ERRDOS,ERRnoaccess));
2776 fsp->pos = res;
2778 outsize = set_message(outbuf,2,0,True);
2779 SIVAL(outbuf,smb_vwv0,res);
2781 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2782 fsp->fnum, (double)startpos, (double)res, mode));
2784 END_PROFILE(SMBlseek);
2785 return(outsize);
2788 /****************************************************************************
2789 Reply to a flush.
2790 ****************************************************************************/
2792 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2794 int outsize = set_message(outbuf,0,0,True);
2795 uint16 fnum = SVAL(inbuf,smb_vwv0);
2796 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2797 START_PROFILE(SMBflush);
2799 if (fnum != 0xFFFF)
2800 CHECK_FSP(fsp,conn);
2802 if (!fsp) {
2803 file_sync_all(conn);
2804 } else {
2805 sync_file(conn,fsp);
2808 DEBUG(3,("flush\n"));
2809 END_PROFILE(SMBflush);
2810 return(outsize);
2813 /****************************************************************************
2814 Reply to a exit.
2815 ****************************************************************************/
2817 int reply_exit(connection_struct *conn,
2818 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2820 int outsize;
2821 START_PROFILE(SMBexit);
2823 file_close_pid(SVAL(inbuf,smb_pid));
2825 outsize = set_message(outbuf,0,0,True);
2827 DEBUG(3,("exit\n"));
2829 END_PROFILE(SMBexit);
2830 return(outsize);
2833 /****************************************************************************
2834 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2835 ****************************************************************************/
2837 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2838 int dum_buffsize)
2840 extern struct current_user current_user;
2841 int outsize = 0;
2842 time_t mtime;
2843 int32 eclass = 0, err = 0;
2844 files_struct *fsp = NULL;
2845 START_PROFILE(SMBclose);
2847 outsize = set_message(outbuf,0,0,True);
2849 /* If it's an IPC, pass off to the pipe handler. */
2850 if (IS_IPC(conn)) {
2851 END_PROFILE(SMBclose);
2852 return reply_pipe_close(conn, inbuf,outbuf);
2855 fsp = file_fsp(inbuf,smb_vwv0);
2858 * We can only use CHECK_FSP if we know it's not a directory.
2861 if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
2862 END_PROFILE(SMBclose);
2863 return ERROR_DOS(ERRDOS,ERRbadfid);
2866 if(fsp->is_directory) {
2868 * Special case - close NT SMB directory handle.
2870 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2871 close_file(fsp,True);
2872 } else {
2874 * Close ordinary file.
2876 int close_err;
2877 pstring file_name;
2879 /* Save the name for time set in close. */
2880 pstrcpy( file_name, fsp->fsp_name);
2882 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2883 fsp->fd, fsp->fnum,
2884 conn->num_files_open));
2887 * Take care of any time sent in the close.
2890 mtime = make_unix_date3(inbuf+smb_vwv1);
2891 fsp_set_pending_modtime(fsp, mtime);
2894 * close_file() returns the unix errno if an error
2895 * was detected on close - normally this is due to
2896 * a disk full error. If not then it was probably an I/O error.
2899 if((close_err = close_file(fsp,True)) != 0) {
2900 errno = close_err;
2901 END_PROFILE(SMBclose);
2902 return (UNIXERROR(ERRHRD,ERRgeneral));
2906 /* We have a cached error */
2907 if(eclass || err) {
2908 END_PROFILE(SMBclose);
2909 return ERROR_DOS(eclass,err);
2912 END_PROFILE(SMBclose);
2913 return(outsize);
2916 /****************************************************************************
2917 Reply to a writeclose (Core+ protocol).
2918 ****************************************************************************/
2920 int reply_writeclose(connection_struct *conn,
2921 char *inbuf,char *outbuf, int size, int dum_buffsize)
2923 size_t numtowrite;
2924 ssize_t nwritten = -1;
2925 int outsize = 0;
2926 int close_err = 0;
2927 SMB_OFF_T startpos;
2928 char *data;
2929 time_t mtime;
2930 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2931 START_PROFILE(SMBwriteclose);
2933 CHECK_FSP(fsp,conn);
2934 CHECK_WRITE(fsp);
2936 numtowrite = SVAL(inbuf,smb_vwv1);
2937 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2938 mtime = make_unix_date3(inbuf+smb_vwv4);
2939 data = smb_buf(inbuf) + 1;
2941 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2942 END_PROFILE(SMBwriteclose);
2943 return ERROR_DOS(ERRDOS,ERRlock);
2946 nwritten = write_file(fsp,data,startpos,numtowrite);
2948 set_filetime(conn, fsp->fsp_name,mtime);
2951 * More insanity. W2K only closes the file if writelen > 0.
2952 * JRA.
2955 if (numtowrite) {
2956 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
2957 fsp->fsp_name ));
2958 close_err = close_file(fsp,True);
2961 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2962 fsp->fnum, (int)numtowrite, (int)nwritten,
2963 conn->num_files_open));
2965 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2966 END_PROFILE(SMBwriteclose);
2967 return(UNIXERROR(ERRHRD,ERRdiskfull));
2970 if(close_err != 0) {
2971 errno = close_err;
2972 END_PROFILE(SMBwriteclose);
2973 return(UNIXERROR(ERRHRD,ERRgeneral));
2976 outsize = set_message(outbuf,1,0,True);
2978 SSVAL(outbuf,smb_vwv0,nwritten);
2979 END_PROFILE(SMBwriteclose);
2980 return(outsize);
2983 /****************************************************************************
2984 Reply to a lock.
2985 ****************************************************************************/
2987 int reply_lock(connection_struct *conn,
2988 char *inbuf,char *outbuf, int length, int dum_buffsize)
2990 int outsize = set_message(outbuf,0,0,True);
2991 SMB_BIG_UINT count,offset;
2992 NTSTATUS status;
2993 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2994 BOOL my_lock_ctx = False;
2996 START_PROFILE(SMBlock);
2998 CHECK_FSP(fsp,conn);
3000 release_level_2_oplocks_on_change(fsp);
3002 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3003 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3005 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3006 fsp->fd, fsp->fnum, (double)offset, (double)count));
3008 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &my_lock_ctx);
3009 if (NT_STATUS_V(status)) {
3010 #if 0
3011 /* Tests using Samba4 against W2K show this call never creates a blocking lock. */
3012 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
3014 * A blocking lock was requested. Package up
3015 * this smb into a queued request and push it
3016 * onto the blocking lock queue.
3018 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), offset, count)) {
3019 END_PROFILE(SMBlock);
3020 return -1;
3023 #endif
3024 END_PROFILE(SMBlock);
3025 return ERROR_NT(status);
3028 END_PROFILE(SMBlock);
3029 return(outsize);
3032 /****************************************************************************
3033 Reply to a unlock.
3034 ****************************************************************************/
3036 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
3037 int dum_buffsize)
3039 int outsize = set_message(outbuf,0,0,True);
3040 SMB_BIG_UINT count,offset;
3041 NTSTATUS status;
3042 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3043 START_PROFILE(SMBunlock);
3045 CHECK_FSP(fsp,conn);
3047 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3048 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3050 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
3051 if (NT_STATUS_V(status)) {
3052 END_PROFILE(SMBunlock);
3053 return ERROR_NT(status);
3056 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3057 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
3059 END_PROFILE(SMBunlock);
3060 return(outsize);
3063 /****************************************************************************
3064 Reply to a tdis.
3065 ****************************************************************************/
3067 int reply_tdis(connection_struct *conn,
3068 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3070 int outsize = set_message(outbuf,0,0,True);
3071 uint16 vuid;
3072 START_PROFILE(SMBtdis);
3074 vuid = SVAL(inbuf,smb_uid);
3076 if (!conn) {
3077 DEBUG(4,("Invalid connection in tdis\n"));
3078 END_PROFILE(SMBtdis);
3079 return ERROR_DOS(ERRSRV,ERRinvnid);
3082 conn->used = False;
3084 close_cnum(conn,vuid);
3086 END_PROFILE(SMBtdis);
3087 return outsize;
3090 /****************************************************************************
3091 Reply to a echo.
3092 ****************************************************************************/
3094 int reply_echo(connection_struct *conn,
3095 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3097 int smb_reverb = SVAL(inbuf,smb_vwv0);
3098 int seq_num;
3099 unsigned int data_len = smb_buflen(inbuf);
3100 int outsize = set_message(outbuf,1,data_len,True);
3101 START_PROFILE(SMBecho);
3103 if (data_len > BUFFER_SIZE) {
3104 DEBUG(0,("reply_echo: data_len too large.\n"));
3105 END_PROFILE(SMBecho);
3106 return -1;
3109 /* copy any incoming data back out */
3110 if (data_len > 0)
3111 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
3113 if (smb_reverb > 100) {
3114 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3115 smb_reverb = 100;
3118 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3119 SSVAL(outbuf,smb_vwv0,seq_num);
3121 smb_setlen(outbuf,outsize - 4);
3123 if (!send_smb(smbd_server_fd(),outbuf))
3124 exit_server("reply_echo: send_smb failed.");
3127 DEBUG(3,("echo %d times\n", smb_reverb));
3129 smb_echo_count++;
3131 END_PROFILE(SMBecho);
3132 return -1;
3135 /****************************************************************************
3136 Reply to a printopen.
3137 ****************************************************************************/
3139 int reply_printopen(connection_struct *conn,
3140 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3142 int outsize = 0;
3143 files_struct *fsp;
3144 START_PROFILE(SMBsplopen);
3146 if (!CAN_PRINT(conn)) {
3147 END_PROFILE(SMBsplopen);
3148 return ERROR_DOS(ERRDOS,ERRnoaccess);
3151 /* Open for exclusive use, write only. */
3152 fsp = print_fsp_open(conn, NULL);
3154 if (!fsp) {
3155 END_PROFILE(SMBsplopen);
3156 return(UNIXERROR(ERRDOS,ERRnoaccess));
3159 outsize = set_message(outbuf,1,0,True);
3160 SSVAL(outbuf,smb_vwv0,fsp->fnum);
3162 DEBUG(3,("openprint fd=%d fnum=%d\n",
3163 fsp->fd, fsp->fnum));
3165 END_PROFILE(SMBsplopen);
3166 return(outsize);
3169 /****************************************************************************
3170 Reply to a printclose.
3171 ****************************************************************************/
3173 int reply_printclose(connection_struct *conn,
3174 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3176 int outsize = set_message(outbuf,0,0,True);
3177 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3178 int close_err = 0;
3179 START_PROFILE(SMBsplclose);
3181 CHECK_FSP(fsp,conn);
3183 if (!CAN_PRINT(conn)) {
3184 END_PROFILE(SMBsplclose);
3185 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
3188 DEBUG(3,("printclose fd=%d fnum=%d\n",
3189 fsp->fd,fsp->fnum));
3191 close_err = close_file(fsp,True);
3193 if(close_err != 0) {
3194 errno = close_err;
3195 END_PROFILE(SMBsplclose);
3196 return(UNIXERROR(ERRHRD,ERRgeneral));
3199 END_PROFILE(SMBsplclose);
3200 return(outsize);
3203 /****************************************************************************
3204 Reply to a printqueue.
3205 ****************************************************************************/
3207 int reply_printqueue(connection_struct *conn,
3208 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3210 int outsize = set_message(outbuf,2,3,True);
3211 int max_count = SVAL(inbuf,smb_vwv0);
3212 int start_index = SVAL(inbuf,smb_vwv1);
3213 START_PROFILE(SMBsplretq);
3215 /* we used to allow the client to get the cnum wrong, but that
3216 is really quite gross and only worked when there was only
3217 one printer - I think we should now only accept it if they
3218 get it right (tridge) */
3219 if (!CAN_PRINT(conn)) {
3220 END_PROFILE(SMBsplretq);
3221 return ERROR_DOS(ERRDOS,ERRnoaccess);
3224 SSVAL(outbuf,smb_vwv0,0);
3225 SSVAL(outbuf,smb_vwv1,0);
3226 SCVAL(smb_buf(outbuf),0,1);
3227 SSVAL(smb_buf(outbuf),1,0);
3229 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3230 start_index, max_count));
3233 print_queue_struct *queue = NULL;
3234 print_status_struct status;
3235 char *p = smb_buf(outbuf) + 3;
3236 int count = print_queue_status(SNUM(conn), &queue, &status);
3237 int num_to_get = ABS(max_count);
3238 int first = (max_count>0?start_index:start_index+max_count+1);
3239 int i;
3241 if (first >= count)
3242 num_to_get = 0;
3243 else
3244 num_to_get = MIN(num_to_get,count-first);
3247 for (i=first;i<first+num_to_get;i++) {
3248 put_dos_date2(p,0,queue[i].time);
3249 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
3250 SSVAL(p,5, queue[i].job);
3251 SIVAL(p,7,queue[i].size);
3252 SCVAL(p,11,0);
3253 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
3254 p += 28;
3257 if (count > 0) {
3258 outsize = set_message(outbuf,2,28*count+3,False);
3259 SSVAL(outbuf,smb_vwv0,count);
3260 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3261 SCVAL(smb_buf(outbuf),0,1);
3262 SSVAL(smb_buf(outbuf),1,28*count);
3265 SAFE_FREE(queue);
3267 DEBUG(3,("%d entries returned in queue\n",count));
3270 END_PROFILE(SMBsplretq);
3271 return(outsize);
3274 /****************************************************************************
3275 Reply to a printwrite.
3276 ****************************************************************************/
3278 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3280 int numtowrite;
3281 int outsize = set_message(outbuf,0,0,True);
3282 char *data;
3283 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3285 START_PROFILE(SMBsplwr);
3287 if (!CAN_PRINT(conn)) {
3288 END_PROFILE(SMBsplwr);
3289 return ERROR_DOS(ERRDOS,ERRnoaccess);
3292 CHECK_FSP(fsp,conn);
3293 CHECK_WRITE(fsp);
3295 numtowrite = SVAL(smb_buf(inbuf),1);
3296 data = smb_buf(inbuf) + 3;
3298 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3299 END_PROFILE(SMBsplwr);
3300 return(UNIXERROR(ERRHRD,ERRdiskfull));
3303 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3305 END_PROFILE(SMBsplwr);
3306 return(outsize);
3309 /****************************************************************************
3310 The guts of the mkdir command, split out so it may be called by the NT SMB
3311 code.
3312 ****************************************************************************/
3314 NTSTATUS mkdir_internal(connection_struct *conn, const pstring directory, BOOL bad_path)
3316 int ret= -1;
3318 if(!CAN_WRITE(conn)) {
3319 DEBUG(5,("mkdir_internal: failing create on read-only share %s\n", lp_servicename(SNUM(conn))));
3320 errno = EACCES;
3321 return map_nt_error_from_unix(errno);
3324 /* The following 2 clauses set explicit DOS error codes. JRA. */
3325 if (ms_has_wild(directory)) {
3326 DEBUG(5,("mkdir_internal: failing create on filename %s with wildcards\n", directory));
3327 unix_ERR_class = ERRDOS;
3328 unix_ERR_code = ERRinvalidname;
3329 return NT_STATUS_OBJECT_NAME_INVALID;
3332 if( strchr_m(directory, ':')) {
3333 DEBUG(5,("mkdir_internal: failing create on filename %s with colon in name\n", directory));
3334 unix_ERR_class = ERRDOS;
3335 unix_ERR_code = ERRinvalidname;
3336 return NT_STATUS_NOT_A_DIRECTORY;
3339 if (bad_path) {
3340 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3343 if (!check_name(directory, conn)) {
3344 if(errno == ENOENT) {
3345 if (bad_path) {
3346 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3347 } else {
3348 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3351 return map_nt_error_from_unix(errno);
3354 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
3355 if (ret == -1) {
3356 if(errno == ENOENT) {
3357 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3359 return map_nt_error_from_unix(errno);
3362 return NT_STATUS_OK;
3365 /****************************************************************************
3366 Reply to a mkdir.
3367 ****************************************************************************/
3369 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3371 pstring directory;
3372 int outsize;
3373 NTSTATUS status;
3374 BOOL bad_path = False;
3375 SMB_STRUCT_STAT sbuf;
3377 START_PROFILE(SMBmkdir);
3379 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False);
3380 if (!NT_STATUS_IS_OK(status)) {
3381 END_PROFILE(SMBmkdir);
3382 return ERROR_NT(status);
3385 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
3387 unix_convert(directory,conn,0,&bad_path,&sbuf);
3389 status = mkdir_internal(conn, directory,bad_path);
3390 if (!NT_STATUS_IS_OK(status)) {
3391 END_PROFILE(SMBmkdir);
3392 return ERROR_NT(status);
3395 if (lp_inherit_owner(SNUM(conn))) {
3396 /* Ensure we're checking for a symlink here.... */
3397 /* We don't want to get caught by a symlink racer. */
3399 if(SMB_VFS_LSTAT(conn,directory, &sbuf) != 0) {
3400 END_PROFILE(SMBmkdir);
3401 return(UNIXERROR(ERRDOS,ERRnoaccess));
3404 if(!S_ISDIR(sbuf.st_mode)) {
3405 DEBUG(0,("reply_mkdir: %s is not a directory !\n", directory ));
3406 END_PROFILE(SMBmkdir);
3407 return(UNIXERROR(ERRDOS,ERRnoaccess));
3410 change_owner_to_parent(conn, NULL, directory, &sbuf);
3413 outsize = set_message(outbuf,0,0,True);
3415 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3417 END_PROFILE(SMBmkdir);
3418 return(outsize);
3421 /****************************************************************************
3422 Static function used by reply_rmdir to delete an entire directory
3423 tree recursively. Return False on ok, True on fail.
3424 ****************************************************************************/
3426 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3428 const char *dname = NULL;
3429 BOOL ret = False;
3430 long offset = 0;
3431 struct smb_Dir *dir_hnd = OpenDir(conn, directory);
3433 if(dir_hnd == NULL)
3434 return True;
3436 while((dname = ReadDirName(dir_hnd, &offset))) {
3437 pstring fullname;
3438 SMB_STRUCT_STAT st;
3440 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3441 continue;
3443 if (!is_visible_file(conn, directory, dname, &st, False))
3444 continue;
3446 /* Construct the full name. */
3447 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3448 errno = ENOMEM;
3449 ret = True;
3450 break;
3453 pstrcpy(fullname, directory);
3454 pstrcat(fullname, "/");
3455 pstrcat(fullname, dname);
3457 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
3458 ret = True;
3459 break;
3462 if(st.st_mode & S_IFDIR) {
3463 if(recursive_rmdir(conn, fullname)!=0) {
3464 ret = True;
3465 break;
3467 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
3468 ret = True;
3469 break;
3471 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
3472 ret = True;
3473 break;
3476 CloseDir(dir_hnd);
3477 return ret;
3480 /****************************************************************************
3481 The internals of the rmdir code - called elsewhere.
3482 ****************************************************************************/
3484 BOOL rmdir_internals(connection_struct *conn, char *directory)
3486 BOOL ok;
3487 SMB_STRUCT_STAT st;
3489 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3490 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3492 * Check to see if the only thing in this directory are
3493 * vetoed files/directories. If so then delete them and
3494 * retry. If we fail to delete any of them (and we *don't*
3495 * do a recursive delete) then fail the rmdir.
3497 BOOL all_veto_files = True;
3498 const char *dname;
3499 struct smb_Dir *dir_hnd = OpenDir(conn, directory);
3501 if(dir_hnd != NULL) {
3502 long dirpos = TellDir(dir_hnd);
3503 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
3504 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3505 continue;
3506 if (!is_visible_file(conn, directory, dname, &st, False))
3507 continue;
3508 if(!IS_VETO_PATH(conn, dname)) {
3509 all_veto_files = False;
3510 break;
3514 if(all_veto_files) {
3515 SeekDir(dir_hnd,dirpos);
3516 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
3517 pstring fullname;
3519 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3520 continue;
3521 if (!is_visible_file(conn, directory, dname, &st, False))
3522 continue;
3524 /* Construct the full name. */
3525 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3526 errno = ENOMEM;
3527 break;
3530 pstrcpy(fullname, directory);
3531 pstrcat(fullname, "/");
3532 pstrcat(fullname, dname);
3534 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
3535 break;
3536 if(st.st_mode & S_IFDIR) {
3537 if(lp_recursive_veto_delete(SNUM(conn))) {
3538 if(recursive_rmdir(conn, fullname) != 0)
3539 break;
3541 if(SMB_VFS_RMDIR(conn,fullname) != 0)
3542 break;
3543 } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
3544 break;
3546 CloseDir(dir_hnd);
3547 /* Retry the rmdir */
3548 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3549 } else {
3550 CloseDir(dir_hnd);
3552 } else {
3553 errno = ENOTEMPTY;
3557 if (!ok)
3558 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
3560 return ok;
3563 /****************************************************************************
3564 Reply to a rmdir.
3565 ****************************************************************************/
3567 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3569 pstring directory;
3570 int outsize = 0;
3571 BOOL ok = False;
3572 BOOL bad_path = False;
3573 SMB_STRUCT_STAT sbuf;
3574 NTSTATUS status;
3575 START_PROFILE(SMBrmdir);
3577 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False);
3578 if (!NT_STATUS_IS_OK(status)) {
3579 END_PROFILE(SMBrmdir);
3580 return ERROR_NT(status);
3583 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3585 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3586 if (bad_path) {
3587 END_PROFILE(SMBrmdir);
3588 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3591 if (check_name(directory,conn)) {
3592 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3593 ok = rmdir_internals(conn, directory);
3596 if (!ok) {
3597 END_PROFILE(SMBrmdir);
3598 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRbadpath);
3601 outsize = set_message(outbuf,0,0,True);
3603 DEBUG( 3, ( "rmdir %s\n", directory ) );
3605 END_PROFILE(SMBrmdir);
3606 return(outsize);
3609 /*******************************************************************
3610 Resolve wildcards in a filename rename.
3611 Note that name is in UNIX charset and thus potentially can be more
3612 than fstring buffer (255 bytes) especially in default UTF-8 case.
3613 Therefore, we use pstring inside and all calls should ensure that
3614 name2 is at least pstring-long (they do already)
3615 ********************************************************************/
3617 static BOOL resolve_wildcards(const char *name1, char *name2)
3619 pstring root1,root2;
3620 pstring ext1,ext2;
3621 char *p,*p2, *pname1, *pname2;
3622 int available_space, actual_space;
3625 pname1 = strrchr_m(name1,'/');
3626 pname2 = strrchr_m(name2,'/');
3628 if (!pname1 || !pname2)
3629 return(False);
3631 pstrcpy(root1,pname1);
3632 pstrcpy(root2,pname2);
3633 p = strrchr_m(root1,'.');
3634 if (p) {
3635 *p = 0;
3636 pstrcpy(ext1,p+1);
3637 } else {
3638 pstrcpy(ext1,"");
3640 p = strrchr_m(root2,'.');
3641 if (p) {
3642 *p = 0;
3643 pstrcpy(ext2,p+1);
3644 } else {
3645 pstrcpy(ext2,"");
3648 p = root1;
3649 p2 = root2;
3650 while (*p2) {
3651 if (*p2 == '?') {
3652 *p2 = *p;
3653 p2++;
3654 } else if (*p2 == '*') {
3655 pstrcpy(p2, p);
3656 break;
3657 } else {
3658 p2++;
3660 if (*p)
3661 p++;
3664 p = ext1;
3665 p2 = ext2;
3666 while (*p2) {
3667 if (*p2 == '?') {
3668 *p2 = *p;
3669 p2++;
3670 } else if (*p2 == '*') {
3671 pstrcpy(p2, p);
3672 break;
3673 } else {
3674 p2++;
3676 if (*p)
3677 p++;
3680 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
3682 if (ext2[0]) {
3683 actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
3684 if (actual_space >= available_space - 1) {
3685 DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
3686 actual_space - available_space));
3688 } else {
3689 pstrcpy_base(pname2, root2, name2);
3692 return(True);
3695 /****************************************************************************
3696 Ensure open files have their names updates.
3697 ****************************************************************************/
3699 static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode, char *newname)
3701 files_struct *fsp;
3702 BOOL did_rename = False;
3704 for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
3705 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
3706 fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
3707 fsp->fsp_name, newname ));
3708 string_set(&fsp->fsp_name, newname);
3709 did_rename = True;
3712 if (!did_rename)
3713 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
3714 (unsigned int)dev, (double)inode, newname ));
3717 /****************************************************************************
3718 Rename an open file - given an fsp.
3719 ****************************************************************************/
3721 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, uint16 attrs, BOOL replace_if_exists)
3723 SMB_STRUCT_STAT sbuf;
3724 BOOL bad_path = False;
3725 pstring newname_last_component;
3726 NTSTATUS error = NT_STATUS_OK;
3727 BOOL dest_exists;
3728 BOOL rcdest = True;
3730 ZERO_STRUCT(sbuf);
3731 rcdest = unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf);
3733 /* Quick check for "." and ".." */
3734 if (!bad_path && newname_last_component[0] == '.') {
3735 if (!newname_last_component[1] || (newname_last_component[1] == '.' && !newname_last_component[2])) {
3736 return NT_STATUS_ACCESS_DENIED;
3739 if (!rcdest && bad_path) {
3740 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3743 /* Ensure newname contains a '/' */
3744 if(strrchr_m(newname,'/') == 0) {
3745 pstring tmpstr;
3747 pstrcpy(tmpstr, "./");
3748 pstrcat(tmpstr, newname);
3749 pstrcpy(newname, tmpstr);
3753 * Check for special case with case preserving and not
3754 * case sensitive. If the old last component differs from the original
3755 * last component only by case, then we should allow
3756 * the rename (user is trying to change the case of the
3757 * filename).
3760 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
3761 strequal(newname, fsp->fsp_name)) {
3762 char *p;
3763 pstring newname_modified_last_component;
3766 * Get the last component of the modified name.
3767 * Note that we guarantee that newname contains a '/'
3768 * character above.
3770 p = strrchr_m(newname,'/');
3771 pstrcpy(newname_modified_last_component,p+1);
3773 if(strcsequal(newname_modified_last_component,
3774 newname_last_component) == False) {
3776 * Replace the modified last component with
3777 * the original.
3779 pstrcpy(p+1, newname_last_component);
3784 * If the src and dest names are identical - including case,
3785 * don't do the rename, just return success.
3788 if (strcsequal(fsp->fsp_name, newname)) {
3789 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
3790 newname));
3791 return NT_STATUS_OK;
3794 dest_exists = vfs_object_exist(conn,newname,NULL);
3796 if(!replace_if_exists && dest_exists) {
3797 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
3798 fsp->fsp_name,newname));
3799 return NT_STATUS_OBJECT_NAME_COLLISION;
3802 error = can_rename(conn,newname,attrs,&sbuf);
3804 if (dest_exists && !NT_STATUS_IS_OK(error)) {
3805 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3806 nt_errstr(error), fsp->fsp_name,newname));
3807 if (NT_STATUS_EQUAL(error,NT_STATUS_SHARING_VIOLATION))
3808 error = NT_STATUS_ACCESS_DENIED;
3809 return error;
3812 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
3813 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
3814 fsp->fsp_name,newname));
3815 rename_open_files(conn, fsp->dev, fsp->inode, newname);
3816 return NT_STATUS_OK;
3819 if (errno == ENOTDIR || errno == EISDIR)
3820 error = NT_STATUS_OBJECT_NAME_COLLISION;
3821 else
3822 error = map_nt_error_from_unix(errno);
3824 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
3825 nt_errstr(error), fsp->fsp_name,newname));
3827 return error;
3830 /****************************************************************************
3831 The guts of the rename command, split out so it may be called by the NT SMB
3832 code.
3833 ****************************************************************************/
3835 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, uint16 attrs, BOOL replace_if_exists)
3837 pstring directory;
3838 pstring mask;
3839 pstring last_component_src;
3840 pstring last_component_dest;
3841 char *p;
3842 BOOL has_wild;
3843 BOOL bad_path_src = False;
3844 BOOL bad_path_dest = False;
3845 int count=0;
3846 NTSTATUS error = NT_STATUS_OK;
3847 BOOL rc = True;
3848 BOOL rcdest = True;
3849 SMB_STRUCT_STAT sbuf1, sbuf2;
3851 *directory = *mask = 0;
3853 ZERO_STRUCT(sbuf1);
3854 ZERO_STRUCT(sbuf2);
3856 rc = unix_convert(name,conn,last_component_src,&bad_path_src,&sbuf1);
3857 if (!rc && bad_path_src) {
3858 if (ms_has_wild(last_component_src))
3859 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3860 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3863 /* Quick check for "." and ".." */
3864 if (last_component_src[0] == '.') {
3865 if (!last_component_src[1] || (last_component_src[1] == '.' && !last_component_src[2])) {
3866 return NT_STATUS_OBJECT_NAME_INVALID;
3870 rcdest = unix_convert(newname,conn,last_component_dest,&bad_path_dest,&sbuf2);
3872 /* Quick check for "." and ".." */
3873 if (last_component_dest[0] == '.') {
3874 if (!last_component_dest[1] || (last_component_dest[1] == '.' && !last_component_dest[2])) {
3875 return NT_STATUS_OBJECT_NAME_INVALID;
3880 * Split the old name into directory and last component
3881 * strings. Note that unix_convert may have stripped off a
3882 * leading ./ from both name and newname if the rename is
3883 * at the root of the share. We need to make sure either both
3884 * name and newname contain a / character or neither of them do
3885 * as this is checked in resolve_wildcards().
3888 p = strrchr_m(name,'/');
3889 if (!p) {
3890 pstrcpy(directory,".");
3891 pstrcpy(mask,name);
3892 } else {
3893 *p = 0;
3894 pstrcpy(directory,name);
3895 pstrcpy(mask,p+1);
3896 *p = '/'; /* Replace needed for exceptional test below. */
3900 * We should only check the mangled cache
3901 * here if unix_convert failed. This means
3902 * that the path in 'mask' doesn't exist
3903 * on the file system and so we need to look
3904 * for a possible mangle. This patch from
3905 * Tine Smukavec <valentin.smukavec@hermes.si>.
3908 if (!rc && mangle_is_mangled(mask))
3909 mangle_check_cache( mask, sizeof(pstring)-1 );
3911 has_wild = ms_has_wild(mask);
3913 if (!has_wild) {
3915 * No wildcards - just process the one file.
3917 BOOL is_short_name = mangle_is_8_3(name, True);
3919 /* Add a terminating '/' to the directory name. */
3920 pstrcat(directory,"/");
3921 pstrcat(directory,mask);
3923 /* Ensure newname contains a '/' also */
3924 if(strrchr_m(newname,'/') == 0) {
3925 pstring tmpstr;
3927 pstrcpy(tmpstr, "./");
3928 pstrcat(tmpstr, newname);
3929 pstrcpy(newname, tmpstr);
3932 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
3933 directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
3934 conn->case_sensitive, conn->case_preserve, conn->short_case_preserve, directory,
3935 newname, last_component_dest, is_short_name));
3938 * Check for special case with case preserving and not
3939 * case sensitive, if directory and newname are identical,
3940 * and the old last component differs from the original
3941 * last component only by case, then we should allow
3942 * the rename (user is trying to change the case of the
3943 * filename).
3945 if((conn->case_sensitive == False) &&
3946 (((conn->case_preserve == True) &&
3947 (is_short_name == False)) ||
3948 ((conn->short_case_preserve == True) &&
3949 (is_short_name == True))) &&
3950 strcsequal(directory, newname)) {
3951 pstring modified_last_component;
3954 * Get the last component of the modified name.
3955 * Note that we guarantee that newname contains a '/'
3956 * character above.
3958 p = strrchr_m(newname,'/');
3959 pstrcpy(modified_last_component,p+1);
3961 if(strcsequal(modified_last_component,
3962 last_component_dest) == False) {
3964 * Replace the modified last component with
3965 * the original.
3967 pstrcpy(p+1, last_component_dest);
3971 resolve_wildcards(directory,newname);
3974 * The source object must exist.
3977 if (!vfs_object_exist(conn, directory, &sbuf1)) {
3978 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
3979 directory,newname));
3981 if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
3983 * Must return different errors depending on whether the parent
3984 * directory existed or not.
3987 p = strrchr_m(directory, '/');
3988 if (!p)
3989 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3990 *p = '\0';
3991 if (vfs_object_exist(conn, directory, NULL))
3992 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3993 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3995 error = map_nt_error_from_unix(errno);
3996 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3997 nt_errstr(error), directory,newname));
3999 return error;
4002 if (!rcdest && bad_path_dest) {
4003 if (ms_has_wild(last_component_dest))
4004 return NT_STATUS_OBJECT_NAME_INVALID;
4005 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4008 error = can_rename(conn,directory,attrs,&sbuf1);
4010 if (!NT_STATUS_IS_OK(error)) {
4011 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4012 nt_errstr(error), directory,newname));
4013 return error;
4017 * If the src and dest names are identical - including case,
4018 * don't do the rename, just return success.
4021 if (strcsequal(directory, newname)) {
4022 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4023 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
4024 return NT_STATUS_OK;
4027 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
4028 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
4029 directory,newname));
4030 return NT_STATUS_OBJECT_NAME_COLLISION;
4033 if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
4034 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
4035 directory,newname));
4036 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4037 return NT_STATUS_OK;
4040 if (errno == ENOTDIR || errno == EISDIR)
4041 error = NT_STATUS_OBJECT_NAME_COLLISION;
4042 else
4043 error = map_nt_error_from_unix(errno);
4045 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4046 nt_errstr(error), directory,newname));
4048 return error;
4049 } else {
4051 * Wildcards - process each file that matches.
4053 struct smb_Dir *dir_hnd = NULL;
4054 const char *dname;
4055 pstring destname;
4057 if (check_name(directory,conn))
4058 dir_hnd = OpenDir(conn, directory);
4060 if (dir_hnd) {
4061 long offset = 0;
4062 error = NT_STATUS_NO_SUCH_FILE;
4063 /* Was error = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */
4065 if (strequal(mask,"????????.???"))
4066 pstrcpy(mask,"*");
4068 while ((dname = ReadDirName(dir_hnd, &offset))) {
4069 pstring fname;
4070 BOOL sysdir_entry = False;
4072 pstrcpy(fname,dname);
4074 /* Quick check for "." and ".." */
4075 if (fname[0] == '.') {
4076 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
4077 if (attrs & aDIR) {
4078 sysdir_entry = True;
4079 } else {
4080 continue;
4085 if (!is_visible_file(conn, directory, dname, &sbuf1, False))
4086 continue;
4088 if(!mask_match(fname, mask, conn->case_sensitive))
4089 continue;
4091 if (sysdir_entry) {
4092 error = NT_STATUS_OBJECT_NAME_INVALID;
4093 break;
4096 error = NT_STATUS_ACCESS_DENIED;
4097 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
4098 if (!vfs_object_exist(conn, fname, &sbuf1)) {
4099 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4100 DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
4101 continue;
4103 error = can_rename(conn,fname,attrs,&sbuf1);
4104 if (!NT_STATUS_IS_OK(error)) {
4105 DEBUG(6,("rename %s refused\n", fname));
4106 continue;
4108 pstrcpy(destname,newname);
4110 if (!resolve_wildcards(fname,destname)) {
4111 DEBUG(6,("resolve_wildcards %s %s failed\n",
4112 fname, destname));
4113 continue;
4116 if (strcsequal(fname,destname)) {
4117 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4118 DEBUG(3,("rename_internals: identical names in wildcard rename %s - success\n", fname));
4119 count++;
4120 error = NT_STATUS_OK;
4121 continue;
4124 if (!replace_if_exists &&
4125 vfs_file_exist(conn,destname, NULL)) {
4126 DEBUG(6,("file_exist %s\n", destname));
4127 error = NT_STATUS_OBJECT_NAME_COLLISION;
4128 continue;
4131 if (!SMB_VFS_RENAME(conn,fname,destname)) {
4132 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4133 count++;
4134 error = NT_STATUS_OK;
4136 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
4138 CloseDir(dir_hnd);
4141 if (!NT_STATUS_EQUAL(error,NT_STATUS_NO_SUCH_FILE)) {
4142 if (!rcdest && bad_path_dest) {
4143 if (ms_has_wild(last_component_dest))
4144 return NT_STATUS_OBJECT_NAME_INVALID;
4145 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4150 if (count == 0 && NT_STATUS_IS_OK(error)) {
4151 error = map_nt_error_from_unix(errno);
4154 return error;
4157 /****************************************************************************
4158 Reply to a mv.
4159 ****************************************************************************/
4161 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
4162 int dum_buffsize)
4164 int outsize = 0;
4165 pstring name;
4166 pstring newname;
4167 char *p;
4168 uint16 attrs = SVAL(inbuf,smb_vwv0);
4169 NTSTATUS status;
4171 START_PROFILE(SMBmv);
4173 p = smb_buf(inbuf) + 1;
4174 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True);
4175 if (!NT_STATUS_IS_OK(status)) {
4176 END_PROFILE(SMBmv);
4177 return ERROR_NT(status);
4179 p++;
4180 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True);
4181 if (!NT_STATUS_IS_OK(status)) {
4182 END_PROFILE(SMBmv);
4183 return ERROR_NT(status);
4186 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
4187 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4189 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
4191 status = rename_internals(conn, name, newname, attrs, False);
4192 if (!NT_STATUS_IS_OK(status)) {
4193 END_PROFILE(SMBmv);
4194 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4195 /* We have re-scheduled this call. */
4196 clear_cached_errors();
4197 return -1;
4199 return ERROR_NT(status);
4203 * Win2k needs a changenotify request response before it will
4204 * update after a rename..
4206 process_pending_change_notify_queue((time_t)0);
4207 outsize = set_message(outbuf,0,0,True);
4209 END_PROFILE(SMBmv);
4210 return(outsize);
4213 /*******************************************************************
4214 Copy a file as part of a reply_copy.
4215 ******************************************************************/
4217 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
4218 int count,BOOL target_is_directory, int *err_ret)
4220 int Access,action;
4221 SMB_STRUCT_STAT src_sbuf, sbuf2;
4222 SMB_OFF_T ret=-1;
4223 files_struct *fsp1,*fsp2;
4224 pstring dest;
4225 uint32 dosattrs;
4227 *err_ret = 0;
4229 pstrcpy(dest,dest1);
4230 if (target_is_directory) {
4231 char *p = strrchr_m(src,'/');
4232 if (p)
4233 p++;
4234 else
4235 p = src;
4236 pstrcat(dest,"/");
4237 pstrcat(dest,p);
4240 if (!vfs_file_exist(conn,src,&src_sbuf))
4241 return(False);
4243 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
4244 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),FILE_ATTRIBUTE_NORMAL,INTERNAL_OPEN_ONLY,
4245 &Access,&action);
4247 if (!fsp1)
4248 return(False);
4250 if (!target_is_directory && count)
4251 ofun = FILE_EXISTS_OPEN;
4253 dosattrs = dos_mode(conn, src, &src_sbuf);
4254 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1)
4255 ZERO_STRUCTP(&sbuf2);
4257 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
4258 ofun,dosattrs,INTERNAL_OPEN_ONLY,&Access,&action);
4260 if (!fsp2) {
4261 close_file(fsp1,False);
4262 return(False);
4265 if ((ofun&3) == 1) {
4266 if(SMB_VFS_LSEEK(fsp2,fsp2->fd,0,SEEK_END) == -1) {
4267 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
4269 * Stop the copy from occurring.
4271 ret = -1;
4272 src_sbuf.st_size = 0;
4276 if (src_sbuf.st_size)
4277 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
4279 close_file(fsp1,False);
4281 /* Ensure the modtime is set correctly on the destination file. */
4282 fsp_set_pending_modtime( fsp2, src_sbuf.st_mtime);
4285 * As we are opening fsp1 read-only we only expect
4286 * an error on close on fsp2 if we are out of space.
4287 * Thus we don't look at the error return from the
4288 * close of fsp1.
4290 *err_ret = close_file(fsp2,False);
4292 return(ret == (SMB_OFF_T)src_sbuf.st_size);
4295 /****************************************************************************
4296 Reply to a file copy.
4297 ****************************************************************************/
4299 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4301 int outsize = 0;
4302 pstring name;
4303 pstring directory;
4304 pstring mask,newname;
4305 char *p;
4306 int count=0;
4307 int error = ERRnoaccess;
4308 int err = 0;
4309 BOOL has_wild;
4310 BOOL exists=False;
4311 int tid2 = SVAL(inbuf,smb_vwv0);
4312 int ofun = SVAL(inbuf,smb_vwv1);
4313 int flags = SVAL(inbuf,smb_vwv2);
4314 BOOL target_is_directory=False;
4315 BOOL bad_path1 = False;
4316 BOOL bad_path2 = False;
4317 BOOL rc = True;
4318 SMB_STRUCT_STAT sbuf1, sbuf2;
4319 NTSTATUS status;
4321 START_PROFILE(SMBcopy);
4323 *directory = *mask = 0;
4325 p = smb_buf(inbuf);
4326 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True);
4327 if (!NT_STATUS_IS_OK(status)) {
4328 END_PROFILE(SMBcopy);
4329 return ERROR_NT(status);
4331 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True);
4332 if (!NT_STATUS_IS_OK(status)) {
4333 END_PROFILE(SMBcopy);
4334 return ERROR_NT(status);
4337 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
4339 if (tid2 != conn->cnum) {
4340 /* can't currently handle inter share copies XXXX */
4341 DEBUG(3,("Rejecting inter-share copy\n"));
4342 END_PROFILE(SMBcopy);
4343 return ERROR_DOS(ERRSRV,ERRinvdevice);
4346 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
4347 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4349 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
4350 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
4352 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
4354 if ((flags&1) && target_is_directory) {
4355 END_PROFILE(SMBcopy);
4356 return ERROR_DOS(ERRDOS,ERRbadfile);
4359 if ((flags&2) && !target_is_directory) {
4360 END_PROFILE(SMBcopy);
4361 return ERROR_DOS(ERRDOS,ERRbadpath);
4364 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
4365 /* wants a tree copy! XXXX */
4366 DEBUG(3,("Rejecting tree copy\n"));
4367 END_PROFILE(SMBcopy);
4368 return ERROR_DOS(ERRSRV,ERRerror);
4371 p = strrchr_m(name,'/');
4372 if (!p) {
4373 pstrcpy(directory,"./");
4374 pstrcpy(mask,name);
4375 } else {
4376 *p = 0;
4377 pstrcpy(directory,name);
4378 pstrcpy(mask,p+1);
4382 * We should only check the mangled cache
4383 * here if unix_convert failed. This means
4384 * that the path in 'mask' doesn't exist
4385 * on the file system and so we need to look
4386 * for a possible mangle. This patch from
4387 * Tine Smukavec <valentin.smukavec@hermes.si>.
4390 if (!rc && mangle_is_mangled(mask))
4391 mangle_check_cache( mask, sizeof(pstring)-1 );
4393 has_wild = ms_has_wild(mask);
4395 if (!has_wild) {
4396 pstrcat(directory,"/");
4397 pstrcat(directory,mask);
4398 if (resolve_wildcards(directory,newname) &&
4399 copy_file(directory,newname,conn,ofun, count,target_is_directory,&err))
4400 count++;
4401 if(!count && err) {
4402 errno = err;
4403 END_PROFILE(SMBcopy);
4404 return(UNIXERROR(ERRHRD,ERRgeneral));
4406 if (!count) {
4407 exists = vfs_file_exist(conn,directory,NULL);
4409 } else {
4410 struct smb_Dir *dir_hnd = NULL;
4411 const char *dname;
4412 pstring destname;
4414 if (check_name(directory,conn))
4415 dir_hnd = OpenDir(conn, directory);
4417 if (dir_hnd) {
4418 long offset = 0;
4419 error = ERRbadfile;
4421 if (strequal(mask,"????????.???"))
4422 pstrcpy(mask,"*");
4424 while ((dname = ReadDirName(dir_hnd, &offset))) {
4425 pstring fname;
4426 pstrcpy(fname,dname);
4428 if (!is_visible_file(conn, directory, dname, &sbuf1, False))
4429 continue;
4431 if(!mask_match(fname, mask, conn->case_sensitive))
4432 continue;
4434 error = ERRnoaccess;
4435 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
4436 pstrcpy(destname,newname);
4437 if (resolve_wildcards(fname,destname) &&
4438 copy_file(fname,destname,conn,ofun,
4439 count,target_is_directory,&err))
4440 count++;
4441 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
4443 CloseDir(dir_hnd);
4447 if (count == 0) {
4448 if(err) {
4449 /* Error on close... */
4450 errno = err;
4451 END_PROFILE(SMBcopy);
4452 return(UNIXERROR(ERRHRD,ERRgeneral));
4455 if (exists) {
4456 END_PROFILE(SMBcopy);
4457 return ERROR_DOS(ERRDOS,error);
4458 } else {
4459 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
4460 unix_ERR_class = ERRDOS;
4461 unix_ERR_code = ERRbadpath;
4463 END_PROFILE(SMBcopy);
4464 return(UNIXERROR(ERRDOS,error));
4468 outsize = set_message(outbuf,1,0,True);
4469 SSVAL(outbuf,smb_vwv0,count);
4471 END_PROFILE(SMBcopy);
4472 return(outsize);
4475 /****************************************************************************
4476 Reply to a setdir.
4477 ****************************************************************************/
4479 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4481 int snum;
4482 int outsize = 0;
4483 BOOL ok = False;
4484 pstring newdir;
4485 NTSTATUS status;
4487 START_PROFILE(pathworks_setdir);
4489 snum = SNUM(conn);
4490 if (!CAN_SETDIR(snum)) {
4491 END_PROFILE(pathworks_setdir);
4492 return ERROR_DOS(ERRDOS,ERRnoaccess);
4495 srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status, False);
4496 if (!NT_STATUS_IS_OK(status)) {
4497 END_PROFILE(pathworks_setdir);
4498 return ERROR_NT(status);
4501 RESOLVE_DFSPATH(newdir, conn, inbuf, outbuf);
4503 if (strlen(newdir) == 0) {
4504 ok = True;
4505 } else {
4506 ok = vfs_directory_exist(conn,newdir,NULL);
4507 if (ok)
4508 string_set(&conn->connectpath,newdir);
4511 if (!ok) {
4512 END_PROFILE(pathworks_setdir);
4513 return ERROR_DOS(ERRDOS,ERRbadpath);
4516 outsize = set_message(outbuf,0,0,True);
4517 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
4519 DEBUG(3,("setdir %s\n", newdir));
4521 END_PROFILE(pathworks_setdir);
4522 return(outsize);
4525 /****************************************************************************
4526 Get a lock pid, dealing with large count requests.
4527 ****************************************************************************/
4529 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
4531 if(!large_file_format)
4532 return SVAL(data,SMB_LPID_OFFSET(data_offset));
4533 else
4534 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
4537 /****************************************************************************
4538 Get a lock count, dealing with large count requests.
4539 ****************************************************************************/
4541 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4543 SMB_BIG_UINT count = 0;
4545 if(!large_file_format) {
4546 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4547 } else {
4549 #if defined(HAVE_LONGLONG)
4550 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4551 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4552 #else /* HAVE_LONGLONG */
4555 * NT4.x seems to be broken in that it sends large file (64 bit)
4556 * lockingX calls even if the CAP_LARGE_FILES was *not*
4557 * negotiated. For boxes without large unsigned ints truncate the
4558 * lock count by dropping the top 32 bits.
4561 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4562 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4563 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4564 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4565 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4568 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4569 #endif /* HAVE_LONGLONG */
4572 return count;
4575 #if !defined(HAVE_LONGLONG)
4576 /****************************************************************************
4577 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
4578 ****************************************************************************/
4580 static uint32 map_lock_offset(uint32 high, uint32 low)
4582 unsigned int i;
4583 uint32 mask = 0;
4584 uint32 highcopy = high;
4587 * Try and find out how many significant bits there are in high.
4590 for(i = 0; highcopy; i++)
4591 highcopy >>= 1;
4594 * We use 31 bits not 32 here as POSIX
4595 * lock offsets may not be negative.
4598 mask = (~0) << (31 - i);
4600 if(low & mask)
4601 return 0; /* Fail. */
4603 high <<= (31 - i);
4605 return (high|low);
4607 #endif /* !defined(HAVE_LONGLONG) */
4609 /****************************************************************************
4610 Get a lock offset, dealing with large offset requests.
4611 ****************************************************************************/
4613 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4615 SMB_BIG_UINT offset = 0;
4617 *err = False;
4619 if(!large_file_format) {
4620 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4621 } else {
4623 #if defined(HAVE_LONGLONG)
4624 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4625 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4626 #else /* HAVE_LONGLONG */
4629 * NT4.x seems to be broken in that it sends large file (64 bit)
4630 * lockingX calls even if the CAP_LARGE_FILES was *not*
4631 * negotiated. For boxes without large unsigned ints mangle the
4632 * lock offset by mapping the top 32 bits onto the lower 32.
4635 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4636 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4637 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4638 uint32 new_low = 0;
4640 if((new_low = map_lock_offset(high, low)) == 0) {
4641 *err = True;
4642 return (SMB_BIG_UINT)-1;
4645 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4646 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4647 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4648 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4651 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4652 #endif /* HAVE_LONGLONG */
4655 return offset;
4658 /****************************************************************************
4659 Reply to a lockingX request.
4660 ****************************************************************************/
4662 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4664 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4665 unsigned char locktype = CVAL(inbuf,smb_vwv3);
4666 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4667 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4668 uint16 num_locks = SVAL(inbuf,smb_vwv7);
4669 SMB_BIG_UINT count = 0, offset = 0;
4670 uint16 lock_pid;
4671 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4672 int i;
4673 char *data;
4674 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4675 BOOL err;
4676 BOOL my_lock_ctx = False;
4677 NTSTATUS status;
4679 START_PROFILE(SMBlockingX);
4681 CHECK_FSP(fsp,conn);
4683 data = smb_buf(inbuf);
4685 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
4686 /* we don't support these - and CANCEL_LOCK makes w2k
4687 and XP reboot so I don't really want to be
4688 compatible! (tridge) */
4689 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
4692 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
4693 /* Need to make this like a cancel.... JRA. */
4694 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
4697 /* Check if this is an oplock break on a file
4698 we have granted an oplock on.
4700 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
4701 /* Client can insist on breaking to none. */
4702 BOOL break_to_none = (oplocklevel == 0);
4704 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4705 (unsigned int)oplocklevel, fsp->fnum ));
4708 * Make sure we have granted an exclusive or batch oplock on this file.
4711 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
4712 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4713 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4715 /* if this is a pure oplock break request then don't send a reply */
4716 if (num_locks == 0 && num_ulocks == 0) {
4717 END_PROFILE(SMBlockingX);
4718 return -1;
4719 } else {
4720 END_PROFILE(SMBlockingX);
4721 return ERROR_DOS(ERRDOS,ERRlock);
4725 if (remove_oplock(fsp, break_to_none) == False) {
4726 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4727 fsp->fsp_name ));
4730 /* if this is a pure oplock break request then don't send a reply */
4731 if (num_locks == 0 && num_ulocks == 0) {
4732 /* Sanity check - ensure a pure oplock break is not a
4733 chained request. */
4734 if(CVAL(inbuf,smb_vwv0) != 0xff)
4735 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4736 (unsigned int)CVAL(inbuf,smb_vwv0) ));
4737 END_PROFILE(SMBlockingX);
4738 return -1;
4743 * We do this check *after* we have checked this is not a oplock break
4744 * response message. JRA.
4747 release_level_2_oplocks_on_change(fsp);
4749 /* Data now points at the beginning of the list
4750 of smb_unlkrng structs */
4751 for(i = 0; i < (int)num_ulocks; i++) {
4752 lock_pid = get_lock_pid( data, i, large_file_format);
4753 count = get_lock_count( data, i, large_file_format);
4754 offset = get_lock_offset( data, i, large_file_format, &err);
4757 * There is no error code marked "stupid client bug".... :-).
4759 if(err) {
4760 END_PROFILE(SMBlockingX);
4761 return ERROR_DOS(ERRDOS,ERRnoaccess);
4764 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4765 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4767 status = do_unlock(fsp,conn,lock_pid,count,offset);
4768 if (NT_STATUS_V(status)) {
4769 END_PROFILE(SMBlockingX);
4770 return ERROR_NT(status);
4774 /* Setup the timeout in seconds. */
4776 lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000);
4778 /* Now do any requested locks */
4779 data += ((large_file_format ? 20 : 10)*num_ulocks);
4781 /* Data now points at the beginning of the list
4782 of smb_lkrng structs */
4784 for(i = 0; i < (int)num_locks; i++) {
4785 lock_pid = get_lock_pid( data, i, large_file_format);
4786 count = get_lock_count( data, i, large_file_format);
4787 offset = get_lock_offset( data, i, large_file_format, &err);
4790 * There is no error code marked "stupid client bug".... :-).
4792 if(err) {
4793 END_PROFILE(SMBlockingX);
4794 return ERROR_DOS(ERRDOS,ERRnoaccess);
4797 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
4798 (double)offset, (double)count, (unsigned int)lock_pid,
4799 fsp->fsp_name, (int)lock_timeout ));
4801 status = do_lock_spin(fsp,conn,lock_pid, count,offset,
4802 ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &my_lock_ctx);
4803 if (NT_STATUS_V(status)) {
4805 * Interesting fact found by IFSTEST /t LockOverlappedTest...
4806 * Even if it's our own lock context, we need to wait here as
4807 * there may be an unlock on the way.
4808 * So I removed a "&& !my_lock_ctx" from the following
4809 * if statement. JRA.
4811 if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
4813 * A blocking lock was requested. Package up
4814 * this smb into a queued request and push it
4815 * onto the blocking lock queue.
4817 if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) {
4818 END_PROFILE(SMBlockingX);
4819 return -1;
4822 break;
4826 /* If any of the above locks failed, then we must unlock
4827 all of the previous locks (X/Open spec). */
4828 if (i != num_locks && num_locks != 0) {
4830 * Ensure we don't do a remove on the lock that just failed,
4831 * as under POSIX rules, if we have a lock already there, we
4832 * will delete it (and we shouldn't) .....
4834 for(i--; i >= 0; i--) {
4835 lock_pid = get_lock_pid( data, i, large_file_format);
4836 count = get_lock_count( data, i, large_file_format);
4837 offset = get_lock_offset( data, i, large_file_format, &err);
4840 * There is no error code marked "stupid client bug".... :-).
4842 if(err) {
4843 END_PROFILE(SMBlockingX);
4844 return ERROR_DOS(ERRDOS,ERRnoaccess);
4847 do_unlock(fsp,conn,lock_pid,count,offset);
4849 END_PROFILE(SMBlockingX);
4850 return ERROR_NT(status);
4853 set_message(outbuf,2,0,True);
4855 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4856 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4858 END_PROFILE(SMBlockingX);
4859 return chain_reply(inbuf,outbuf,length,bufsize);
4862 /****************************************************************************
4863 Reply to a SMBreadbmpx (read block multiplex) request.
4864 ****************************************************************************/
4866 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4868 ssize_t nread = -1;
4869 ssize_t total_read;
4870 char *data;
4871 SMB_OFF_T startpos;
4872 int outsize;
4873 size_t maxcount;
4874 int max_per_packet;
4875 size_t tcount;
4876 int pad;
4877 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4878 START_PROFILE(SMBreadBmpx);
4880 /* this function doesn't seem to work - disable by default */
4881 if (!lp_readbmpx()) {
4882 END_PROFILE(SMBreadBmpx);
4883 return ERROR_DOS(ERRSRV,ERRuseSTD);
4886 outsize = set_message(outbuf,8,0,True);
4888 CHECK_FSP(fsp,conn);
4889 CHECK_READ(fsp);
4891 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
4892 maxcount = SVAL(inbuf,smb_vwv3);
4894 data = smb_buf(outbuf);
4895 pad = ((long)data)%4;
4896 if (pad)
4897 pad = 4 - pad;
4898 data += pad;
4900 max_per_packet = bufsize-(outsize+pad);
4901 tcount = maxcount;
4902 total_read = 0;
4904 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
4905 END_PROFILE(SMBreadBmpx);
4906 return ERROR_DOS(ERRDOS,ERRlock);
4909 do {
4910 size_t N = MIN(max_per_packet,tcount-total_read);
4912 nread = read_file(fsp,data,startpos,N);
4914 if (nread <= 0)
4915 nread = 0;
4917 if (nread < (ssize_t)N)
4918 tcount = total_read + nread;
4920 set_message(outbuf,8,nread,False);
4921 SIVAL(outbuf,smb_vwv0,startpos);
4922 SSVAL(outbuf,smb_vwv2,tcount);
4923 SSVAL(outbuf,smb_vwv6,nread);
4924 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4926 if (!send_smb(smbd_server_fd(),outbuf))
4927 exit_server("reply_readbmpx: send_smb failed.");
4929 total_read += nread;
4930 startpos += nread;
4931 } while (total_read < (ssize_t)tcount);
4933 END_PROFILE(SMBreadBmpx);
4934 return(-1);
4937 /****************************************************************************
4938 Reply to a SMBsetattrE.
4939 ****************************************************************************/
4941 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4943 struct utimbuf unix_times;
4944 int outsize = 0;
4945 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4946 START_PROFILE(SMBsetattrE);
4948 outsize = set_message(outbuf,0,0,True);
4950 if(!fsp || (fsp->conn != conn)) {
4951 END_PROFILE(SMBgetattrE);
4952 return ERROR_DOS(ERRDOS,ERRbadfid);
4956 * Convert the DOS times into unix times. Ignore create
4957 * time as UNIX can't set this.
4960 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4961 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4964 * Patch from Ray Frush <frush@engr.colostate.edu>
4965 * Sometimes times are sent as zero - ignore them.
4968 if (null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) {
4969 /* Ignore request */
4970 if( DEBUGLVL( 3 ) ) {
4971 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4972 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4974 END_PROFILE(SMBsetattrE);
4975 return(outsize);
4976 } else if (!null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) {
4977 /* set modify time = to access time if modify time was unset */
4978 unix_times.modtime = unix_times.actime;
4981 /* Set the date on this file */
4982 /* Should we set pending modtime here ? JRA */
4983 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4984 END_PROFILE(SMBsetattrE);
4985 return ERROR_DOS(ERRDOS,ERRnoaccess);
4988 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4989 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4991 END_PROFILE(SMBsetattrE);
4992 return(outsize);
4996 /* Back from the dead for OS/2..... JRA. */
4998 /****************************************************************************
4999 Reply to a SMBwritebmpx (write block multiplex primary) request.
5000 ****************************************************************************/
5002 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5004 size_t numtowrite;
5005 ssize_t nwritten = -1;
5006 int outsize = 0;
5007 SMB_OFF_T startpos;
5008 size_t tcount;
5009 BOOL write_through;
5010 int smb_doff;
5011 char *data;
5012 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5013 START_PROFILE(SMBwriteBmpx);
5015 CHECK_FSP(fsp,conn);
5016 CHECK_WRITE(fsp);
5017 CHECK_ERROR(fsp);
5019 tcount = SVAL(inbuf,smb_vwv1);
5020 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
5021 write_through = BITSETW(inbuf+smb_vwv7,0);
5022 numtowrite = SVAL(inbuf,smb_vwv10);
5023 smb_doff = SVAL(inbuf,smb_vwv11);
5025 data = smb_base(inbuf) + smb_doff;
5027 /* If this fails we need to send an SMBwriteC response,
5028 not an SMBwritebmpx - set this up now so we don't forget */
5029 SCVAL(outbuf,smb_com,SMBwritec);
5031 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) {
5032 END_PROFILE(SMBwriteBmpx);
5033 return(ERROR_DOS(ERRDOS,ERRlock));
5036 nwritten = write_file(fsp,data,startpos,numtowrite);
5038 if(lp_syncalways(SNUM(conn)) || write_through)
5039 sync_file(conn,fsp);
5041 if(nwritten < (ssize_t)numtowrite) {
5042 END_PROFILE(SMBwriteBmpx);
5043 return(UNIXERROR(ERRHRD,ERRdiskfull));
5046 /* If the maximum to be written to this file
5047 is greater than what we just wrote then set
5048 up a secondary struct to be attached to this
5049 fd, we will use this to cache error messages etc. */
5051 if((ssize_t)tcount > nwritten) {
5052 write_bmpx_struct *wbms;
5053 if(fsp->wbmpx_ptr != NULL)
5054 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
5055 else
5056 wbms = SMB_MALLOC_P(write_bmpx_struct);
5057 if(!wbms) {
5058 DEBUG(0,("Out of memory in reply_readmpx\n"));
5059 END_PROFILE(SMBwriteBmpx);
5060 return(ERROR_DOS(ERRSRV,ERRnoresource));
5062 wbms->wr_mode = write_through;
5063 wbms->wr_discard = False; /* No errors yet */
5064 wbms->wr_total_written = nwritten;
5065 wbms->wr_errclass = 0;
5066 wbms->wr_error = 0;
5067 fsp->wbmpx_ptr = wbms;
5070 /* We are returning successfully, set the message type back to
5071 SMBwritebmpx */
5072 SCVAL(outbuf,smb_com,SMBwriteBmpx);
5074 outsize = set_message(outbuf,1,0,True);
5076 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
5078 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
5079 fsp->fnum, (int)numtowrite, (int)nwritten ) );
5081 if (write_through && tcount==nwritten) {
5082 /* We need to send both a primary and a secondary response */
5083 smb_setlen(outbuf,outsize - 4);
5084 if (!send_smb(smbd_server_fd(),outbuf))
5085 exit_server("reply_writebmpx: send_smb failed.");
5087 /* Now the secondary */
5088 outsize = set_message(outbuf,1,0,True);
5089 SCVAL(outbuf,smb_com,SMBwritec);
5090 SSVAL(outbuf,smb_vwv0,nwritten);
5093 END_PROFILE(SMBwriteBmpx);
5094 return(outsize);
5097 /****************************************************************************
5098 Reply to a SMBwritebs (write block multiplex secondary) request.
5099 ****************************************************************************/
5101 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5103 size_t numtowrite;
5104 ssize_t nwritten = -1;
5105 int outsize = 0;
5106 SMB_OFF_T startpos;
5107 size_t tcount;
5108 BOOL write_through;
5109 int smb_doff;
5110 char *data;
5111 write_bmpx_struct *wbms;
5112 BOOL send_response = False;
5113 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5114 START_PROFILE(SMBwriteBs);
5116 CHECK_FSP(fsp,conn);
5117 CHECK_WRITE(fsp);
5119 tcount = SVAL(inbuf,smb_vwv1);
5120 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
5121 numtowrite = SVAL(inbuf,smb_vwv6);
5122 smb_doff = SVAL(inbuf,smb_vwv7);
5124 data = smb_base(inbuf) + smb_doff;
5126 /* We need to send an SMBwriteC response, not an SMBwritebs */
5127 SCVAL(outbuf,smb_com,SMBwritec);
5129 /* This fd should have an auxiliary struct attached,
5130 check that it does */
5131 wbms = fsp->wbmpx_ptr;
5132 if(!wbms) {
5133 END_PROFILE(SMBwriteBs);
5134 return(-1);
5137 /* If write through is set we can return errors, else we must cache them */
5138 write_through = wbms->wr_mode;
5140 /* Check for an earlier error */
5141 if(wbms->wr_discard) {
5142 END_PROFILE(SMBwriteBs);
5143 return -1; /* Just discard the packet */
5146 nwritten = write_file(fsp,data,startpos,numtowrite);
5148 if(lp_syncalways(SNUM(conn)) || write_through)
5149 sync_file(conn,fsp);
5151 if (nwritten < (ssize_t)numtowrite) {
5152 if(write_through) {
5153 /* We are returning an error - we can delete the aux struct */
5154 if (wbms)
5155 free((char *)wbms);
5156 fsp->wbmpx_ptr = NULL;
5157 END_PROFILE(SMBwriteBs);
5158 return(ERROR_DOS(ERRHRD,ERRdiskfull));
5160 END_PROFILE(SMBwriteBs);
5161 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
5164 /* Increment the total written, if this matches tcount
5165 we can discard the auxiliary struct (hurrah !) and return a writeC */
5166 wbms->wr_total_written += nwritten;
5167 if(wbms->wr_total_written >= tcount) {
5168 if (write_through) {
5169 outsize = set_message(outbuf,1,0,True);
5170 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
5171 send_response = True;
5174 free((char *)wbms);
5175 fsp->wbmpx_ptr = NULL;
5178 if(send_response) {
5179 END_PROFILE(SMBwriteBs);
5180 return(outsize);
5183 END_PROFILE(SMBwriteBs);
5184 return(-1);
5187 /****************************************************************************
5188 Reply to a SMBgetattrE.
5189 ****************************************************************************/
5191 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5193 SMB_STRUCT_STAT sbuf;
5194 int outsize = 0;
5195 int mode;
5196 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5197 START_PROFILE(SMBgetattrE);
5199 outsize = set_message(outbuf,11,0,True);
5201 if(!fsp || (fsp->conn != conn)) {
5202 END_PROFILE(SMBgetattrE);
5203 return ERROR_DOS(ERRDOS,ERRbadfid);
5206 /* Do an fstat on this file */
5207 if(fsp_stat(fsp, &sbuf)) {
5208 END_PROFILE(SMBgetattrE);
5209 return(UNIXERROR(ERRDOS,ERRnoaccess));
5212 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
5215 * Convert the times into dos times. Set create
5216 * date to be last modify date as UNIX doesn't save
5217 * this.
5220 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
5221 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
5222 /* Should we check pending modtime here ? JRA */
5223 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
5225 if (mode & aDIR) {
5226 SIVAL(outbuf,smb_vwv6,0);
5227 SIVAL(outbuf,smb_vwv8,0);
5228 } else {
5229 uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf);
5230 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
5231 SIVAL(outbuf,smb_vwv8,allocation_size);
5233 SSVAL(outbuf,smb_vwv10, mode);
5235 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
5237 END_PROFILE(SMBgetattrE);
5238 return(outsize);