r5739: sync for 3.0.12rc1 (current with SAMBA_3_0 r5738)
[Samba.git] / source / smbd / reply.c
blobf149b79f793bd7a5a476c9199cd6556a972f58dd
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 unix_convert(fname,conn,0,&bad_path,&sbuf);
705 if (bad_path) {
706 END_PROFILE(SMBsetatr);
707 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
710 mode = SVAL(inbuf,smb_vwv0);
711 mtime = make_unix_date3(inbuf+smb_vwv1);
713 if (mode != FILE_ATTRIBUTE_NORMAL) {
714 if (VALID_STAT_OF_DIR(sbuf))
715 mode |= aDIR;
716 else
717 mode &= ~aDIR;
719 if (check_name(fname,conn)) {
720 ok = (file_set_dosmode(conn,fname,mode,&sbuf,False) == 0);
722 } else {
723 ok = True;
726 if (ok)
727 ok = set_filetime(conn,fname,mtime);
729 if (!ok) {
730 END_PROFILE(SMBsetatr);
731 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
734 outsize = set_message(outbuf,0,0,True);
736 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
738 END_PROFILE(SMBsetatr);
739 return(outsize);
742 /****************************************************************************
743 Reply to a dskattr.
744 ****************************************************************************/
746 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
748 int outsize = 0;
749 SMB_BIG_UINT dfree,dsize,bsize;
750 START_PROFILE(SMBdskattr);
752 SMB_VFS_DISK_FREE(conn,".",True,&bsize,&dfree,&dsize);
754 outsize = set_message(outbuf,5,0,True);
756 if (Protocol <= PROTOCOL_LANMAN2) {
757 double total_space, free_space;
758 /* we need to scale this to a number that DOS6 can handle. We
759 use floating point so we can handle large drives on systems
760 that don't have 64 bit integers
762 we end up displaying a maximum of 2G to DOS systems
764 total_space = dsize * (double)bsize;
765 free_space = dfree * (double)bsize;
767 dsize = (total_space+63*512) / (64*512);
768 dfree = (free_space+63*512) / (64*512);
770 if (dsize > 0xFFFF) dsize = 0xFFFF;
771 if (dfree > 0xFFFF) dfree = 0xFFFF;
773 SSVAL(outbuf,smb_vwv0,dsize);
774 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
775 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
776 SSVAL(outbuf,smb_vwv3,dfree);
777 } else {
778 SSVAL(outbuf,smb_vwv0,dsize);
779 SSVAL(outbuf,smb_vwv1,bsize/512);
780 SSVAL(outbuf,smb_vwv2,512);
781 SSVAL(outbuf,smb_vwv3,dfree);
784 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
786 END_PROFILE(SMBdskattr);
787 return(outsize);
790 /****************************************************************************
791 Reply to a search.
792 Can be called from SMBsearch, SMBffirst or SMBfunique.
793 ****************************************************************************/
795 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
797 pstring mask;
798 pstring directory;
799 pstring fname;
800 SMB_OFF_T size;
801 int mode;
802 time_t date;
803 int dirtype;
804 int outsize = 0;
805 unsigned int numentries = 0;
806 unsigned int maxentries = 0;
807 BOOL finished = False;
808 char *p;
809 BOOL ok = False;
810 int status_len;
811 pstring path;
812 char status[21];
813 int dptr_num= -1;
814 BOOL check_descend = False;
815 BOOL expect_close = False;
816 BOOL can_open = True;
817 BOOL bad_path = False;
818 NTSTATUS nt_status;
819 START_PROFILE(SMBsearch);
821 *mask = *directory = *fname = 0;
823 /* If we were called as SMBffirst then we must expect close. */
824 if(CVAL(inbuf,smb_com) == SMBffirst)
825 expect_close = True;
827 outsize = set_message(outbuf,1,3,True);
828 maxentries = SVAL(inbuf,smb_vwv0);
829 dirtype = SVAL(inbuf,smb_vwv1);
830 p = smb_buf(inbuf) + 1;
831 p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &nt_status, True);
832 if (!NT_STATUS_IS_OK(nt_status)) {
833 END_PROFILE(SMBsearch);
834 return ERROR_NT(nt_status);
836 p++;
837 status_len = SVAL(p, 0);
838 p += 2;
840 /* dirtype &= ~aDIR; */
842 if (status_len == 0) {
843 SMB_STRUCT_STAT sbuf;
844 pstring dir2;
846 pstrcpy(directory,path);
847 pstrcpy(dir2,path);
848 unix_convert(directory,conn,0,&bad_path,&sbuf);
849 unix_format(dir2);
851 if (!check_name(directory,conn))
852 can_open = False;
854 p = strrchr_m(dir2,'/');
855 if (p == NULL) {
856 pstrcpy(mask,dir2);
857 *dir2 = 0;
858 } else {
859 *p = 0;
860 pstrcpy(mask,p+1);
863 p = strrchr_m(directory,'/');
864 if (!p)
865 *directory = 0;
866 else
867 *p = 0;
869 if (strlen(directory) == 0)
870 pstrcpy(directory,".");
871 memset((char *)status,'\0',21);
872 SCVAL(status,0,(dirtype & 0x1F));
873 } else {
874 int status_dirtype;
876 memcpy(status,p,21);
877 status_dirtype = CVAL(status,0) & 0x1F;
878 if (status_dirtype != (dirtype & 0x1F))
879 dirtype = status_dirtype;
881 conn->dirptr = dptr_fetch(status+12,&dptr_num);
882 if (!conn->dirptr)
883 goto SearchEmpty;
884 string_set(&conn->dirpath,dptr_path(dptr_num));
885 pstrcpy(mask, dptr_wcard(dptr_num));
888 if (can_open) {
889 p = smb_buf(outbuf) + 3;
890 ok = True;
892 if (status_len == 0) {
893 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
894 if (dptr_num < 0) {
895 if(dptr_num == -2) {
896 END_PROFILE(SMBsearch);
897 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnofids);
899 END_PROFILE(SMBsearch);
900 return ERROR_DOS(ERRDOS,ERRnofids);
902 if (!dptr_set_wcard_and_attributes(dptr_num, mask, dirtype)) {
903 END_PROFILE(SMBsearch);
904 return ERROR_DOS(ERRDOS,ERRnomem);
906 } else {
907 dirtype = dptr_attr(dptr_num);
910 DEBUG(4,("dptr_num is %d\n",dptr_num));
912 if (ok) {
913 if ((dirtype&0x1F) == aVOLID) {
914 memcpy(p,status,21);
915 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
916 dptr_fill(p+12,dptr_num);
917 if (dptr_zero(p+12) && (status_len==0))
918 numentries = 1;
919 else
920 numentries = 0;
921 p += DIR_STRUCT_SIZE;
922 } else {
923 unsigned int i;
924 maxentries = MIN(maxentries, ((BUFFER_SIZE - (p - outbuf))/DIR_STRUCT_SIZE));
926 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
927 conn->dirpath,lp_dontdescend(SNUM(conn))));
928 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
929 check_descend = True;
931 for (i=numentries;(i<maxentries) && !finished;i++) {
932 finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
933 if (!finished) {
934 memcpy(p,status,21);
935 make_dir_struct(p,mask,fname,size,mode,date);
936 dptr_fill(p+12,dptr_num);
937 numentries++;
938 p += DIR_STRUCT_SIZE;
942 } /* if (ok ) */
946 SearchEmpty:
948 /* If we were called as SMBffirst with smb_search_id == NULL
949 and no entries were found then return error and close dirptr
950 (X/Open spec) */
952 if (numentries == 0 || !ok) {
953 dptr_close(&dptr_num);
954 } else if(ok && expect_close && status_len == 0) {
955 /* Close the dptr - we know it's gone */
956 dptr_close(&dptr_num);
959 /* If we were called as SMBfunique, then we can close the dirptr now ! */
960 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique) {
961 dptr_close(&dptr_num);
964 if ((numentries == 0) && !ms_has_wild(mask)) {
965 return ERROR_BOTH(STATUS_NO_MORE_FILES,ERRDOS,ERRnofiles);
968 SSVAL(outbuf,smb_vwv0,numentries);
969 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
970 SCVAL(smb_buf(outbuf),0,5);
971 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
973 if (Protocol >= PROTOCOL_NT1)
974 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
976 outsize += DIR_STRUCT_SIZE*numentries;
977 smb_setlen(outbuf,outsize - 4);
979 if ((! *directory) && dptr_path(dptr_num))
980 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
982 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
983 smb_fn_name(CVAL(inbuf,smb_com)),
984 mask, directory, dirtype, numentries, maxentries ) );
986 END_PROFILE(SMBsearch);
987 return(outsize);
990 /****************************************************************************
991 Reply to a fclose (stop directory search).
992 ****************************************************************************/
994 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
996 int outsize = 0;
997 int status_len;
998 pstring path;
999 char status[21];
1000 int dptr_num= -2;
1001 char *p;
1002 NTSTATUS err;
1004 START_PROFILE(SMBfclose);
1006 outsize = set_message(outbuf,1,0,True);
1007 p = smb_buf(inbuf) + 1;
1008 p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err, True);
1009 if (!NT_STATUS_IS_OK(err)) {
1010 END_PROFILE(SMBfclose);
1011 return ERROR_NT(err);
1013 p++;
1014 status_len = SVAL(p,0);
1015 p += 2;
1017 if (status_len == 0) {
1018 END_PROFILE(SMBfclose);
1019 return ERROR_DOS(ERRSRV,ERRsrverror);
1022 memcpy(status,p,21);
1024 if(dptr_fetch(status+12,&dptr_num)) {
1025 /* Close the dptr - we know it's gone */
1026 dptr_close(&dptr_num);
1029 SSVAL(outbuf,smb_vwv0,0);
1031 DEBUG(3,("search close\n"));
1033 END_PROFILE(SMBfclose);
1034 return(outsize);
1037 /****************************************************************************
1038 Reply to an open.
1039 ****************************************************************************/
1041 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1043 pstring fname;
1044 int outsize = 0;
1045 int fmode=0;
1046 int share_mode;
1047 SMB_OFF_T size = 0;
1048 time_t mtime=0;
1049 int rmode=0;
1050 SMB_STRUCT_STAT sbuf;
1051 BOOL bad_path = False;
1052 files_struct *fsp;
1053 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1054 uint16 dos_attr = SVAL(inbuf,smb_vwv1);
1055 NTSTATUS status;
1056 START_PROFILE(SMBopen);
1058 share_mode = SVAL(inbuf,smb_vwv0);
1060 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status, False);
1061 if (!NT_STATUS_IS_OK(status)) {
1062 END_PROFILE(SMBopen);
1063 return ERROR_NT(status);
1066 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1068 unix_convert(fname,conn,0,&bad_path,&sbuf);
1069 if (bad_path) {
1070 END_PROFILE(SMBopen);
1071 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1074 fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1075 (uint32)dos_attr, oplock_request,&rmode,NULL);
1077 if (!fsp) {
1078 END_PROFILE(SMBopen);
1079 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1080 /* We have re-scheduled this call. */
1081 clear_cached_errors();
1082 return -1;
1084 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1087 size = sbuf.st_size;
1088 fmode = dos_mode(conn,fname,&sbuf);
1089 mtime = sbuf.st_mtime;
1091 if (fmode & aDIR) {
1092 DEBUG(3,("attempt to open a directory %s\n",fname));
1093 close_file(fsp,False);
1094 END_PROFILE(SMBopen);
1095 return ERROR_DOS(ERRDOS,ERRnoaccess);
1098 outsize = set_message(outbuf,7,0,True);
1099 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1100 SSVAL(outbuf,smb_vwv1,fmode);
1101 if(lp_dos_filetime_resolution(SNUM(conn)) )
1102 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1103 else
1104 put_dos_date3(outbuf,smb_vwv2,mtime);
1105 SIVAL(outbuf,smb_vwv4,(uint32)size);
1106 SSVAL(outbuf,smb_vwv6,rmode);
1108 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1109 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1111 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1112 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1113 END_PROFILE(SMBopen);
1114 return(outsize);
1117 /****************************************************************************
1118 Reply to an open and X.
1119 ****************************************************************************/
1121 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1123 pstring fname;
1124 int smb_mode = SVAL(inbuf,smb_vwv3);
1125 int smb_attr = SVAL(inbuf,smb_vwv5);
1126 /* Breakout the oplock request bits so we can set the
1127 reply bits separately. */
1128 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1129 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1130 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1131 #if 0
1132 int open_flags = SVAL(inbuf,smb_vwv2);
1133 int smb_sattr = SVAL(inbuf,smb_vwv4);
1134 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1135 #endif
1136 int smb_ofun = SVAL(inbuf,smb_vwv8);
1137 SMB_OFF_T size=0;
1138 int fmode=0,mtime=0,rmode=0;
1139 SMB_STRUCT_STAT sbuf;
1140 int smb_action = 0;
1141 BOOL bad_path = False;
1142 files_struct *fsp;
1143 NTSTATUS status;
1144 START_PROFILE(SMBopenX);
1146 /* If it's an IPC, pass off the pipe handler. */
1147 if (IS_IPC(conn)) {
1148 if (lp_nt_pipe_support()) {
1149 END_PROFILE(SMBopenX);
1150 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1151 } else {
1152 END_PROFILE(SMBopenX);
1153 return ERROR_DOS(ERRSRV,ERRaccess);
1157 /* XXXX we need to handle passed times, sattr and flags */
1158 srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status, False);
1159 if (!NT_STATUS_IS_OK(status)) {
1160 END_PROFILE(SMBopenX);
1161 return ERROR_NT(status);
1164 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1166 unix_convert(fname,conn,0,&bad_path,&sbuf);
1167 if (bad_path) {
1168 END_PROFILE(SMBopenX);
1169 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1172 fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,(uint32)smb_attr,
1173 oplock_request, &rmode,&smb_action);
1175 if (!fsp) {
1176 END_PROFILE(SMBopenX);
1177 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1178 /* We have re-scheduled this call. */
1179 clear_cached_errors();
1180 return -1;
1182 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1185 size = sbuf.st_size;
1186 fmode = dos_mode(conn,fname,&sbuf);
1187 mtime = sbuf.st_mtime;
1188 if (fmode & aDIR) {
1189 close_file(fsp,False);
1190 END_PROFILE(SMBopenX);
1191 return ERROR_DOS(ERRDOS,ERRnoaccess);
1194 /* If the caller set the extended oplock request bit
1195 and we granted one (by whatever means) - set the
1196 correct bit for extended oplock reply.
1199 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn)))
1200 smb_action |= EXTENDED_OPLOCK_GRANTED;
1202 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1203 smb_action |= EXTENDED_OPLOCK_GRANTED;
1205 /* If the caller set the core oplock request bit
1206 and we granted one (by whatever means) - set the
1207 correct bit for core oplock reply.
1210 if (core_oplock_request && lp_fake_oplocks(SNUM(conn)))
1211 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1213 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1214 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1216 set_message(outbuf,15,0,True);
1217 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1218 SSVAL(outbuf,smb_vwv3,fmode);
1219 if(lp_dos_filetime_resolution(SNUM(conn)) )
1220 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1221 else
1222 put_dos_date3(outbuf,smb_vwv4,mtime);
1223 SIVAL(outbuf,smb_vwv6,(uint32)size);
1224 SSVAL(outbuf,smb_vwv8,rmode);
1225 SSVAL(outbuf,smb_vwv11,smb_action);
1227 END_PROFILE(SMBopenX);
1228 return chain_reply(inbuf,outbuf,length,bufsize);
1231 /****************************************************************************
1232 Reply to a SMBulogoffX.
1233 ****************************************************************************/
1235 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1237 uint16 vuid = SVAL(inbuf,smb_uid);
1238 user_struct *vuser = get_valid_user_struct(vuid);
1239 START_PROFILE(SMBulogoffX);
1241 if(vuser == 0)
1242 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1244 /* in user level security we are supposed to close any files
1245 open by this user */
1246 if ((vuser != 0) && (lp_security() != SEC_SHARE))
1247 file_close_user(vuid);
1249 invalidate_vuid(vuid);
1251 set_message(outbuf,2,0,True);
1253 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1255 END_PROFILE(SMBulogoffX);
1256 return chain_reply(inbuf,outbuf,length,bufsize);
1259 /****************************************************************************
1260 Reply to a mknew or a create.
1261 ****************************************************************************/
1263 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1265 pstring fname;
1266 int com;
1267 int outsize = 0;
1268 int createmode;
1269 int ofun = 0;
1270 BOOL bad_path = False;
1271 files_struct *fsp;
1272 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1273 SMB_STRUCT_STAT sbuf;
1274 NTSTATUS status;
1275 START_PROFILE(SMBcreate);
1277 com = SVAL(inbuf,smb_com);
1279 createmode = SVAL(inbuf,smb_vwv0);
1280 srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status, False);
1281 if (!NT_STATUS_IS_OK(status)) {
1282 END_PROFILE(SMBcreate);
1283 return ERROR_NT(status);
1286 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1288 unix_convert(fname,conn,0,&bad_path,&sbuf);
1289 if (bad_path) {
1290 END_PROFILE(SMBcreate);
1291 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1294 if (createmode & aVOLID)
1295 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1297 if(com == SMBmknew) {
1298 /* We should fail if file exists. */
1299 ofun = FILE_CREATE_IF_NOT_EXIST;
1300 } else {
1301 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1302 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1305 /* Open file in dos compatibility share mode. */
1306 fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1307 ofun, (uint32)createmode, oplock_request, NULL, NULL);
1309 if (!fsp) {
1310 END_PROFILE(SMBcreate);
1311 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1312 /* We have re-scheduled this call. */
1313 clear_cached_errors();
1314 return -1;
1316 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1319 outsize = set_message(outbuf,1,0,True);
1320 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1322 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1323 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1325 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1326 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1328 DEBUG( 2, ( "new file %s\n", fname ) );
1329 DEBUG( 3, ( "mknew %s fd=%d dmode=%d\n", fname, fsp->fd, createmode ) );
1331 END_PROFILE(SMBcreate);
1332 return(outsize);
1335 /****************************************************************************
1336 Reply to a create temporary file.
1337 ****************************************************************************/
1339 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1341 pstring fname;
1342 int outsize = 0;
1343 int createattr;
1344 BOOL bad_path = False;
1345 files_struct *fsp;
1346 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1347 int tmpfd;
1348 SMB_STRUCT_STAT sbuf;
1349 char *p, *s;
1350 NTSTATUS status;
1351 unsigned int namelen;
1353 START_PROFILE(SMBctemp);
1355 createattr = SVAL(inbuf,smb_vwv0);
1356 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status, False);
1357 if (!NT_STATUS_IS_OK(status)) {
1358 END_PROFILE(SMBctemp);
1359 return ERROR_NT(status);
1361 if (*fname) {
1362 pstrcat(fname,"/TMXXXXXX");
1363 } else {
1364 pstrcat(fname,"TMXXXXXX");
1367 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1369 unix_convert(fname,conn,0,&bad_path,&sbuf);
1370 if (bad_path) {
1371 END_PROFILE(SMBctemp);
1372 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1375 tmpfd = smb_mkstemp(fname);
1376 if (tmpfd == -1) {
1377 END_PROFILE(SMBctemp);
1378 return(UNIXERROR(ERRDOS,ERRnoaccess));
1381 SMB_VFS_STAT(conn,fname,&sbuf);
1383 /* Open file in dos compatibility share mode. */
1384 /* We should fail if file does not exist. */
1385 fsp = open_file_shared(conn,fname,&sbuf,
1386 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1387 FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
1388 (uint32)createattr, oplock_request, NULL, NULL);
1390 /* close fd from smb_mkstemp() */
1391 close(tmpfd);
1393 if (!fsp) {
1394 END_PROFILE(SMBctemp);
1395 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1396 /* We have re-scheduled this call. */
1397 clear_cached_errors();
1398 return -1;
1400 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1403 outsize = set_message(outbuf,1,0,True);
1404 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1406 /* the returned filename is relative to the directory */
1407 s = strrchr_m(fname, '/');
1408 if (!s)
1409 s = fname;
1410 else
1411 s++;
1413 p = smb_buf(outbuf);
1414 #if 0
1415 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
1416 thing in the byte section. JRA */
1417 SSVALS(p, 0, -1); /* what is this? not in spec */
1418 #endif
1419 namelen = srvstr_push(outbuf, p, s, -1, STR_ASCII|STR_TERMINATE);
1420 p += namelen;
1421 outsize = set_message_end(outbuf, p);
1423 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1424 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1426 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1427 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1429 DEBUG( 2, ( "created temp file %s\n", fname ) );
1430 DEBUG( 3, ( "ctemp %s fd=%d umode=%o\n",
1431 fname, fsp->fd, sbuf.st_mode ) );
1433 END_PROFILE(SMBctemp);
1434 return(outsize);
1437 /*******************************************************************
1438 Check if a user is allowed to rename a file.
1439 ********************************************************************/
1441 static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, SMB_STRUCT_STAT *pst)
1443 int smb_action;
1444 int access_mode;
1445 files_struct *fsp;
1446 uint16 fmode;
1448 if (!CAN_WRITE(conn))
1449 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1451 fmode = dos_mode(conn,fname,pst);
1452 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1453 return NT_STATUS_NO_SUCH_FILE;
1455 if (S_ISDIR(pst->st_mode))
1456 return NT_STATUS_OK;
1458 /* We need a better way to return NT status codes from open... */
1459 unix_ERR_class = 0;
1460 unix_ERR_code = 0;
1462 fsp = open_file_shared1(conn, fname, pst, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1463 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action);
1465 if (!fsp) {
1466 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1467 if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1468 ret = NT_STATUS_SHARING_VIOLATION;
1469 unix_ERR_class = 0;
1470 unix_ERR_code = 0;
1471 unix_ERR_ntstatus = NT_STATUS_OK;
1472 return ret;
1474 close_file(fsp,False);
1475 return NT_STATUS_OK;
1478 /*******************************************************************
1479 Check if a user is allowed to delete a file.
1480 ********************************************************************/
1482 NTSTATUS can_delete(connection_struct *conn, char *fname, int dirtype, BOOL bad_path, BOOL check_is_at_open)
1484 SMB_STRUCT_STAT sbuf;
1485 int fmode;
1486 int smb_action;
1487 int access_mode;
1488 files_struct *fsp;
1490 DEBUG(10,("can_delete: %s, dirtype = %d\n",
1491 fname, dirtype ));
1493 if (!CAN_WRITE(conn))
1494 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1496 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
1497 if(errno == ENOENT) {
1498 if (bad_path)
1499 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1500 else
1501 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1503 return map_nt_error_from_unix(errno);
1506 fmode = dos_mode(conn,fname,&sbuf);
1508 /* Can't delete a directory. */
1509 if (fmode & aDIR)
1510 return NT_STATUS_FILE_IS_A_DIRECTORY;
1511 #if 0 /* JRATEST */
1512 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
1513 return NT_STATUS_OBJECT_NAME_INVALID;
1514 #endif /* JRATEST */
1516 if (!lp_delete_readonly(SNUM(conn))) {
1517 if (fmode & aRONLY)
1518 return NT_STATUS_CANNOT_DELETE;
1520 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1521 return NT_STATUS_NO_SUCH_FILE;
1523 if (check_is_at_open) {
1524 if (!can_delete_file_in_directory(conn, fname)) {
1525 return NT_STATUS_ACCESS_DENIED;
1527 } else {
1528 /* On open checks the open itself will check the share mode, so
1529 don't do it here as we'll get it wrong. */
1531 /* We need a better way to return NT status codes from open... */
1532 unix_ERR_class = 0;
1533 unix_ERR_code = 0;
1535 fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1536 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action);
1538 if (!fsp) {
1539 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1540 if (!NT_STATUS_IS_OK(unix_ERR_ntstatus))
1541 ret = unix_ERR_ntstatus;
1542 else if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1543 ret = NT_STATUS_SHARING_VIOLATION;
1544 unix_ERR_class = 0;
1545 unix_ERR_code = 0;
1546 unix_ERR_ntstatus = NT_STATUS_OK;
1547 return ret;
1549 close_file(fsp,False);
1551 return NT_STATUS_OK;
1554 /****************************************************************************
1555 The guts of the unlink command, split out so it may be called by the NT SMB
1556 code.
1557 ****************************************************************************/
1559 NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
1561 pstring directory;
1562 pstring mask;
1563 char *p;
1564 int count=0;
1565 NTSTATUS error = NT_STATUS_OK;
1566 BOOL has_wild;
1567 BOOL bad_path = False;
1568 BOOL rc = True;
1569 SMB_STRUCT_STAT sbuf;
1571 *directory = *mask = 0;
1573 /* We must check for wildcards in the name given
1574 * directly by the client - before any unmangling.
1575 * This prevents an unmangling of a UNIX name containing
1576 * a DOS wildcard like '*' or '?' from unmangling into
1577 * a wildcard delete which was not intended.
1578 * FIX for #226. JRA.
1581 has_wild = ms_has_wild(name);
1583 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1585 p = strrchr_m(name,'/');
1586 if (!p) {
1587 pstrcpy(directory,".");
1588 pstrcpy(mask,name);
1589 } else {
1590 *p = 0;
1591 pstrcpy(directory,name);
1592 pstrcpy(mask,p+1);
1596 * We should only check the mangled cache
1597 * here if unix_convert failed. This means
1598 * that the path in 'mask' doesn't exist
1599 * on the file system and so we need to look
1600 * for a possible mangle. This patch from
1601 * Tine Smukavec <valentin.smukavec@hermes.si>.
1604 if (!rc && mangle_is_mangled(mask))
1605 mangle_check_cache( mask, sizeof(pstring)-1 );
1607 if (!has_wild) {
1608 pstrcat(directory,"/");
1609 pstrcat(directory,mask);
1610 error = can_delete(conn,directory,dirtype,bad_path,False);
1611 if (!NT_STATUS_IS_OK(error))
1612 return error;
1614 if (SMB_VFS_UNLINK(conn,directory) == 0) {
1615 count++;
1617 } else {
1618 struct smb_Dir *dir_hnd = NULL;
1619 const char *dname;
1621 if (check_name(directory,conn))
1622 dir_hnd = OpenDir(conn, directory);
1624 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1625 the pattern matches against the long name, otherwise the short name
1626 We don't implement this yet XXXX
1629 if (dir_hnd) {
1630 long offset = 0;
1631 error = NT_STATUS_NO_SUCH_FILE;
1633 if (strequal(mask,"????????.???"))
1634 pstrcpy(mask,"*");
1636 while ((dname = ReadDirName(dir_hnd, &offset))) {
1637 SMB_STRUCT_STAT st;
1638 pstring fname;
1639 BOOL sys_direntry = False;
1640 pstrcpy(fname,dname);
1642 if (!is_visible_file(conn, directory, dname, &st, True)) {
1643 continue;
1646 /* Quick check for "." and ".." */
1647 if (fname[0] == '.') {
1648 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
1649 if ((dirtype & FILE_ATTRIBUTE_DIRECTORY) && (dirtype & FILE_ATTRIBUTE_SYSTEM)) {
1650 sys_direntry = True;
1651 } else {
1652 continue;
1657 if(!mask_match(fname, mask, conn->case_sensitive))
1658 continue;
1660 if (sys_direntry) {
1661 error = NT_STATUS_OBJECT_NAME_INVALID;
1662 DEBUG(3,("unlink_internals: system directory delete denied [%s] mask [%s]\n",
1663 fname, mask));
1664 break;
1667 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1668 error = can_delete(conn,fname,dirtype,bad_path,False);
1669 if (!NT_STATUS_IS_OK(error)) {
1670 continue;
1672 if (SMB_VFS_UNLINK(conn,fname) == 0)
1673 count++;
1674 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
1676 CloseDir(dir_hnd);
1680 if (count == 0 && NT_STATUS_IS_OK(error)) {
1681 error = map_nt_error_from_unix(errno);
1684 return error;
1687 /****************************************************************************
1688 Reply to a unlink
1689 ****************************************************************************/
1691 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
1692 int dum_buffsize)
1694 int outsize = 0;
1695 pstring name;
1696 int dirtype;
1697 NTSTATUS status;
1698 START_PROFILE(SMBunlink);
1700 dirtype = SVAL(inbuf,smb_vwv0);
1702 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, True);
1703 if (!NT_STATUS_IS_OK(status)) {
1704 END_PROFILE(SMBunlink);
1705 return ERROR_NT(status);
1708 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1710 DEBUG(3,("reply_unlink : %s\n",name));
1712 status = unlink_internals(conn, dirtype, name);
1713 if (!NT_STATUS_IS_OK(status)) {
1714 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1715 /* We have re-scheduled this call. */
1716 clear_cached_errors();
1717 return -1;
1719 return ERROR_NT(status);
1723 * Win2k needs a changenotify request response before it will
1724 * update after a rename..
1726 process_pending_change_notify_queue((time_t)0);
1728 outsize = set_message(outbuf,0,0,True);
1730 END_PROFILE(SMBunlink);
1731 return outsize;
1734 /****************************************************************************
1735 Fail for readbraw.
1736 ****************************************************************************/
1738 static void fail_readraw(void)
1740 pstring errstr;
1741 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
1742 strerror(errno) );
1743 exit_server(errstr);
1746 #if defined(WITH_SENDFILE)
1747 /****************************************************************************
1748 Fake (read/write) sendfile. Returns -1 on read or write fail.
1749 ****************************************************************************/
1751 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread, char *buf, int bufsize)
1753 ssize_t ret=0;
1755 /* Paranioa check... */
1756 if (nread > bufsize) {
1757 fail_readraw();
1760 if (nread > 0) {
1761 ret = read_file(fsp,buf,startpos,nread);
1762 if (ret == -1) {
1763 return -1;
1767 /* If we had a short read, fill with zeros. */
1768 if (ret < nread) {
1769 memset(buf, '\0', nread - ret);
1772 if (write_data(smbd_server_fd(),buf,nread) != nread) {
1773 return -1;
1776 return (ssize_t)nread;
1778 #endif
1780 /****************************************************************************
1781 Use sendfile in readbraw.
1782 ****************************************************************************/
1784 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
1785 ssize_t mincount, char *outbuf, int out_buffsize)
1787 ssize_t ret=0;
1789 #if defined(WITH_SENDFILE)
1791 * We can only use sendfile on a non-chained packet
1792 * but we can use on a non-oplocked file. tridge proved this
1793 * on a train in Germany :-). JRA.
1794 * reply_readbraw has already checked the length.
1797 if (chain_size ==0 && (nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) && lp_use_sendfile(SNUM(conn)) ) {
1798 DATA_BLOB header;
1800 _smb_setlen(outbuf,nread);
1801 header.data = outbuf;
1802 header.length = 4;
1803 header.free = NULL;
1805 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) {
1806 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
1807 if (errno == ENOSYS) {
1808 goto normal_readbraw;
1812 * Special hack for broken Linux with no working sendfile. If we
1813 * return EINTR we sent the header but not the rest of the data.
1814 * Fake this up by doing read/write calls.
1816 if (errno == EINTR) {
1817 /* Ensure we don't do this again. */
1818 set_use_sendfile(SNUM(conn), False);
1819 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
1821 if (fake_sendfile(fsp, startpos, nread, outbuf + 4, out_buffsize - 4) == -1) {
1822 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
1823 fsp->fsp_name, strerror(errno) ));
1824 exit_server("send_file_readbraw fake_sendfile failed");
1826 return;
1829 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
1830 fsp->fsp_name, strerror(errno) ));
1831 exit_server("send_file_readbraw sendfile failed");
1836 normal_readbraw:
1838 #endif
1840 if (nread > 0) {
1841 ret = read_file(fsp,outbuf+4,startpos,nread);
1842 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1843 if (ret < mincount)
1844 ret = 0;
1845 #else
1846 if (ret < nread)
1847 ret = 0;
1848 #endif
1851 _smb_setlen(outbuf,ret);
1852 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
1853 fail_readraw();
1856 /****************************************************************************
1857 Reply to a readbraw (core+ protocol).
1858 ****************************************************************************/
1860 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int out_buffsize)
1862 extern struct current_user current_user;
1863 ssize_t maxcount,mincount;
1864 size_t nread = 0;
1865 SMB_OFF_T startpos;
1866 char *header = outbuf;
1867 files_struct *fsp;
1868 START_PROFILE(SMBreadbraw);
1870 if (srv_is_signing_active()) {
1871 exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
1875 * Special check if an oplock break has been issued
1876 * and the readraw request croses on the wire, we must
1877 * return a zero length response here.
1880 if(global_oplock_break) {
1881 _smb_setlen(header,0);
1882 if (write_data(smbd_server_fd(),header,4) != 4)
1883 fail_readraw();
1884 DEBUG(5,("readbraw - oplock break finished\n"));
1885 END_PROFILE(SMBreadbraw);
1886 return -1;
1889 fsp = file_fsp(inbuf,smb_vwv0);
1891 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1893 * fsp could be NULL here so use the value from the packet. JRA.
1895 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
1896 _smb_setlen(header,0);
1897 if (write_data(smbd_server_fd(),header,4) != 4)
1898 fail_readraw();
1899 END_PROFILE(SMBreadbraw);
1900 return(-1);
1903 CHECK_FSP(fsp,conn);
1905 flush_write_cache(fsp, READRAW_FLUSH);
1907 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
1908 if(CVAL(inbuf,smb_wct) == 10) {
1910 * This is a large offset (64 bit) read.
1912 #ifdef LARGE_SMB_OFF_T
1914 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
1916 #else /* !LARGE_SMB_OFF_T */
1919 * Ensure we haven't been sent a >32 bit offset.
1922 if(IVAL(inbuf,smb_vwv8) != 0) {
1923 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
1924 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
1925 _smb_setlen(header,0);
1926 if (write_data(smbd_server_fd(),header,4) != 4)
1927 fail_readraw();
1928 END_PROFILE(SMBreadbraw);
1929 return(-1);
1932 #endif /* LARGE_SMB_OFF_T */
1934 if(startpos < 0) {
1935 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
1936 _smb_setlen(header,0);
1937 if (write_data(smbd_server_fd(),header,4) != 4)
1938 fail_readraw();
1939 END_PROFILE(SMBreadbraw);
1940 return(-1);
1943 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
1944 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
1946 /* ensure we don't overrun the packet size */
1947 maxcount = MIN(65535,maxcount);
1949 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
1950 SMB_OFF_T size = fsp->size;
1951 SMB_OFF_T sizeneeded = startpos + maxcount;
1953 if (size < sizeneeded) {
1954 SMB_STRUCT_STAT st;
1955 if (SMB_VFS_FSTAT(fsp,fsp->fd,&st) == 0)
1956 size = st.st_size;
1957 if (!fsp->can_write)
1958 fsp->size = size;
1961 if (startpos >= size)
1962 nread = 0;
1963 else
1964 nread = MIN(maxcount,(size - startpos));
1967 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1968 if (nread < mincount)
1969 nread = 0;
1970 #endif
1972 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
1973 (int)maxcount, (int)mincount, (int)nread ) );
1975 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf, out_buffsize);
1977 DEBUG(5,("readbraw finished\n"));
1978 END_PROFILE(SMBreadbraw);
1979 return -1;
1982 /****************************************************************************
1983 Reply to a lockread (core+ protocol).
1984 ****************************************************************************/
1986 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
1988 ssize_t nread = -1;
1989 char *data;
1990 int outsize = 0;
1991 SMB_OFF_T startpos;
1992 size_t numtoread;
1993 NTSTATUS status;
1994 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1995 BOOL my_lock_ctx = False;
1996 START_PROFILE(SMBlockread);
1998 CHECK_FSP(fsp,conn);
1999 CHECK_READ(fsp);
2001 release_level_2_oplocks_on_change(fsp);
2003 numtoread = SVAL(inbuf,smb_vwv1);
2004 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2006 outsize = set_message(outbuf,5,3,True);
2007 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2008 data = smb_buf(outbuf) + 3;
2011 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2012 * protocol request that predates the read/write lock concept.
2013 * Thus instead of asking for a read lock here we need to ask
2014 * for a write lock. JRA.
2015 * Note that the requested lock size is unaffected by max_recv.
2018 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid),
2019 (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, &my_lock_ctx);
2021 if (NT_STATUS_V(status)) {
2022 #if 0
2024 * We used to make lockread a blocking lock. It turns out
2025 * that this isn't on W2k. Found by the Samba 4 RAW-READ torture
2026 * tester. JRA.
2029 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
2031 * A blocking lock was requested. Package up
2032 * this smb into a queued request and push it
2033 * onto the blocking lock queue.
2035 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)startpos,
2036 (SMB_BIG_UINT)numtoread)) {
2037 END_PROFILE(SMBlockread);
2038 return -1;
2041 #endif
2042 END_PROFILE(SMBlockread);
2043 return ERROR_NT(status);
2047 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
2050 if (numtoread > max_recv) {
2051 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
2052 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2053 (unsigned int)numtoread, (unsigned int)max_recv ));
2054 numtoread = MIN(numtoread,max_recv);
2056 nread = read_file(fsp,data,startpos,numtoread);
2058 if (nread < 0) {
2059 END_PROFILE(SMBlockread);
2060 return(UNIXERROR(ERRDOS,ERRnoaccess));
2063 outsize += nread;
2064 SSVAL(outbuf,smb_vwv0,nread);
2065 SSVAL(outbuf,smb_vwv5,nread+3);
2066 SSVAL(smb_buf(outbuf),1,nread);
2068 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
2069 fsp->fnum, (int)numtoread, (int)nread));
2071 END_PROFILE(SMBlockread);
2072 return(outsize);
2075 /****************************************************************************
2076 Reply to a read.
2077 ****************************************************************************/
2079 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2081 size_t numtoread;
2082 ssize_t nread = 0;
2083 char *data;
2084 SMB_OFF_T startpos;
2085 int outsize = 0;
2086 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2087 START_PROFILE(SMBread);
2089 CHECK_FSP(fsp,conn);
2090 CHECK_READ(fsp);
2092 numtoread = SVAL(inbuf,smb_vwv1);
2093 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2095 outsize = set_message(outbuf,5,3,True);
2096 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2098 * The requested read size cannot be greater than max_recv. JRA.
2100 if (numtoread > max_recv) {
2101 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
2102 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2103 (unsigned int)numtoread, (unsigned int)max_recv ));
2104 numtoread = MIN(numtoread,max_recv);
2107 data = smb_buf(outbuf) + 3;
2109 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2110 END_PROFILE(SMBread);
2111 return ERROR_DOS(ERRDOS,ERRlock);
2114 if (numtoread > 0)
2115 nread = read_file(fsp,data,startpos,numtoread);
2117 if (nread < 0) {
2118 END_PROFILE(SMBread);
2119 return(UNIXERROR(ERRDOS,ERRnoaccess));
2122 outsize += nread;
2123 SSVAL(outbuf,smb_vwv0,nread);
2124 SSVAL(outbuf,smb_vwv5,nread+3);
2125 SCVAL(smb_buf(outbuf),0,1);
2126 SSVAL(smb_buf(outbuf),1,nread);
2128 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2129 fsp->fnum, (int)numtoread, (int)nread ) );
2131 END_PROFILE(SMBread);
2132 return(outsize);
2135 /****************************************************************************
2136 Reply to a read and X - possibly using sendfile.
2137 ****************************************************************************/
2139 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length, int len_outbuf,
2140 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
2142 int outsize = 0;
2143 ssize_t nread = -1;
2144 char *data = smb_buf(outbuf);
2146 #if defined(WITH_SENDFILE)
2148 * We can only use sendfile on a non-chained packet
2149 * but we can use on a non-oplocked file. tridge proved this
2150 * on a train in Germany :-). JRA.
2153 if (chain_size ==0 && (CVAL(inbuf,smb_vwv0) == 0xFF) && lp_use_sendfile(SNUM(conn)) &&
2154 (lp_write_cache_size(SNUM(conn)) == 0) ) {
2155 SMB_STRUCT_STAT sbuf;
2156 DATA_BLOB header;
2158 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1)
2159 return(UNIXERROR(ERRDOS,ERRnoaccess));
2161 if (startpos > sbuf.st_size)
2162 goto normal_read;
2164 if (smb_maxcnt > (sbuf.st_size - startpos))
2165 smb_maxcnt = (sbuf.st_size - startpos);
2167 if (smb_maxcnt == 0)
2168 goto normal_read;
2171 * Set up the packet header before send. We
2172 * assume here the sendfile will work (get the
2173 * correct amount of data).
2176 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2177 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
2178 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2179 SSVAL(outbuf,smb_vwv7,((smb_maxcnt >> 16) & 1));
2180 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
2181 SCVAL(outbuf,smb_vwv0,0xFF);
2182 set_message(outbuf,12,smb_maxcnt,False);
2183 header.data = outbuf;
2184 header.length = data - outbuf;
2185 header.free = NULL;
2187 if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt)) == -1) {
2188 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2189 if (errno == ENOSYS) {
2190 goto normal_read;
2194 * Special hack for broken Linux with no working sendfile. If we
2195 * return EINTR we sent the header but not the rest of the data.
2196 * Fake this up by doing read/write calls.
2199 if (errno == EINTR) {
2200 /* Ensure we don't do this again. */
2201 set_use_sendfile(SNUM(conn), False);
2202 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
2204 if ((nread = fake_sendfile(fsp, startpos, smb_maxcnt, data,
2205 len_outbuf - (data-outbuf))) == -1) {
2206 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
2207 fsp->fsp_name, strerror(errno) ));
2208 exit_server("send_file_readX: fake_sendfile failed");
2210 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
2211 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2212 /* Returning -1 here means successful sendfile. */
2213 return -1;
2216 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2217 fsp->fsp_name, strerror(errno) ));
2218 exit_server("send_file_readX sendfile failed");
2221 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2222 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2223 /* Returning -1 here means successful sendfile. */
2224 return -1;
2227 normal_read:
2229 #endif
2231 nread = read_file(fsp,data,startpos,smb_maxcnt);
2233 if (nread < 0) {
2234 END_PROFILE(SMBreadX);
2235 return(UNIXERROR(ERRDOS,ERRnoaccess));
2238 outsize = set_message(outbuf,12,nread,False);
2239 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2240 SSVAL(outbuf,smb_vwv5,nread);
2241 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2242 SSVAL(outbuf,smb_vwv7,((nread >> 16) & 1));
2243 SSVAL(smb_buf(outbuf),-2,nread);
2245 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2246 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2248 /* Returning the number of bytes we want to send back - including header. */
2249 return outsize;
2252 /****************************************************************************
2253 Reply to a read and X.
2254 ****************************************************************************/
2256 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2258 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2259 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2260 ssize_t nread = -1;
2261 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2262 #if 0
2263 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2264 #endif
2266 START_PROFILE(SMBreadX);
2268 /* If it's an IPC, pass off the pipe handler. */
2269 if (IS_IPC(conn)) {
2270 END_PROFILE(SMBreadX);
2271 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2274 CHECK_FSP(fsp,conn);
2275 CHECK_READ(fsp);
2277 set_message(outbuf,12,0,True);
2279 if (global_client_caps & CAP_LARGE_READX) {
2280 if (SVAL(inbuf,smb_vwv7) == 1) {
2281 smb_maxcnt |= (1<<16);
2283 if (smb_maxcnt > BUFFER_SIZE) {
2284 DEBUG(0,("reply_read_and_X - read too large (%u) for reply buffer %u\n",
2285 (unsigned int)smb_maxcnt, (unsigned int)BUFFER_SIZE));
2286 END_PROFILE(SMBreadX);
2287 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2291 if(CVAL(inbuf,smb_wct) == 12) {
2292 #ifdef LARGE_SMB_OFF_T
2294 * This is a large offset (64 bit) read.
2296 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2298 #else /* !LARGE_SMB_OFF_T */
2301 * Ensure we haven't been sent a >32 bit offset.
2304 if(IVAL(inbuf,smb_vwv10) != 0) {
2305 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2306 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2307 END_PROFILE(SMBreadX);
2308 return ERROR_DOS(ERRDOS,ERRbadaccess);
2311 #endif /* LARGE_SMB_OFF_T */
2315 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2316 END_PROFILE(SMBreadX);
2317 return ERROR_DOS(ERRDOS,ERRlock);
2320 nread = send_file_readX(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt);
2321 if (nread != -1)
2322 nread = chain_reply(inbuf,outbuf,length,bufsize);
2324 END_PROFILE(SMBreadX);
2325 return nread;
2328 /****************************************************************************
2329 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2330 ****************************************************************************/
2332 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2334 ssize_t nwritten=0;
2335 ssize_t total_written=0;
2336 size_t numtowrite=0;
2337 size_t tcount;
2338 SMB_OFF_T startpos;
2339 char *data=NULL;
2340 BOOL write_through;
2341 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2342 int outsize = 0;
2343 START_PROFILE(SMBwritebraw);
2345 if (srv_is_signing_active()) {
2346 exit_server("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2349 CHECK_FSP(fsp,conn);
2350 CHECK_WRITE(fsp);
2352 tcount = IVAL(inbuf,smb_vwv1);
2353 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2354 write_through = BITSETW(inbuf+smb_vwv7,0);
2356 /* We have to deal with slightly different formats depending
2357 on whether we are using the core+ or lanman1.0 protocol */
2359 if(Protocol <= PROTOCOL_COREPLUS) {
2360 numtowrite = SVAL(smb_buf(inbuf),-2);
2361 data = smb_buf(inbuf);
2362 } else {
2363 numtowrite = SVAL(inbuf,smb_vwv10);
2364 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2367 /* force the error type */
2368 SCVAL(inbuf,smb_com,SMBwritec);
2369 SCVAL(outbuf,smb_com,SMBwritec);
2371 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2372 END_PROFILE(SMBwritebraw);
2373 return(ERROR_DOS(ERRDOS,ERRlock));
2376 if (numtowrite>0)
2377 nwritten = write_file(fsp,data,startpos,numtowrite);
2379 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2380 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2382 if (nwritten < (ssize_t)numtowrite) {
2383 END_PROFILE(SMBwritebraw);
2384 return(UNIXERROR(ERRHRD,ERRdiskfull));
2387 total_written = nwritten;
2389 /* Return a message to the redirector to tell it to send more bytes */
2390 SCVAL(outbuf,smb_com,SMBwritebraw);
2391 SSVALS(outbuf,smb_vwv0,-1);
2392 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2393 if (!send_smb(smbd_server_fd(),outbuf))
2394 exit_server("reply_writebraw: send_smb failed.");
2396 /* Now read the raw data into the buffer and write it */
2397 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2398 exit_server("secondary writebraw failed");
2401 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2402 numtowrite = smb_len(inbuf);
2404 /* Set up outbuf to return the correct return */
2405 outsize = set_message(outbuf,1,0,True);
2406 SCVAL(outbuf,smb_com,SMBwritec);
2407 SSVAL(outbuf,smb_vwv0,total_written);
2409 if (numtowrite != 0) {
2411 if (numtowrite > BUFFER_SIZE) {
2412 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2413 (unsigned int)numtowrite ));
2414 exit_server("secondary writebraw failed");
2417 if (tcount > nwritten+numtowrite) {
2418 DEBUG(3,("Client overestimated the write %d %d %d\n",
2419 (int)tcount,(int)nwritten,(int)numtowrite));
2422 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2423 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2424 strerror(errno) ));
2425 exit_server("secondary writebraw failed");
2428 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2430 if (nwritten < (ssize_t)numtowrite) {
2431 SCVAL(outbuf,smb_rcls,ERRHRD);
2432 SSVAL(outbuf,smb_err,ERRdiskfull);
2435 if (nwritten > 0)
2436 total_written += nwritten;
2439 if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn)))
2440 sync_file(conn,fsp);
2442 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2443 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2445 /* we won't return a status if write through is not selected - this follows what WfWg does */
2446 END_PROFILE(SMBwritebraw);
2447 if (!write_through && total_written==tcount) {
2449 #if RABBIT_PELLET_FIX
2451 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2452 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2454 if (!send_keepalive(smbd_server_fd()))
2455 exit_server("reply_writebraw: send of keepalive failed");
2456 #endif
2457 return(-1);
2460 return(outsize);
2463 /****************************************************************************
2464 Reply to a writeunlock (core+).
2465 ****************************************************************************/
2467 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
2468 int size, int dum_buffsize)
2470 ssize_t nwritten = -1;
2471 size_t numtowrite;
2472 SMB_OFF_T startpos;
2473 char *data;
2474 NTSTATUS status = NT_STATUS_OK;
2475 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2476 int outsize = 0;
2477 START_PROFILE(SMBwriteunlock);
2479 CHECK_FSP(fsp,conn);
2480 CHECK_WRITE(fsp);
2482 numtowrite = SVAL(inbuf,smb_vwv1);
2483 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2484 data = smb_buf(inbuf) + 3;
2486 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2487 END_PROFILE(SMBwriteunlock);
2488 return ERROR_DOS(ERRDOS,ERRlock);
2491 /* The special X/Open SMB protocol handling of
2492 zero length writes is *NOT* done for
2493 this call */
2494 if(numtowrite == 0)
2495 nwritten = 0;
2496 else
2497 nwritten = write_file(fsp,data,startpos,numtowrite);
2499 if (lp_syncalways(SNUM(conn)))
2500 sync_file(conn,fsp);
2502 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2503 END_PROFILE(SMBwriteunlock);
2504 return(UNIXERROR(ERRHRD,ERRdiskfull));
2507 if (numtowrite) {
2508 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite,
2509 (SMB_BIG_UINT)startpos);
2510 if (NT_STATUS_V(status)) {
2511 END_PROFILE(SMBwriteunlock);
2512 return ERROR_NT(status);
2516 outsize = set_message(outbuf,1,0,True);
2518 SSVAL(outbuf,smb_vwv0,nwritten);
2520 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2521 fsp->fnum, (int)numtowrite, (int)nwritten));
2523 END_PROFILE(SMBwriteunlock);
2524 return outsize;
2527 /****************************************************************************
2528 Reply to a write.
2529 ****************************************************************************/
2531 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2533 size_t numtowrite;
2534 ssize_t nwritten = -1;
2535 SMB_OFF_T startpos;
2536 char *data;
2537 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2538 int outsize = 0;
2539 START_PROFILE(SMBwrite);
2541 /* If it's an IPC, pass off the pipe handler. */
2542 if (IS_IPC(conn)) {
2543 END_PROFILE(SMBwrite);
2544 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2547 CHECK_FSP(fsp,conn);
2548 CHECK_WRITE(fsp);
2550 numtowrite = SVAL(inbuf,smb_vwv1);
2551 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2552 data = smb_buf(inbuf) + 3;
2554 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2555 END_PROFILE(SMBwrite);
2556 return ERROR_DOS(ERRDOS,ERRlock);
2560 * X/Open SMB protocol says that if smb_vwv1 is
2561 * zero then the file size should be extended or
2562 * truncated to the size given in smb_vwv[2-3].
2565 if(numtowrite == 0) {
2567 * This is actually an allocate call, and set EOF. JRA.
2569 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2570 if (nwritten < 0) {
2571 END_PROFILE(SMBwrite);
2572 return ERROR_NT(NT_STATUS_DISK_FULL);
2574 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2575 if (nwritten < 0) {
2576 END_PROFILE(SMBwrite);
2577 return ERROR_NT(NT_STATUS_DISK_FULL);
2579 } else
2580 nwritten = write_file(fsp,data,startpos,numtowrite);
2582 if (lp_syncalways(SNUM(conn)))
2583 sync_file(conn,fsp);
2585 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2586 END_PROFILE(SMBwrite);
2587 return(UNIXERROR(ERRHRD,ERRdiskfull));
2590 outsize = set_message(outbuf,1,0,True);
2592 SSVAL(outbuf,smb_vwv0,nwritten);
2594 if (nwritten < (ssize_t)numtowrite) {
2595 SCVAL(outbuf,smb_rcls,ERRHRD);
2596 SSVAL(outbuf,smb_err,ERRdiskfull);
2599 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2601 END_PROFILE(SMBwrite);
2602 return(outsize);
2605 /****************************************************************************
2606 Reply to a write and X.
2607 ****************************************************************************/
2609 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2611 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2612 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2613 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2614 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2615 ssize_t nwritten = -1;
2616 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2617 unsigned int smblen = smb_len(inbuf);
2618 char *data;
2619 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2620 START_PROFILE(SMBwriteX);
2622 /* If it's an IPC, pass off the pipe handler. */
2623 if (IS_IPC(conn)) {
2624 END_PROFILE(SMBwriteX);
2625 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2628 CHECK_FSP(fsp,conn);
2629 CHECK_WRITE(fsp);
2631 /* Deal with possible LARGE_WRITEX */
2632 if (large_writeX)
2633 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2635 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2636 END_PROFILE(SMBwriteX);
2637 return ERROR_DOS(ERRDOS,ERRbadmem);
2640 data = smb_base(inbuf) + smb_doff;
2642 if(CVAL(inbuf,smb_wct) == 14) {
2643 #ifdef LARGE_SMB_OFF_T
2645 * This is a large offset (64 bit) write.
2647 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2649 #else /* !LARGE_SMB_OFF_T */
2652 * Ensure we haven't been sent a >32 bit offset.
2655 if(IVAL(inbuf,smb_vwv12) != 0) {
2656 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2657 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2658 END_PROFILE(SMBwriteX);
2659 return ERROR_DOS(ERRDOS,ERRbadaccess);
2662 #endif /* LARGE_SMB_OFF_T */
2665 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2666 END_PROFILE(SMBwriteX);
2667 return ERROR_DOS(ERRDOS,ERRlock);
2670 /* X/Open SMB protocol says that, unlike SMBwrite
2671 if the length is zero then NO truncation is
2672 done, just a write of zero. To truncate a file,
2673 use SMBwrite. */
2675 if(numtowrite == 0)
2676 nwritten = 0;
2677 else
2678 nwritten = write_file(fsp,data,startpos,numtowrite);
2680 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2681 END_PROFILE(SMBwriteX);
2682 return(UNIXERROR(ERRHRD,ERRdiskfull));
2685 set_message(outbuf,6,0,True);
2687 SSVAL(outbuf,smb_vwv2,nwritten);
2688 if (large_writeX)
2689 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2691 if (nwritten < (ssize_t)numtowrite) {
2692 SCVAL(outbuf,smb_rcls,ERRHRD);
2693 SSVAL(outbuf,smb_err,ERRdiskfull);
2696 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2697 fsp->fnum, (int)numtowrite, (int)nwritten));
2699 if (lp_syncalways(SNUM(conn)) || write_through)
2700 sync_file(conn,fsp);
2702 END_PROFILE(SMBwriteX);
2703 return chain_reply(inbuf,outbuf,length,bufsize);
2706 /****************************************************************************
2707 Reply to a lseek.
2708 ****************************************************************************/
2710 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2712 SMB_OFF_T startpos;
2713 SMB_OFF_T res= -1;
2714 int mode,umode;
2715 int outsize = 0;
2716 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2717 START_PROFILE(SMBlseek);
2719 CHECK_FSP(fsp,conn);
2721 flush_write_cache(fsp, SEEK_FLUSH);
2723 mode = SVAL(inbuf,smb_vwv1) & 3;
2724 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
2725 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
2727 switch (mode) {
2728 case 0:
2729 umode = SEEK_SET;
2730 res = startpos;
2731 break;
2732 case 1:
2733 umode = SEEK_CUR;
2734 res = fsp->pos + startpos;
2735 break;
2736 case 2:
2737 umode = SEEK_END;
2738 break;
2739 default:
2740 umode = SEEK_SET;
2741 res = startpos;
2742 break;
2745 if (umode == SEEK_END) {
2746 if((res = SMB_VFS_LSEEK(fsp,fsp->fd,startpos,umode)) == -1) {
2747 if(errno == EINVAL) {
2748 SMB_OFF_T current_pos = startpos;
2749 SMB_STRUCT_STAT sbuf;
2751 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) {
2752 END_PROFILE(SMBlseek);
2753 return(UNIXERROR(ERRDOS,ERRnoaccess));
2756 current_pos += sbuf.st_size;
2757 if(current_pos < 0)
2758 res = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_SET);
2762 if(res == -1) {
2763 END_PROFILE(SMBlseek);
2764 return(UNIXERROR(ERRDOS,ERRnoaccess));
2768 fsp->pos = res;
2770 outsize = set_message(outbuf,2,0,True);
2771 SIVAL(outbuf,smb_vwv0,res);
2773 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2774 fsp->fnum, (double)startpos, (double)res, mode));
2776 END_PROFILE(SMBlseek);
2777 return(outsize);
2780 /****************************************************************************
2781 Reply to a flush.
2782 ****************************************************************************/
2784 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2786 int outsize = set_message(outbuf,0,0,True);
2787 uint16 fnum = SVAL(inbuf,smb_vwv0);
2788 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2789 START_PROFILE(SMBflush);
2791 if (fnum != 0xFFFF)
2792 CHECK_FSP(fsp,conn);
2794 if (!fsp) {
2795 file_sync_all(conn);
2796 } else {
2797 sync_file(conn,fsp);
2800 DEBUG(3,("flush\n"));
2801 END_PROFILE(SMBflush);
2802 return(outsize);
2805 /****************************************************************************
2806 Reply to a exit.
2807 ****************************************************************************/
2809 int reply_exit(connection_struct *conn,
2810 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2812 int outsize;
2813 START_PROFILE(SMBexit);
2815 file_close_pid(SVAL(inbuf,smb_pid));
2817 outsize = set_message(outbuf,0,0,True);
2819 DEBUG(3,("exit\n"));
2821 END_PROFILE(SMBexit);
2822 return(outsize);
2825 /****************************************************************************
2826 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2827 ****************************************************************************/
2829 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2830 int dum_buffsize)
2832 extern struct current_user current_user;
2833 int outsize = 0;
2834 time_t mtime;
2835 int32 eclass = 0, err = 0;
2836 files_struct *fsp = NULL;
2837 START_PROFILE(SMBclose);
2839 outsize = set_message(outbuf,0,0,True);
2841 /* If it's an IPC, pass off to the pipe handler. */
2842 if (IS_IPC(conn)) {
2843 END_PROFILE(SMBclose);
2844 return reply_pipe_close(conn, inbuf,outbuf);
2847 fsp = file_fsp(inbuf,smb_vwv0);
2850 * We can only use CHECK_FSP if we know it's not a directory.
2853 if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
2854 END_PROFILE(SMBclose);
2855 return ERROR_DOS(ERRDOS,ERRbadfid);
2858 if(fsp->is_directory) {
2860 * Special case - close NT SMB directory handle.
2862 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2863 close_file(fsp,True);
2864 } else {
2866 * Close ordinary file.
2868 int close_err;
2869 pstring file_name;
2871 /* Save the name for time set in close. */
2872 pstrcpy( file_name, fsp->fsp_name);
2874 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2875 fsp->fd, fsp->fnum,
2876 conn->num_files_open));
2879 * Take care of any time sent in the close.
2882 mtime = make_unix_date3(inbuf+smb_vwv1);
2883 fsp_set_pending_modtime(fsp, mtime);
2886 * close_file() returns the unix errno if an error
2887 * was detected on close - normally this is due to
2888 * a disk full error. If not then it was probably an I/O error.
2891 if((close_err = close_file(fsp,True)) != 0) {
2892 errno = close_err;
2893 END_PROFILE(SMBclose);
2894 return (UNIXERROR(ERRHRD,ERRgeneral));
2898 /* We have a cached error */
2899 if(eclass || err) {
2900 END_PROFILE(SMBclose);
2901 return ERROR_DOS(eclass,err);
2904 END_PROFILE(SMBclose);
2905 return(outsize);
2908 /****************************************************************************
2909 Reply to a writeclose (Core+ protocol).
2910 ****************************************************************************/
2912 int reply_writeclose(connection_struct *conn,
2913 char *inbuf,char *outbuf, int size, int dum_buffsize)
2915 size_t numtowrite;
2916 ssize_t nwritten = -1;
2917 int outsize = 0;
2918 int close_err = 0;
2919 SMB_OFF_T startpos;
2920 char *data;
2921 time_t mtime;
2922 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2923 START_PROFILE(SMBwriteclose);
2925 CHECK_FSP(fsp,conn);
2926 CHECK_WRITE(fsp);
2928 numtowrite = SVAL(inbuf,smb_vwv1);
2929 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2930 mtime = make_unix_date3(inbuf+smb_vwv4);
2931 data = smb_buf(inbuf) + 1;
2933 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2934 END_PROFILE(SMBwriteclose);
2935 return ERROR_DOS(ERRDOS,ERRlock);
2938 nwritten = write_file(fsp,data,startpos,numtowrite);
2940 set_filetime(conn, fsp->fsp_name,mtime);
2943 * More insanity. W2K only closes the file if writelen > 0.
2944 * JRA.
2947 if (numtowrite) {
2948 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
2949 fsp->fsp_name ));
2950 close_err = close_file(fsp,True);
2953 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2954 fsp->fnum, (int)numtowrite, (int)nwritten,
2955 conn->num_files_open));
2957 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2958 END_PROFILE(SMBwriteclose);
2959 return(UNIXERROR(ERRHRD,ERRdiskfull));
2962 if(close_err != 0) {
2963 errno = close_err;
2964 END_PROFILE(SMBwriteclose);
2965 return(UNIXERROR(ERRHRD,ERRgeneral));
2968 outsize = set_message(outbuf,1,0,True);
2970 SSVAL(outbuf,smb_vwv0,nwritten);
2971 END_PROFILE(SMBwriteclose);
2972 return(outsize);
2975 /****************************************************************************
2976 Reply to a lock.
2977 ****************************************************************************/
2979 int reply_lock(connection_struct *conn,
2980 char *inbuf,char *outbuf, int length, int dum_buffsize)
2982 int outsize = set_message(outbuf,0,0,True);
2983 SMB_BIG_UINT count,offset;
2984 NTSTATUS status;
2985 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2986 BOOL my_lock_ctx = False;
2988 START_PROFILE(SMBlock);
2990 CHECK_FSP(fsp,conn);
2992 release_level_2_oplocks_on_change(fsp);
2994 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2995 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2997 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2998 fsp->fd, fsp->fnum, (double)offset, (double)count));
3000 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &my_lock_ctx);
3001 if (NT_STATUS_V(status)) {
3002 #if 0
3003 /* Tests using Samba4 against W2K show this call never creates a blocking lock. */
3004 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
3006 * A blocking lock was requested. Package up
3007 * this smb into a queued request and push it
3008 * onto the blocking lock queue.
3010 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), offset, count)) {
3011 END_PROFILE(SMBlock);
3012 return -1;
3015 #endif
3016 END_PROFILE(SMBlock);
3017 return ERROR_NT(status);
3020 END_PROFILE(SMBlock);
3021 return(outsize);
3024 /****************************************************************************
3025 Reply to a unlock.
3026 ****************************************************************************/
3028 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
3029 int dum_buffsize)
3031 int outsize = set_message(outbuf,0,0,True);
3032 SMB_BIG_UINT count,offset;
3033 NTSTATUS status;
3034 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3035 START_PROFILE(SMBunlock);
3037 CHECK_FSP(fsp,conn);
3039 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3040 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3042 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
3043 if (NT_STATUS_V(status)) {
3044 END_PROFILE(SMBunlock);
3045 return ERROR_NT(status);
3048 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3049 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
3051 END_PROFILE(SMBunlock);
3052 return(outsize);
3055 /****************************************************************************
3056 Reply to a tdis.
3057 ****************************************************************************/
3059 int reply_tdis(connection_struct *conn,
3060 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3062 int outsize = set_message(outbuf,0,0,True);
3063 uint16 vuid;
3064 START_PROFILE(SMBtdis);
3066 vuid = SVAL(inbuf,smb_uid);
3068 if (!conn) {
3069 DEBUG(4,("Invalid connection in tdis\n"));
3070 END_PROFILE(SMBtdis);
3071 return ERROR_DOS(ERRSRV,ERRinvnid);
3074 conn->used = False;
3076 close_cnum(conn,vuid);
3078 END_PROFILE(SMBtdis);
3079 return outsize;
3082 /****************************************************************************
3083 Reply to a echo.
3084 ****************************************************************************/
3086 int reply_echo(connection_struct *conn,
3087 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3089 int smb_reverb = SVAL(inbuf,smb_vwv0);
3090 int seq_num;
3091 unsigned int data_len = smb_buflen(inbuf);
3092 int outsize = set_message(outbuf,1,data_len,True);
3093 START_PROFILE(SMBecho);
3095 if (data_len > BUFFER_SIZE) {
3096 DEBUG(0,("reply_echo: data_len too large.\n"));
3097 END_PROFILE(SMBecho);
3098 return -1;
3101 /* copy any incoming data back out */
3102 if (data_len > 0)
3103 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
3105 if (smb_reverb > 100) {
3106 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3107 smb_reverb = 100;
3110 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3111 SSVAL(outbuf,smb_vwv0,seq_num);
3113 smb_setlen(outbuf,outsize - 4);
3115 if (!send_smb(smbd_server_fd(),outbuf))
3116 exit_server("reply_echo: send_smb failed.");
3119 DEBUG(3,("echo %d times\n", smb_reverb));
3121 smb_echo_count++;
3123 END_PROFILE(SMBecho);
3124 return -1;
3127 /****************************************************************************
3128 Reply to a printopen.
3129 ****************************************************************************/
3131 int reply_printopen(connection_struct *conn,
3132 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3134 int outsize = 0;
3135 files_struct *fsp;
3136 START_PROFILE(SMBsplopen);
3138 if (!CAN_PRINT(conn)) {
3139 END_PROFILE(SMBsplopen);
3140 return ERROR_DOS(ERRDOS,ERRnoaccess);
3143 /* Open for exclusive use, write only. */
3144 fsp = print_fsp_open(conn, NULL);
3146 if (!fsp) {
3147 END_PROFILE(SMBsplopen);
3148 return(UNIXERROR(ERRDOS,ERRnoaccess));
3151 outsize = set_message(outbuf,1,0,True);
3152 SSVAL(outbuf,smb_vwv0,fsp->fnum);
3154 DEBUG(3,("openprint fd=%d fnum=%d\n",
3155 fsp->fd, fsp->fnum));
3157 END_PROFILE(SMBsplopen);
3158 return(outsize);
3161 /****************************************************************************
3162 Reply to a printclose.
3163 ****************************************************************************/
3165 int reply_printclose(connection_struct *conn,
3166 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3168 int outsize = set_message(outbuf,0,0,True);
3169 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3170 int close_err = 0;
3171 START_PROFILE(SMBsplclose);
3173 CHECK_FSP(fsp,conn);
3175 if (!CAN_PRINT(conn)) {
3176 END_PROFILE(SMBsplclose);
3177 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
3180 DEBUG(3,("printclose fd=%d fnum=%d\n",
3181 fsp->fd,fsp->fnum));
3183 close_err = close_file(fsp,True);
3185 if(close_err != 0) {
3186 errno = close_err;
3187 END_PROFILE(SMBsplclose);
3188 return(UNIXERROR(ERRHRD,ERRgeneral));
3191 END_PROFILE(SMBsplclose);
3192 return(outsize);
3195 /****************************************************************************
3196 Reply to a printqueue.
3197 ****************************************************************************/
3199 int reply_printqueue(connection_struct *conn,
3200 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3202 int outsize = set_message(outbuf,2,3,True);
3203 int max_count = SVAL(inbuf,smb_vwv0);
3204 int start_index = SVAL(inbuf,smb_vwv1);
3205 START_PROFILE(SMBsplretq);
3207 /* we used to allow the client to get the cnum wrong, but that
3208 is really quite gross and only worked when there was only
3209 one printer - I think we should now only accept it if they
3210 get it right (tridge) */
3211 if (!CAN_PRINT(conn)) {
3212 END_PROFILE(SMBsplretq);
3213 return ERROR_DOS(ERRDOS,ERRnoaccess);
3216 SSVAL(outbuf,smb_vwv0,0);
3217 SSVAL(outbuf,smb_vwv1,0);
3218 SCVAL(smb_buf(outbuf),0,1);
3219 SSVAL(smb_buf(outbuf),1,0);
3221 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3222 start_index, max_count));
3225 print_queue_struct *queue = NULL;
3226 print_status_struct status;
3227 char *p = smb_buf(outbuf) + 3;
3228 int count = print_queue_status(SNUM(conn), &queue, &status);
3229 int num_to_get = ABS(max_count);
3230 int first = (max_count>0?start_index:start_index+max_count+1);
3231 int i;
3233 if (first >= count)
3234 num_to_get = 0;
3235 else
3236 num_to_get = MIN(num_to_get,count-first);
3239 for (i=first;i<first+num_to_get;i++) {
3240 put_dos_date2(p,0,queue[i].time);
3241 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
3242 SSVAL(p,5, queue[i].job);
3243 SIVAL(p,7,queue[i].size);
3244 SCVAL(p,11,0);
3245 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
3246 p += 28;
3249 if (count > 0) {
3250 outsize = set_message(outbuf,2,28*count+3,False);
3251 SSVAL(outbuf,smb_vwv0,count);
3252 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3253 SCVAL(smb_buf(outbuf),0,1);
3254 SSVAL(smb_buf(outbuf),1,28*count);
3257 SAFE_FREE(queue);
3259 DEBUG(3,("%d entries returned in queue\n",count));
3262 END_PROFILE(SMBsplretq);
3263 return(outsize);
3266 /****************************************************************************
3267 Reply to a printwrite.
3268 ****************************************************************************/
3270 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3272 int numtowrite;
3273 int outsize = set_message(outbuf,0,0,True);
3274 char *data;
3275 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3277 START_PROFILE(SMBsplwr);
3279 if (!CAN_PRINT(conn)) {
3280 END_PROFILE(SMBsplwr);
3281 return ERROR_DOS(ERRDOS,ERRnoaccess);
3284 CHECK_FSP(fsp,conn);
3285 CHECK_WRITE(fsp);
3287 numtowrite = SVAL(smb_buf(inbuf),1);
3288 data = smb_buf(inbuf) + 3;
3290 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3291 END_PROFILE(SMBsplwr);
3292 return(UNIXERROR(ERRHRD,ERRdiskfull));
3295 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3297 END_PROFILE(SMBsplwr);
3298 return(outsize);
3301 /****************************************************************************
3302 The guts of the mkdir command, split out so it may be called by the NT SMB
3303 code.
3304 ****************************************************************************/
3306 NTSTATUS mkdir_internal(connection_struct *conn, pstring directory)
3308 BOOL bad_path = False;
3309 SMB_STRUCT_STAT sbuf;
3310 int ret= -1;
3312 unix_convert(directory,conn,0,&bad_path,&sbuf);
3314 if( strchr_m(directory, ':')) {
3315 return NT_STATUS_NOT_A_DIRECTORY;
3318 if (ms_has_wild(directory)) {
3319 return NT_STATUS_OBJECT_NAME_INVALID;
3322 if (bad_path) {
3323 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3326 if (check_name(directory, conn))
3327 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
3329 if (ret == -1) {
3330 if(errno == ENOENT) {
3331 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3333 return map_nt_error_from_unix(errno);
3336 return NT_STATUS_OK;
3339 /****************************************************************************
3340 Reply to a mkdir.
3341 ****************************************************************************/
3343 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3345 pstring directory;
3346 int outsize;
3347 NTSTATUS status;
3348 START_PROFILE(SMBmkdir);
3350 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False);
3351 if (!NT_STATUS_IS_OK(status)) {
3352 END_PROFILE(SMBmkdir);
3353 return ERROR_NT(status);
3356 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
3358 status = mkdir_internal(conn, directory);
3359 if (!NT_STATUS_IS_OK(status)) {
3360 END_PROFILE(SMBmkdir);
3361 return ERROR_NT(status);
3364 outsize = set_message(outbuf,0,0,True);
3366 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3368 END_PROFILE(SMBmkdir);
3369 return(outsize);
3372 /****************************************************************************
3373 Static function used by reply_rmdir to delete an entire directory
3374 tree recursively. Return False on ok, True on fail.
3375 ****************************************************************************/
3377 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3379 const char *dname = NULL;
3380 BOOL ret = False;
3381 long offset = 0;
3382 struct smb_Dir *dir_hnd = OpenDir(conn, directory);
3384 if(dir_hnd == NULL)
3385 return True;
3387 while((dname = ReadDirName(dir_hnd, &offset))) {
3388 pstring fullname;
3389 SMB_STRUCT_STAT st;
3391 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3392 continue;
3394 if (!is_visible_file(conn, directory, dname, &st, False))
3395 continue;
3397 /* Construct the full name. */
3398 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3399 errno = ENOMEM;
3400 ret = True;
3401 break;
3404 pstrcpy(fullname, directory);
3405 pstrcat(fullname, "/");
3406 pstrcat(fullname, dname);
3408 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
3409 ret = True;
3410 break;
3413 if(st.st_mode & S_IFDIR) {
3414 if(recursive_rmdir(conn, fullname)!=0) {
3415 ret = True;
3416 break;
3418 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
3419 ret = True;
3420 break;
3422 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
3423 ret = True;
3424 break;
3427 CloseDir(dir_hnd);
3428 return ret;
3431 /****************************************************************************
3432 The internals of the rmdir code - called elsewhere.
3433 ****************************************************************************/
3435 BOOL rmdir_internals(connection_struct *conn, char *directory)
3437 BOOL ok;
3438 SMB_STRUCT_STAT st;
3440 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3441 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3443 * Check to see if the only thing in this directory are
3444 * vetoed files/directories. If so then delete them and
3445 * retry. If we fail to delete any of them (and we *don't*
3446 * do a recursive delete) then fail the rmdir.
3448 BOOL all_veto_files = True;
3449 const char *dname;
3450 struct smb_Dir *dir_hnd = OpenDir(conn, directory);
3452 if(dir_hnd != NULL) {
3453 long dirpos = TellDir(dir_hnd);
3454 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
3455 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3456 continue;
3457 if (!is_visible_file(conn, directory, dname, &st, False))
3458 continue;
3459 if(!IS_VETO_PATH(conn, dname)) {
3460 all_veto_files = False;
3461 break;
3465 if(all_veto_files) {
3466 SeekDir(dir_hnd,dirpos);
3467 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
3468 pstring fullname;
3470 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3471 continue;
3472 if (!is_visible_file(conn, directory, dname, &st, False))
3473 continue;
3475 /* Construct the full name. */
3476 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3477 errno = ENOMEM;
3478 break;
3481 pstrcpy(fullname, directory);
3482 pstrcat(fullname, "/");
3483 pstrcat(fullname, dname);
3485 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
3486 break;
3487 if(st.st_mode & S_IFDIR) {
3488 if(lp_recursive_veto_delete(SNUM(conn))) {
3489 if(recursive_rmdir(conn, fullname) != 0)
3490 break;
3492 if(SMB_VFS_RMDIR(conn,fullname) != 0)
3493 break;
3494 } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
3495 break;
3497 CloseDir(dir_hnd);
3498 /* Retry the rmdir */
3499 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3500 } else {
3501 CloseDir(dir_hnd);
3503 } else {
3504 errno = ENOTEMPTY;
3508 if (!ok)
3509 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
3511 return ok;
3514 /****************************************************************************
3515 Reply to a rmdir.
3516 ****************************************************************************/
3518 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3520 pstring directory;
3521 int outsize = 0;
3522 BOOL ok = False;
3523 BOOL bad_path = False;
3524 SMB_STRUCT_STAT sbuf;
3525 NTSTATUS status;
3526 START_PROFILE(SMBrmdir);
3528 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False);
3529 if (!NT_STATUS_IS_OK(status)) {
3530 END_PROFILE(SMBrmdir);
3531 return ERROR_NT(status);
3534 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3536 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3537 if (bad_path) {
3538 END_PROFILE(SMBrmdir);
3539 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3542 if (check_name(directory,conn)) {
3543 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3544 ok = rmdir_internals(conn, directory);
3547 if (!ok) {
3548 END_PROFILE(SMBrmdir);
3549 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRbadpath);
3552 outsize = set_message(outbuf,0,0,True);
3554 DEBUG( 3, ( "rmdir %s\n", directory ) );
3556 END_PROFILE(SMBrmdir);
3557 return(outsize);
3560 /*******************************************************************
3561 Resolve wildcards in a filename rename.
3562 Note that name is in UNIX charset and thus potentially can be more
3563 than fstring buffer (255 bytes) especially in default UTF-8 case.
3564 Therefore, we use pstring inside and all calls should ensure that
3565 name2 is at least pstring-long (they do already)
3566 ********************************************************************/
3568 static BOOL resolve_wildcards(const char *name1, char *name2)
3570 pstring root1,root2;
3571 pstring ext1,ext2;
3572 char *p,*p2, *pname1, *pname2;
3573 int available_space, actual_space;
3576 pname1 = strrchr_m(name1,'/');
3577 pname2 = strrchr_m(name2,'/');
3579 if (!pname1 || !pname2)
3580 return(False);
3582 pstrcpy(root1,pname1);
3583 pstrcpy(root2,pname2);
3584 p = strrchr_m(root1,'.');
3585 if (p) {
3586 *p = 0;
3587 pstrcpy(ext1,p+1);
3588 } else {
3589 pstrcpy(ext1,"");
3591 p = strrchr_m(root2,'.');
3592 if (p) {
3593 *p = 0;
3594 pstrcpy(ext2,p+1);
3595 } else {
3596 pstrcpy(ext2,"");
3599 p = root1;
3600 p2 = root2;
3601 while (*p2) {
3602 if (*p2 == '?') {
3603 *p2 = *p;
3604 p2++;
3605 } else if (*p2 == '*') {
3606 pstrcpy(p2, p);
3607 break;
3608 } else {
3609 p2++;
3611 if (*p)
3612 p++;
3615 p = ext1;
3616 p2 = ext2;
3617 while (*p2) {
3618 if (*p2 == '?') {
3619 *p2 = *p;
3620 p2++;
3621 } else if (*p2 == '*') {
3622 pstrcpy(p2, p);
3623 break;
3624 } else {
3625 p2++;
3627 if (*p)
3628 p++;
3631 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
3633 if (ext2[0]) {
3634 actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
3635 if (actual_space >= available_space - 1) {
3636 DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
3637 actual_space - available_space));
3639 } else {
3640 pstrcpy_base(pname2, root2, name2);
3643 return(True);
3646 /****************************************************************************
3647 Ensure open files have their names updates.
3648 ****************************************************************************/
3650 static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode, char *newname)
3652 files_struct *fsp;
3653 BOOL did_rename = False;
3655 for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
3656 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
3657 fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
3658 fsp->fsp_name, newname ));
3659 string_set(&fsp->fsp_name, newname);
3660 did_rename = True;
3663 if (!did_rename)
3664 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
3665 (unsigned int)dev, (double)inode, newname ));
3668 /****************************************************************************
3669 Rename an open file - given an fsp.
3670 ****************************************************************************/
3672 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, uint16 attrs, BOOL replace_if_exists)
3674 SMB_STRUCT_STAT sbuf;
3675 BOOL bad_path = False;
3676 pstring newname_last_component;
3677 NTSTATUS error = NT_STATUS_OK;
3678 BOOL dest_exists;
3679 BOOL rcdest = True;
3681 ZERO_STRUCT(sbuf);
3682 rcdest = unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf);
3684 /* Quick check for "." and ".." */
3685 if (!bad_path && newname_last_component[0] == '.') {
3686 if (!newname_last_component[1] || (newname_last_component[1] == '.' && !newname_last_component[2])) {
3687 return NT_STATUS_ACCESS_DENIED;
3690 if (!rcdest && bad_path) {
3691 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3694 /* Ensure newname contains a '/' */
3695 if(strrchr_m(newname,'/') == 0) {
3696 pstring tmpstr;
3698 pstrcpy(tmpstr, "./");
3699 pstrcat(tmpstr, newname);
3700 pstrcpy(newname, tmpstr);
3704 * Check for special case with case preserving and not
3705 * case sensitive. If the old last component differs from the original
3706 * last component only by case, then we should allow
3707 * the rename (user is trying to change the case of the
3708 * filename).
3711 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
3712 strequal(newname, fsp->fsp_name)) {
3713 char *p;
3714 pstring newname_modified_last_component;
3717 * Get the last component of the modified name.
3718 * Note that we guarantee that newname contains a '/'
3719 * character above.
3721 p = strrchr_m(newname,'/');
3722 pstrcpy(newname_modified_last_component,p+1);
3724 if(strcsequal(newname_modified_last_component,
3725 newname_last_component) == False) {
3727 * Replace the modified last component with
3728 * the original.
3730 pstrcpy(p+1, newname_last_component);
3735 * If the src and dest names are identical - including case,
3736 * don't do the rename, just return success.
3739 if (strcsequal(fsp->fsp_name, newname)) {
3740 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
3741 newname));
3742 return NT_STATUS_OK;
3745 dest_exists = vfs_object_exist(conn,newname,NULL);
3747 if(!replace_if_exists && dest_exists) {
3748 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
3749 fsp->fsp_name,newname));
3750 return NT_STATUS_OBJECT_NAME_COLLISION;
3753 error = can_rename(conn,newname,attrs,&sbuf);
3755 if (dest_exists && !NT_STATUS_IS_OK(error)) {
3756 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3757 nt_errstr(error), fsp->fsp_name,newname));
3758 if (NT_STATUS_EQUAL(error,NT_STATUS_SHARING_VIOLATION))
3759 error = NT_STATUS_ACCESS_DENIED;
3760 return error;
3763 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
3764 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
3765 fsp->fsp_name,newname));
3766 rename_open_files(conn, fsp->dev, fsp->inode, newname);
3767 return NT_STATUS_OK;
3770 if (errno == ENOTDIR || errno == EISDIR)
3771 error = NT_STATUS_OBJECT_NAME_COLLISION;
3772 else
3773 error = map_nt_error_from_unix(errno);
3775 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
3776 nt_errstr(error), fsp->fsp_name,newname));
3778 return error;
3781 /****************************************************************************
3782 The guts of the rename command, split out so it may be called by the NT SMB
3783 code.
3784 ****************************************************************************/
3786 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, uint16 attrs, BOOL replace_if_exists)
3788 pstring directory;
3789 pstring mask;
3790 pstring last_component_src;
3791 pstring last_component_dest;
3792 char *p;
3793 BOOL has_wild;
3794 BOOL bad_path_src = False;
3795 BOOL bad_path_dest = False;
3796 int count=0;
3797 NTSTATUS error = NT_STATUS_OK;
3798 BOOL rc = True;
3799 BOOL rcdest = True;
3800 SMB_STRUCT_STAT sbuf1, sbuf2;
3802 *directory = *mask = 0;
3804 ZERO_STRUCT(sbuf1);
3805 ZERO_STRUCT(sbuf2);
3807 rc = unix_convert(name,conn,last_component_src,&bad_path_src,&sbuf1);
3808 if (!rc && bad_path_src) {
3809 if (ms_has_wild(last_component_src))
3810 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3811 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3814 /* Quick check for "." and ".." */
3815 if (last_component_src[0] == '.') {
3816 if (!last_component_src[1] || (last_component_src[1] == '.' && !last_component_src[2])) {
3817 return NT_STATUS_OBJECT_NAME_INVALID;
3821 rcdest = unix_convert(newname,conn,last_component_dest,&bad_path_dest,&sbuf2);
3823 /* Quick check for "." and ".." */
3824 if (last_component_dest[0] == '.') {
3825 if (!last_component_dest[1] || (last_component_dest[1] == '.' && !last_component_dest[2])) {
3826 return NT_STATUS_OBJECT_NAME_INVALID;
3831 * Split the old name into directory and last component
3832 * strings. Note that unix_convert may have stripped off a
3833 * leading ./ from both name and newname if the rename is
3834 * at the root of the share. We need to make sure either both
3835 * name and newname contain a / character or neither of them do
3836 * as this is checked in resolve_wildcards().
3839 p = strrchr_m(name,'/');
3840 if (!p) {
3841 pstrcpy(directory,".");
3842 pstrcpy(mask,name);
3843 } else {
3844 *p = 0;
3845 pstrcpy(directory,name);
3846 pstrcpy(mask,p+1);
3847 *p = '/'; /* Replace needed for exceptional test below. */
3851 * We should only check the mangled cache
3852 * here if unix_convert failed. This means
3853 * that the path in 'mask' doesn't exist
3854 * on the file system and so we need to look
3855 * for a possible mangle. This patch from
3856 * Tine Smukavec <valentin.smukavec@hermes.si>.
3859 if (!rc && mangle_is_mangled(mask))
3860 mangle_check_cache( mask, sizeof(pstring)-1 );
3862 has_wild = ms_has_wild(mask);
3864 if (!has_wild) {
3866 * No wildcards - just process the one file.
3868 BOOL is_short_name = mangle_is_8_3(name, True);
3870 /* Add a terminating '/' to the directory name. */
3871 pstrcat(directory,"/");
3872 pstrcat(directory,mask);
3874 /* Ensure newname contains a '/' also */
3875 if(strrchr_m(newname,'/') == 0) {
3876 pstring tmpstr;
3878 pstrcpy(tmpstr, "./");
3879 pstrcat(tmpstr, newname);
3880 pstrcpy(newname, tmpstr);
3883 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
3884 directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
3885 conn->case_sensitive, conn->case_preserve, conn->short_case_preserve, directory,
3886 newname, last_component_dest, is_short_name));
3889 * Check for special case with case preserving and not
3890 * case sensitive, if directory and newname are identical,
3891 * and the old last component differs from the original
3892 * last component only by case, then we should allow
3893 * the rename (user is trying to change the case of the
3894 * filename).
3896 if((conn->case_sensitive == False) &&
3897 (((conn->case_preserve == True) &&
3898 (is_short_name == False)) ||
3899 ((conn->short_case_preserve == True) &&
3900 (is_short_name == True))) &&
3901 strcsequal(directory, newname)) {
3902 pstring modified_last_component;
3905 * Get the last component of the modified name.
3906 * Note that we guarantee that newname contains a '/'
3907 * character above.
3909 p = strrchr_m(newname,'/');
3910 pstrcpy(modified_last_component,p+1);
3912 if(strcsequal(modified_last_component,
3913 last_component_dest) == False) {
3915 * Replace the modified last component with
3916 * the original.
3918 pstrcpy(p+1, last_component_dest);
3922 resolve_wildcards(directory,newname);
3925 * The source object must exist.
3928 if (!vfs_object_exist(conn, directory, &sbuf1)) {
3929 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
3930 directory,newname));
3932 if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
3934 * Must return different errors depending on whether the parent
3935 * directory existed or not.
3938 p = strrchr_m(directory, '/');
3939 if (!p)
3940 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3941 *p = '\0';
3942 if (vfs_object_exist(conn, directory, NULL))
3943 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3944 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3946 error = map_nt_error_from_unix(errno);
3947 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3948 nt_errstr(error), directory,newname));
3950 return error;
3953 if (!rcdest && bad_path_dest) {
3954 if (ms_has_wild(last_component_dest))
3955 return NT_STATUS_OBJECT_NAME_INVALID;
3956 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3959 error = can_rename(conn,directory,attrs,&sbuf1);
3961 if (!NT_STATUS_IS_OK(error)) {
3962 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3963 nt_errstr(error), directory,newname));
3964 return error;
3968 * If the src and dest names are identical - including case,
3969 * don't do the rename, just return success.
3972 if (strcsequal(directory, newname)) {
3973 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3974 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
3975 return NT_STATUS_OK;
3978 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
3979 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
3980 directory,newname));
3981 return NT_STATUS_OBJECT_NAME_COLLISION;
3984 if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
3985 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
3986 directory,newname));
3987 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3988 return NT_STATUS_OK;
3991 if (errno == ENOTDIR || errno == EISDIR)
3992 error = NT_STATUS_OBJECT_NAME_COLLISION;
3993 else
3994 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;
4000 } else {
4002 * Wildcards - process each file that matches.
4004 struct smb_Dir *dir_hnd = NULL;
4005 const char *dname;
4006 pstring destname;
4008 if (check_name(directory,conn))
4009 dir_hnd = OpenDir(conn, directory);
4011 if (dir_hnd) {
4012 long offset = 0;
4013 error = NT_STATUS_NO_SUCH_FILE;
4014 /* Was error = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */
4016 if (strequal(mask,"????????.???"))
4017 pstrcpy(mask,"*");
4019 while ((dname = ReadDirName(dir_hnd, &offset))) {
4020 pstring fname;
4021 BOOL sysdir_entry = False;
4023 pstrcpy(fname,dname);
4025 /* Quick check for "." and ".." */
4026 if (fname[0] == '.') {
4027 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
4028 if (attrs & aDIR) {
4029 sysdir_entry = True;
4030 } else {
4031 continue;
4036 if (!is_visible_file(conn, directory, dname, &sbuf1, False))
4037 continue;
4039 if(!mask_match(fname, mask, conn->case_sensitive))
4040 continue;
4042 if (sysdir_entry) {
4043 error = NT_STATUS_OBJECT_NAME_INVALID;
4044 break;
4047 error = NT_STATUS_ACCESS_DENIED;
4048 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
4049 if (!vfs_object_exist(conn, fname, &sbuf1)) {
4050 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4051 DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
4052 continue;
4054 error = can_rename(conn,fname,attrs,&sbuf1);
4055 if (!NT_STATUS_IS_OK(error)) {
4056 DEBUG(6,("rename %s refused\n", fname));
4057 continue;
4059 pstrcpy(destname,newname);
4061 if (!resolve_wildcards(fname,destname)) {
4062 DEBUG(6,("resolve_wildcards %s %s failed\n",
4063 fname, destname));
4064 continue;
4067 if (strcsequal(fname,destname)) {
4068 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4069 DEBUG(3,("rename_internals: identical names in wildcard rename %s - success\n", fname));
4070 count++;
4071 error = NT_STATUS_OK;
4072 continue;
4075 if (!replace_if_exists &&
4076 vfs_file_exist(conn,destname, NULL)) {
4077 DEBUG(6,("file_exist %s\n", destname));
4078 error = NT_STATUS_OBJECT_NAME_COLLISION;
4079 continue;
4082 if (!SMB_VFS_RENAME(conn,fname,destname)) {
4083 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4084 count++;
4085 error = NT_STATUS_OK;
4087 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
4089 CloseDir(dir_hnd);
4092 if (!NT_STATUS_EQUAL(error,NT_STATUS_NO_SUCH_FILE)) {
4093 if (!rcdest && bad_path_dest) {
4094 if (ms_has_wild(last_component_dest))
4095 return NT_STATUS_OBJECT_NAME_INVALID;
4096 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4101 if (count == 0 && NT_STATUS_IS_OK(error)) {
4102 error = map_nt_error_from_unix(errno);
4105 return error;
4108 /****************************************************************************
4109 Reply to a mv.
4110 ****************************************************************************/
4112 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
4113 int dum_buffsize)
4115 int outsize = 0;
4116 pstring name;
4117 pstring newname;
4118 char *p;
4119 uint16 attrs = SVAL(inbuf,smb_vwv0);
4120 NTSTATUS status;
4122 START_PROFILE(SMBmv);
4124 p = smb_buf(inbuf) + 1;
4125 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True);
4126 if (!NT_STATUS_IS_OK(status)) {
4127 END_PROFILE(SMBmv);
4128 return ERROR_NT(status);
4130 p++;
4131 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True);
4132 if (!NT_STATUS_IS_OK(status)) {
4133 END_PROFILE(SMBmv);
4134 return ERROR_NT(status);
4137 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
4138 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4140 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
4142 status = rename_internals(conn, name, newname, attrs, False);
4143 if (!NT_STATUS_IS_OK(status)) {
4144 END_PROFILE(SMBmv);
4145 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4146 /* We have re-scheduled this call. */
4147 clear_cached_errors();
4148 return -1;
4150 return ERROR_NT(status);
4154 * Win2k needs a changenotify request response before it will
4155 * update after a rename..
4157 process_pending_change_notify_queue((time_t)0);
4158 outsize = set_message(outbuf,0,0,True);
4160 END_PROFILE(SMBmv);
4161 return(outsize);
4164 /*******************************************************************
4165 Copy a file as part of a reply_copy.
4166 ******************************************************************/
4168 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
4169 int count,BOOL target_is_directory, int *err_ret)
4171 int Access,action;
4172 SMB_STRUCT_STAT src_sbuf, sbuf2;
4173 SMB_OFF_T ret=-1;
4174 files_struct *fsp1,*fsp2;
4175 pstring dest;
4176 uint32 dosattrs;
4178 *err_ret = 0;
4180 pstrcpy(dest,dest1);
4181 if (target_is_directory) {
4182 char *p = strrchr_m(src,'/');
4183 if (p)
4184 p++;
4185 else
4186 p = src;
4187 pstrcat(dest,"/");
4188 pstrcat(dest,p);
4191 if (!vfs_file_exist(conn,src,&src_sbuf))
4192 return(False);
4194 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
4195 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),FILE_ATTRIBUTE_NORMAL,INTERNAL_OPEN_ONLY,
4196 &Access,&action);
4198 if (!fsp1)
4199 return(False);
4201 if (!target_is_directory && count)
4202 ofun = FILE_EXISTS_OPEN;
4204 dosattrs = dos_mode(conn, src, &src_sbuf);
4205 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1)
4206 ZERO_STRUCTP(&sbuf2);
4208 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
4209 ofun,dosattrs,INTERNAL_OPEN_ONLY,&Access,&action);
4211 if (!fsp2) {
4212 close_file(fsp1,False);
4213 return(False);
4216 if ((ofun&3) == 1) {
4217 if(SMB_VFS_LSEEK(fsp2,fsp2->fd,0,SEEK_END) == -1) {
4218 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
4220 * Stop the copy from occurring.
4222 ret = -1;
4223 src_sbuf.st_size = 0;
4227 if (src_sbuf.st_size)
4228 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
4230 close_file(fsp1,False);
4232 /* Ensure the modtime is set correctly on the destination file. */
4233 fsp_set_pending_modtime( fsp2, src_sbuf.st_mtime);
4236 * As we are opening fsp1 read-only we only expect
4237 * an error on close on fsp2 if we are out of space.
4238 * Thus we don't look at the error return from the
4239 * close of fsp1.
4241 *err_ret = close_file(fsp2,False);
4243 return(ret == (SMB_OFF_T)src_sbuf.st_size);
4246 /****************************************************************************
4247 Reply to a file copy.
4248 ****************************************************************************/
4250 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4252 int outsize = 0;
4253 pstring name;
4254 pstring directory;
4255 pstring mask,newname;
4256 char *p;
4257 int count=0;
4258 int error = ERRnoaccess;
4259 int err = 0;
4260 BOOL has_wild;
4261 BOOL exists=False;
4262 int tid2 = SVAL(inbuf,smb_vwv0);
4263 int ofun = SVAL(inbuf,smb_vwv1);
4264 int flags = SVAL(inbuf,smb_vwv2);
4265 BOOL target_is_directory=False;
4266 BOOL bad_path1 = False;
4267 BOOL bad_path2 = False;
4268 BOOL rc = True;
4269 SMB_STRUCT_STAT sbuf1, sbuf2;
4270 NTSTATUS status;
4272 START_PROFILE(SMBcopy);
4274 *directory = *mask = 0;
4276 p = smb_buf(inbuf);
4277 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True);
4278 if (!NT_STATUS_IS_OK(status)) {
4279 END_PROFILE(SMBcopy);
4280 return ERROR_NT(status);
4282 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True);
4283 if (!NT_STATUS_IS_OK(status)) {
4284 END_PROFILE(SMBcopy);
4285 return ERROR_NT(status);
4288 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
4290 if (tid2 != conn->cnum) {
4291 /* can't currently handle inter share copies XXXX */
4292 DEBUG(3,("Rejecting inter-share copy\n"));
4293 END_PROFILE(SMBcopy);
4294 return ERROR_DOS(ERRSRV,ERRinvdevice);
4297 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
4298 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4300 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
4301 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
4303 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
4305 if ((flags&1) && target_is_directory) {
4306 END_PROFILE(SMBcopy);
4307 return ERROR_DOS(ERRDOS,ERRbadfile);
4310 if ((flags&2) && !target_is_directory) {
4311 END_PROFILE(SMBcopy);
4312 return ERROR_DOS(ERRDOS,ERRbadpath);
4315 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
4316 /* wants a tree copy! XXXX */
4317 DEBUG(3,("Rejecting tree copy\n"));
4318 END_PROFILE(SMBcopy);
4319 return ERROR_DOS(ERRSRV,ERRerror);
4322 p = strrchr_m(name,'/');
4323 if (!p) {
4324 pstrcpy(directory,"./");
4325 pstrcpy(mask,name);
4326 } else {
4327 *p = 0;
4328 pstrcpy(directory,name);
4329 pstrcpy(mask,p+1);
4333 * We should only check the mangled cache
4334 * here if unix_convert failed. This means
4335 * that the path in 'mask' doesn't exist
4336 * on the file system and so we need to look
4337 * for a possible mangle. This patch from
4338 * Tine Smukavec <valentin.smukavec@hermes.si>.
4341 if (!rc && mangle_is_mangled(mask))
4342 mangle_check_cache( mask, sizeof(pstring)-1 );
4344 has_wild = ms_has_wild(mask);
4346 if (!has_wild) {
4347 pstrcat(directory,"/");
4348 pstrcat(directory,mask);
4349 if (resolve_wildcards(directory,newname) &&
4350 copy_file(directory,newname,conn,ofun, count,target_is_directory,&err))
4351 count++;
4352 if(!count && err) {
4353 errno = err;
4354 END_PROFILE(SMBcopy);
4355 return(UNIXERROR(ERRHRD,ERRgeneral));
4357 if (!count) {
4358 exists = vfs_file_exist(conn,directory,NULL);
4360 } else {
4361 struct smb_Dir *dir_hnd = NULL;
4362 const char *dname;
4363 pstring destname;
4365 if (check_name(directory,conn))
4366 dir_hnd = OpenDir(conn, directory);
4368 if (dir_hnd) {
4369 long offset = 0;
4370 error = ERRbadfile;
4372 if (strequal(mask,"????????.???"))
4373 pstrcpy(mask,"*");
4375 while ((dname = ReadDirName(dir_hnd, &offset))) {
4376 pstring fname;
4377 pstrcpy(fname,dname);
4379 if (!is_visible_file(conn, directory, dname, &sbuf1, False))
4380 continue;
4382 if(!mask_match(fname, mask, conn->case_sensitive))
4383 continue;
4385 error = ERRnoaccess;
4386 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
4387 pstrcpy(destname,newname);
4388 if (resolve_wildcards(fname,destname) &&
4389 copy_file(fname,destname,conn,ofun,
4390 count,target_is_directory,&err))
4391 count++;
4392 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
4394 CloseDir(dir_hnd);
4398 if (count == 0) {
4399 if(err) {
4400 /* Error on close... */
4401 errno = err;
4402 END_PROFILE(SMBcopy);
4403 return(UNIXERROR(ERRHRD,ERRgeneral));
4406 if (exists) {
4407 END_PROFILE(SMBcopy);
4408 return ERROR_DOS(ERRDOS,error);
4409 } else {
4410 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
4411 unix_ERR_class = ERRDOS;
4412 unix_ERR_code = ERRbadpath;
4414 END_PROFILE(SMBcopy);
4415 return(UNIXERROR(ERRDOS,error));
4419 outsize = set_message(outbuf,1,0,True);
4420 SSVAL(outbuf,smb_vwv0,count);
4422 END_PROFILE(SMBcopy);
4423 return(outsize);
4426 /****************************************************************************
4427 Reply to a setdir.
4428 ****************************************************************************/
4430 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4432 int snum;
4433 int outsize = 0;
4434 BOOL ok = False;
4435 pstring newdir;
4436 NTSTATUS status;
4438 START_PROFILE(pathworks_setdir);
4440 snum = SNUM(conn);
4441 if (!CAN_SETDIR(snum)) {
4442 END_PROFILE(pathworks_setdir);
4443 return ERROR_DOS(ERRDOS,ERRnoaccess);
4446 srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status, False);
4447 if (!NT_STATUS_IS_OK(status)) {
4448 END_PROFILE(pathworks_setdir);
4449 return ERROR_NT(status);
4452 if (strlen(newdir) == 0) {
4453 ok = True;
4454 } else {
4455 ok = vfs_directory_exist(conn,newdir,NULL);
4456 if (ok)
4457 string_set(&conn->connectpath,newdir);
4460 if (!ok) {
4461 END_PROFILE(pathworks_setdir);
4462 return ERROR_DOS(ERRDOS,ERRbadpath);
4465 outsize = set_message(outbuf,0,0,True);
4466 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
4468 DEBUG(3,("setdir %s\n", newdir));
4470 END_PROFILE(pathworks_setdir);
4471 return(outsize);
4474 /****************************************************************************
4475 Get a lock pid, dealing with large count requests.
4476 ****************************************************************************/
4478 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
4480 if(!large_file_format)
4481 return SVAL(data,SMB_LPID_OFFSET(data_offset));
4482 else
4483 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
4486 /****************************************************************************
4487 Get a lock count, dealing with large count requests.
4488 ****************************************************************************/
4490 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4492 SMB_BIG_UINT count = 0;
4494 if(!large_file_format) {
4495 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4496 } else {
4498 #if defined(HAVE_LONGLONG)
4499 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4500 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4501 #else /* HAVE_LONGLONG */
4504 * NT4.x seems to be broken in that it sends large file (64 bit)
4505 * lockingX calls even if the CAP_LARGE_FILES was *not*
4506 * negotiated. For boxes without large unsigned ints truncate the
4507 * lock count by dropping the top 32 bits.
4510 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4511 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4512 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4513 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4514 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4517 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4518 #endif /* HAVE_LONGLONG */
4521 return count;
4524 #if !defined(HAVE_LONGLONG)
4525 /****************************************************************************
4526 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
4527 ****************************************************************************/
4529 static uint32 map_lock_offset(uint32 high, uint32 low)
4531 unsigned int i;
4532 uint32 mask = 0;
4533 uint32 highcopy = high;
4536 * Try and find out how many significant bits there are in high.
4539 for(i = 0; highcopy; i++)
4540 highcopy >>= 1;
4543 * We use 31 bits not 32 here as POSIX
4544 * lock offsets may not be negative.
4547 mask = (~0) << (31 - i);
4549 if(low & mask)
4550 return 0; /* Fail. */
4552 high <<= (31 - i);
4554 return (high|low);
4556 #endif /* !defined(HAVE_LONGLONG) */
4558 /****************************************************************************
4559 Get a lock offset, dealing with large offset requests.
4560 ****************************************************************************/
4562 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4564 SMB_BIG_UINT offset = 0;
4566 *err = False;
4568 if(!large_file_format) {
4569 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4570 } else {
4572 #if defined(HAVE_LONGLONG)
4573 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4574 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4575 #else /* HAVE_LONGLONG */
4578 * NT4.x seems to be broken in that it sends large file (64 bit)
4579 * lockingX calls even if the CAP_LARGE_FILES was *not*
4580 * negotiated. For boxes without large unsigned ints mangle the
4581 * lock offset by mapping the top 32 bits onto the lower 32.
4584 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4585 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4586 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4587 uint32 new_low = 0;
4589 if((new_low = map_lock_offset(high, low)) == 0) {
4590 *err = True;
4591 return (SMB_BIG_UINT)-1;
4594 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4595 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4596 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4597 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4600 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4601 #endif /* HAVE_LONGLONG */
4604 return offset;
4607 /****************************************************************************
4608 Reply to a lockingX request.
4609 ****************************************************************************/
4611 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4613 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4614 unsigned char locktype = CVAL(inbuf,smb_vwv3);
4615 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4616 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4617 uint16 num_locks = SVAL(inbuf,smb_vwv7);
4618 SMB_BIG_UINT count = 0, offset = 0;
4619 uint16 lock_pid;
4620 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4621 int i;
4622 char *data;
4623 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4624 BOOL err;
4625 BOOL my_lock_ctx = False;
4626 NTSTATUS status;
4628 START_PROFILE(SMBlockingX);
4630 CHECK_FSP(fsp,conn);
4632 data = smb_buf(inbuf);
4634 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
4635 /* we don't support these - and CANCEL_LOCK makes w2k
4636 and XP reboot so I don't really want to be
4637 compatible! (tridge) */
4638 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
4641 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
4642 /* Need to make this like a cancel.... JRA. */
4643 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
4646 /* Check if this is an oplock break on a file
4647 we have granted an oplock on.
4649 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
4650 /* Client can insist on breaking to none. */
4651 BOOL break_to_none = (oplocklevel == 0);
4653 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4654 (unsigned int)oplocklevel, fsp->fnum ));
4657 * Make sure we have granted an exclusive or batch oplock on this file.
4660 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
4661 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4662 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4664 /* if this is a pure oplock break request then don't send a reply */
4665 if (num_locks == 0 && num_ulocks == 0) {
4666 END_PROFILE(SMBlockingX);
4667 return -1;
4668 } else {
4669 END_PROFILE(SMBlockingX);
4670 return ERROR_DOS(ERRDOS,ERRlock);
4674 if (remove_oplock(fsp, break_to_none) == False) {
4675 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4676 fsp->fsp_name ));
4679 /* if this is a pure oplock break request then don't send a reply */
4680 if (num_locks == 0 && num_ulocks == 0) {
4681 /* Sanity check - ensure a pure oplock break is not a
4682 chained request. */
4683 if(CVAL(inbuf,smb_vwv0) != 0xff)
4684 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4685 (unsigned int)CVAL(inbuf,smb_vwv0) ));
4686 END_PROFILE(SMBlockingX);
4687 return -1;
4692 * We do this check *after* we have checked this is not a oplock break
4693 * response message. JRA.
4696 release_level_2_oplocks_on_change(fsp);
4698 /* Data now points at the beginning of the list
4699 of smb_unlkrng structs */
4700 for(i = 0; i < (int)num_ulocks; i++) {
4701 lock_pid = get_lock_pid( data, i, large_file_format);
4702 count = get_lock_count( data, i, large_file_format);
4703 offset = get_lock_offset( data, i, large_file_format, &err);
4706 * There is no error code marked "stupid client bug".... :-).
4708 if(err) {
4709 END_PROFILE(SMBlockingX);
4710 return ERROR_DOS(ERRDOS,ERRnoaccess);
4713 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4714 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4716 status = do_unlock(fsp,conn,lock_pid,count,offset);
4717 if (NT_STATUS_V(status)) {
4718 END_PROFILE(SMBlockingX);
4719 return ERROR_NT(status);
4723 /* Setup the timeout in seconds. */
4725 lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000);
4727 /* Now do any requested locks */
4728 data += ((large_file_format ? 20 : 10)*num_ulocks);
4730 /* Data now points at the beginning of the list
4731 of smb_lkrng structs */
4733 for(i = 0; i < (int)num_locks; i++) {
4734 lock_pid = get_lock_pid( data, i, large_file_format);
4735 count = get_lock_count( data, i, large_file_format);
4736 offset = get_lock_offset( data, i, large_file_format, &err);
4739 * There is no error code marked "stupid client bug".... :-).
4741 if(err) {
4742 END_PROFILE(SMBlockingX);
4743 return ERROR_DOS(ERRDOS,ERRnoaccess);
4746 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
4747 (double)offset, (double)count, (unsigned int)lock_pid,
4748 fsp->fsp_name, (int)lock_timeout ));
4750 status = do_lock_spin(fsp,conn,lock_pid, count,offset,
4751 ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &my_lock_ctx);
4752 if (NT_STATUS_V(status)) {
4754 * Interesting fact found by IFSTEST /t LockOverlappedTest...
4755 * Even if it's our own lock context, we need to wait here as
4756 * there may be an unlock on the way.
4757 * So I removed a "&& !my_lock_ctx" from the following
4758 * if statement. JRA.
4760 if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
4762 * A blocking lock was requested. Package up
4763 * this smb into a queued request and push it
4764 * onto the blocking lock queue.
4766 if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) {
4767 END_PROFILE(SMBlockingX);
4768 return -1;
4771 break;
4775 /* If any of the above locks failed, then we must unlock
4776 all of the previous locks (X/Open spec). */
4777 if (i != num_locks && num_locks != 0) {
4779 * Ensure we don't do a remove on the lock that just failed,
4780 * as under POSIX rules, if we have a lock already there, we
4781 * will delete it (and we shouldn't) .....
4783 for(i--; i >= 0; i--) {
4784 lock_pid = get_lock_pid( data, i, large_file_format);
4785 count = get_lock_count( data, i, large_file_format);
4786 offset = get_lock_offset( data, i, large_file_format, &err);
4789 * There is no error code marked "stupid client bug".... :-).
4791 if(err) {
4792 END_PROFILE(SMBlockingX);
4793 return ERROR_DOS(ERRDOS,ERRnoaccess);
4796 do_unlock(fsp,conn,lock_pid,count,offset);
4798 END_PROFILE(SMBlockingX);
4799 return ERROR_NT(status);
4802 set_message(outbuf,2,0,True);
4804 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4805 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4807 END_PROFILE(SMBlockingX);
4808 return chain_reply(inbuf,outbuf,length,bufsize);
4811 /****************************************************************************
4812 Reply to a SMBreadbmpx (read block multiplex) request.
4813 ****************************************************************************/
4815 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4817 ssize_t nread = -1;
4818 ssize_t total_read;
4819 char *data;
4820 SMB_OFF_T startpos;
4821 int outsize;
4822 size_t maxcount;
4823 int max_per_packet;
4824 size_t tcount;
4825 int pad;
4826 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4827 START_PROFILE(SMBreadBmpx);
4829 /* this function doesn't seem to work - disable by default */
4830 if (!lp_readbmpx()) {
4831 END_PROFILE(SMBreadBmpx);
4832 return ERROR_DOS(ERRSRV,ERRuseSTD);
4835 outsize = set_message(outbuf,8,0,True);
4837 CHECK_FSP(fsp,conn);
4838 CHECK_READ(fsp);
4840 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
4841 maxcount = SVAL(inbuf,smb_vwv3);
4843 data = smb_buf(outbuf);
4844 pad = ((long)data)%4;
4845 if (pad)
4846 pad = 4 - pad;
4847 data += pad;
4849 max_per_packet = bufsize-(outsize+pad);
4850 tcount = maxcount;
4851 total_read = 0;
4853 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
4854 END_PROFILE(SMBreadBmpx);
4855 return ERROR_DOS(ERRDOS,ERRlock);
4858 do {
4859 size_t N = MIN(max_per_packet,tcount-total_read);
4861 nread = read_file(fsp,data,startpos,N);
4863 if (nread <= 0)
4864 nread = 0;
4866 if (nread < (ssize_t)N)
4867 tcount = total_read + nread;
4869 set_message(outbuf,8,nread,False);
4870 SIVAL(outbuf,smb_vwv0,startpos);
4871 SSVAL(outbuf,smb_vwv2,tcount);
4872 SSVAL(outbuf,smb_vwv6,nread);
4873 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4875 if (!send_smb(smbd_server_fd(),outbuf))
4876 exit_server("reply_readbmpx: send_smb failed.");
4878 total_read += nread;
4879 startpos += nread;
4880 } while (total_read < (ssize_t)tcount);
4882 END_PROFILE(SMBreadBmpx);
4883 return(-1);
4886 /****************************************************************************
4887 Reply to a SMBsetattrE.
4888 ****************************************************************************/
4890 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4892 struct utimbuf unix_times;
4893 int outsize = 0;
4894 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4895 START_PROFILE(SMBsetattrE);
4897 outsize = set_message(outbuf,0,0,True);
4899 if(!fsp || (fsp->conn != conn)) {
4900 END_PROFILE(SMBgetattrE);
4901 return ERROR_DOS(ERRDOS,ERRbadfid);
4905 * Convert the DOS times into unix times. Ignore create
4906 * time as UNIX can't set this.
4909 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4910 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4913 * Patch from Ray Frush <frush@engr.colostate.edu>
4914 * Sometimes times are sent as zero - ignore them.
4917 if (null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) {
4918 /* Ignore request */
4919 if( DEBUGLVL( 3 ) ) {
4920 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4921 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4923 END_PROFILE(SMBsetattrE);
4924 return(outsize);
4925 } else if (!null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) {
4926 /* set modify time = to access time if modify time was unset */
4927 unix_times.modtime = unix_times.actime;
4930 /* Set the date on this file */
4931 /* Should we set pending modtime here ? JRA */
4932 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4933 END_PROFILE(SMBsetattrE);
4934 return ERROR_DOS(ERRDOS,ERRnoaccess);
4937 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4938 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4940 END_PROFILE(SMBsetattrE);
4941 return(outsize);
4945 /* Back from the dead for OS/2..... JRA. */
4947 /****************************************************************************
4948 Reply to a SMBwritebmpx (write block multiplex primary) request.
4949 ****************************************************************************/
4951 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4953 size_t numtowrite;
4954 ssize_t nwritten = -1;
4955 int outsize = 0;
4956 SMB_OFF_T startpos;
4957 size_t tcount;
4958 BOOL write_through;
4959 int smb_doff;
4960 char *data;
4961 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4962 START_PROFILE(SMBwriteBmpx);
4964 CHECK_FSP(fsp,conn);
4965 CHECK_WRITE(fsp);
4966 CHECK_ERROR(fsp);
4968 tcount = SVAL(inbuf,smb_vwv1);
4969 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
4970 write_through = BITSETW(inbuf+smb_vwv7,0);
4971 numtowrite = SVAL(inbuf,smb_vwv10);
4972 smb_doff = SVAL(inbuf,smb_vwv11);
4974 data = smb_base(inbuf) + smb_doff;
4976 /* If this fails we need to send an SMBwriteC response,
4977 not an SMBwritebmpx - set this up now so we don't forget */
4978 SCVAL(outbuf,smb_com,SMBwritec);
4980 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) {
4981 END_PROFILE(SMBwriteBmpx);
4982 return(ERROR_DOS(ERRDOS,ERRlock));
4985 nwritten = write_file(fsp,data,startpos,numtowrite);
4987 if(lp_syncalways(SNUM(conn)) || write_through)
4988 sync_file(conn,fsp);
4990 if(nwritten < (ssize_t)numtowrite) {
4991 END_PROFILE(SMBwriteBmpx);
4992 return(UNIXERROR(ERRHRD,ERRdiskfull));
4995 /* If the maximum to be written to this file
4996 is greater than what we just wrote then set
4997 up a secondary struct to be attached to this
4998 fd, we will use this to cache error messages etc. */
5000 if((ssize_t)tcount > nwritten) {
5001 write_bmpx_struct *wbms;
5002 if(fsp->wbmpx_ptr != NULL)
5003 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
5004 else
5005 wbms = SMB_MALLOC_P(write_bmpx_struct);
5006 if(!wbms) {
5007 DEBUG(0,("Out of memory in reply_readmpx\n"));
5008 END_PROFILE(SMBwriteBmpx);
5009 return(ERROR_DOS(ERRSRV,ERRnoresource));
5011 wbms->wr_mode = write_through;
5012 wbms->wr_discard = False; /* No errors yet */
5013 wbms->wr_total_written = nwritten;
5014 wbms->wr_errclass = 0;
5015 wbms->wr_error = 0;
5016 fsp->wbmpx_ptr = wbms;
5019 /* We are returning successfully, set the message type back to
5020 SMBwritebmpx */
5021 SCVAL(outbuf,smb_com,SMBwriteBmpx);
5023 outsize = set_message(outbuf,1,0,True);
5025 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
5027 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
5028 fsp->fnum, (int)numtowrite, (int)nwritten ) );
5030 if (write_through && tcount==nwritten) {
5031 /* We need to send both a primary and a secondary response */
5032 smb_setlen(outbuf,outsize - 4);
5033 if (!send_smb(smbd_server_fd(),outbuf))
5034 exit_server("reply_writebmpx: send_smb failed.");
5036 /* Now the secondary */
5037 outsize = set_message(outbuf,1,0,True);
5038 SCVAL(outbuf,smb_com,SMBwritec);
5039 SSVAL(outbuf,smb_vwv0,nwritten);
5042 END_PROFILE(SMBwriteBmpx);
5043 return(outsize);
5046 /****************************************************************************
5047 Reply to a SMBwritebs (write block multiplex secondary) request.
5048 ****************************************************************************/
5050 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5052 size_t numtowrite;
5053 ssize_t nwritten = -1;
5054 int outsize = 0;
5055 SMB_OFF_T startpos;
5056 size_t tcount;
5057 BOOL write_through;
5058 int smb_doff;
5059 char *data;
5060 write_bmpx_struct *wbms;
5061 BOOL send_response = False;
5062 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5063 START_PROFILE(SMBwriteBs);
5065 CHECK_FSP(fsp,conn);
5066 CHECK_WRITE(fsp);
5068 tcount = SVAL(inbuf,smb_vwv1);
5069 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
5070 numtowrite = SVAL(inbuf,smb_vwv6);
5071 smb_doff = SVAL(inbuf,smb_vwv7);
5073 data = smb_base(inbuf) + smb_doff;
5075 /* We need to send an SMBwriteC response, not an SMBwritebs */
5076 SCVAL(outbuf,smb_com,SMBwritec);
5078 /* This fd should have an auxiliary struct attached,
5079 check that it does */
5080 wbms = fsp->wbmpx_ptr;
5081 if(!wbms) {
5082 END_PROFILE(SMBwriteBs);
5083 return(-1);
5086 /* If write through is set we can return errors, else we must cache them */
5087 write_through = wbms->wr_mode;
5089 /* Check for an earlier error */
5090 if(wbms->wr_discard) {
5091 END_PROFILE(SMBwriteBs);
5092 return -1; /* Just discard the packet */
5095 nwritten = write_file(fsp,data,startpos,numtowrite);
5097 if(lp_syncalways(SNUM(conn)) || write_through)
5098 sync_file(conn,fsp);
5100 if (nwritten < (ssize_t)numtowrite) {
5101 if(write_through) {
5102 /* We are returning an error - we can delete the aux struct */
5103 if (wbms)
5104 free((char *)wbms);
5105 fsp->wbmpx_ptr = NULL;
5106 END_PROFILE(SMBwriteBs);
5107 return(ERROR_DOS(ERRHRD,ERRdiskfull));
5109 END_PROFILE(SMBwriteBs);
5110 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
5113 /* Increment the total written, if this matches tcount
5114 we can discard the auxiliary struct (hurrah !) and return a writeC */
5115 wbms->wr_total_written += nwritten;
5116 if(wbms->wr_total_written >= tcount) {
5117 if (write_through) {
5118 outsize = set_message(outbuf,1,0,True);
5119 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
5120 send_response = True;
5123 free((char *)wbms);
5124 fsp->wbmpx_ptr = NULL;
5127 if(send_response) {
5128 END_PROFILE(SMBwriteBs);
5129 return(outsize);
5132 END_PROFILE(SMBwriteBs);
5133 return(-1);
5136 /****************************************************************************
5137 Reply to a SMBgetattrE.
5138 ****************************************************************************/
5140 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5142 SMB_STRUCT_STAT sbuf;
5143 int outsize = 0;
5144 int mode;
5145 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5146 START_PROFILE(SMBgetattrE);
5148 outsize = set_message(outbuf,11,0,True);
5150 if(!fsp || (fsp->conn != conn)) {
5151 END_PROFILE(SMBgetattrE);
5152 return ERROR_DOS(ERRDOS,ERRbadfid);
5155 /* Do an fstat on this file */
5156 if(fsp_stat(fsp, &sbuf)) {
5157 END_PROFILE(SMBgetattrE);
5158 return(UNIXERROR(ERRDOS,ERRnoaccess));
5161 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
5164 * Convert the times into dos times. Set create
5165 * date to be last modify date as UNIX doesn't save
5166 * this.
5169 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
5170 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
5171 /* Should we check pending modtime here ? JRA */
5172 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
5174 if (mode & aDIR) {
5175 SIVAL(outbuf,smb_vwv6,0);
5176 SIVAL(outbuf,smb_vwv8,0);
5177 } else {
5178 uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf);
5179 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
5180 SIVAL(outbuf,smb_vwv8,allocation_size);
5182 SSVAL(outbuf,smb_vwv10, mode);
5184 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
5186 END_PROFILE(SMBgetattrE);
5187 return(outsize);