r5555: current with 3.0 tree as of r5548; getting ready for 3.0.12pre1
[Samba.git] / source / smbd / reply.c
blob89183aed347abf3a3d148f62947849a3f8b6185d
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 * close_file() returns the unix errno if an error
2880 * was detected on close - normally this is due to
2881 * a disk full error. If not then it was probably an I/O error.
2884 if((close_err = close_file(fsp,True)) != 0) {
2885 errno = close_err;
2886 END_PROFILE(SMBclose);
2887 return (UNIXERROR(ERRHRD,ERRgeneral));
2891 * Now take care of any time sent in the close.
2894 mtime = make_unix_date3(inbuf+smb_vwv1);
2896 /* try and set the date */
2897 set_filetime(conn, file_name, mtime);
2901 /* We have a cached error */
2902 if(eclass || err) {
2903 END_PROFILE(SMBclose);
2904 return ERROR_DOS(eclass,err);
2907 END_PROFILE(SMBclose);
2908 return(outsize);
2911 /****************************************************************************
2912 Reply to a writeclose (Core+ protocol).
2913 ****************************************************************************/
2915 int reply_writeclose(connection_struct *conn,
2916 char *inbuf,char *outbuf, int size, int dum_buffsize)
2918 size_t numtowrite;
2919 ssize_t nwritten = -1;
2920 int outsize = 0;
2921 int close_err = 0;
2922 SMB_OFF_T startpos;
2923 char *data;
2924 time_t mtime;
2925 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2926 START_PROFILE(SMBwriteclose);
2928 CHECK_FSP(fsp,conn);
2929 CHECK_WRITE(fsp);
2931 numtowrite = SVAL(inbuf,smb_vwv1);
2932 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2933 mtime = make_unix_date3(inbuf+smb_vwv4);
2934 data = smb_buf(inbuf) + 1;
2936 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2937 END_PROFILE(SMBwriteclose);
2938 return ERROR_DOS(ERRDOS,ERRlock);
2941 nwritten = write_file(fsp,data,startpos,numtowrite);
2943 set_filetime(conn, fsp->fsp_name,mtime);
2946 * More insanity. W2K only closes the file if writelen > 0.
2947 * JRA.
2950 if (numtowrite) {
2951 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
2952 fsp->fsp_name ));
2953 close_err = close_file(fsp,True);
2956 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2957 fsp->fnum, (int)numtowrite, (int)nwritten,
2958 conn->num_files_open));
2960 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2961 END_PROFILE(SMBwriteclose);
2962 return(UNIXERROR(ERRHRD,ERRdiskfull));
2965 if(close_err != 0) {
2966 errno = close_err;
2967 END_PROFILE(SMBwriteclose);
2968 return(UNIXERROR(ERRHRD,ERRgeneral));
2971 outsize = set_message(outbuf,1,0,True);
2973 SSVAL(outbuf,smb_vwv0,nwritten);
2974 END_PROFILE(SMBwriteclose);
2975 return(outsize);
2978 /****************************************************************************
2979 Reply to a lock.
2980 ****************************************************************************/
2982 int reply_lock(connection_struct *conn,
2983 char *inbuf,char *outbuf, int length, int dum_buffsize)
2985 int outsize = set_message(outbuf,0,0,True);
2986 SMB_BIG_UINT count,offset;
2987 NTSTATUS status;
2988 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2989 BOOL my_lock_ctx = False;
2991 START_PROFILE(SMBlock);
2993 CHECK_FSP(fsp,conn);
2995 release_level_2_oplocks_on_change(fsp);
2997 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2998 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3000 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3001 fsp->fd, fsp->fnum, (double)offset, (double)count));
3003 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &my_lock_ctx);
3004 if (NT_STATUS_V(status)) {
3005 #if 0
3006 /* Tests using Samba4 against W2K show this call never creates a blocking lock. */
3007 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
3009 * A blocking lock was requested. Package up
3010 * this smb into a queued request and push it
3011 * onto the blocking lock queue.
3013 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), offset, count)) {
3014 END_PROFILE(SMBlock);
3015 return -1;
3018 #endif
3019 END_PROFILE(SMBlock);
3020 return ERROR_NT(status);
3023 END_PROFILE(SMBlock);
3024 return(outsize);
3027 /****************************************************************************
3028 Reply to a unlock.
3029 ****************************************************************************/
3031 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
3032 int dum_buffsize)
3034 int outsize = set_message(outbuf,0,0,True);
3035 SMB_BIG_UINT count,offset;
3036 NTSTATUS status;
3037 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3038 START_PROFILE(SMBunlock);
3040 CHECK_FSP(fsp,conn);
3042 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3043 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3045 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
3046 if (NT_STATUS_V(status)) {
3047 END_PROFILE(SMBunlock);
3048 return ERROR_NT(status);
3051 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3052 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
3054 END_PROFILE(SMBunlock);
3055 return(outsize);
3058 /****************************************************************************
3059 Reply to a tdis.
3060 ****************************************************************************/
3062 int reply_tdis(connection_struct *conn,
3063 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3065 int outsize = set_message(outbuf,0,0,True);
3066 uint16 vuid;
3067 START_PROFILE(SMBtdis);
3069 vuid = SVAL(inbuf,smb_uid);
3071 if (!conn) {
3072 DEBUG(4,("Invalid connection in tdis\n"));
3073 END_PROFILE(SMBtdis);
3074 return ERROR_DOS(ERRSRV,ERRinvnid);
3077 conn->used = False;
3079 close_cnum(conn,vuid);
3081 END_PROFILE(SMBtdis);
3082 return outsize;
3085 /****************************************************************************
3086 Reply to a echo.
3087 ****************************************************************************/
3089 int reply_echo(connection_struct *conn,
3090 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3092 int smb_reverb = SVAL(inbuf,smb_vwv0);
3093 int seq_num;
3094 unsigned int data_len = smb_buflen(inbuf);
3095 int outsize = set_message(outbuf,1,data_len,True);
3096 START_PROFILE(SMBecho);
3098 if (data_len > BUFFER_SIZE) {
3099 DEBUG(0,("reply_echo: data_len too large.\n"));
3100 END_PROFILE(SMBecho);
3101 return -1;
3104 /* copy any incoming data back out */
3105 if (data_len > 0)
3106 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
3108 if (smb_reverb > 100) {
3109 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3110 smb_reverb = 100;
3113 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3114 SSVAL(outbuf,smb_vwv0,seq_num);
3116 smb_setlen(outbuf,outsize - 4);
3118 if (!send_smb(smbd_server_fd(),outbuf))
3119 exit_server("reply_echo: send_smb failed.");
3122 DEBUG(3,("echo %d times\n", smb_reverb));
3124 smb_echo_count++;
3126 END_PROFILE(SMBecho);
3127 return -1;
3130 /****************************************************************************
3131 Reply to a printopen.
3132 ****************************************************************************/
3134 int reply_printopen(connection_struct *conn,
3135 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3137 int outsize = 0;
3138 files_struct *fsp;
3139 START_PROFILE(SMBsplopen);
3141 if (!CAN_PRINT(conn)) {
3142 END_PROFILE(SMBsplopen);
3143 return ERROR_DOS(ERRDOS,ERRnoaccess);
3146 /* Open for exclusive use, write only. */
3147 fsp = print_fsp_open(conn, NULL);
3149 if (!fsp) {
3150 END_PROFILE(SMBsplopen);
3151 return(UNIXERROR(ERRDOS,ERRnoaccess));
3154 outsize = set_message(outbuf,1,0,True);
3155 SSVAL(outbuf,smb_vwv0,fsp->fnum);
3157 DEBUG(3,("openprint fd=%d fnum=%d\n",
3158 fsp->fd, fsp->fnum));
3160 END_PROFILE(SMBsplopen);
3161 return(outsize);
3164 /****************************************************************************
3165 Reply to a printclose.
3166 ****************************************************************************/
3168 int reply_printclose(connection_struct *conn,
3169 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3171 int outsize = set_message(outbuf,0,0,True);
3172 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3173 int close_err = 0;
3174 START_PROFILE(SMBsplclose);
3176 CHECK_FSP(fsp,conn);
3178 if (!CAN_PRINT(conn)) {
3179 END_PROFILE(SMBsplclose);
3180 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
3183 DEBUG(3,("printclose fd=%d fnum=%d\n",
3184 fsp->fd,fsp->fnum));
3186 close_err = close_file(fsp,True);
3188 if(close_err != 0) {
3189 errno = close_err;
3190 END_PROFILE(SMBsplclose);
3191 return(UNIXERROR(ERRHRD,ERRgeneral));
3194 END_PROFILE(SMBsplclose);
3195 return(outsize);
3198 /****************************************************************************
3199 Reply to a printqueue.
3200 ****************************************************************************/
3202 int reply_printqueue(connection_struct *conn,
3203 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3205 int outsize = set_message(outbuf,2,3,True);
3206 int max_count = SVAL(inbuf,smb_vwv0);
3207 int start_index = SVAL(inbuf,smb_vwv1);
3208 START_PROFILE(SMBsplretq);
3210 /* we used to allow the client to get the cnum wrong, but that
3211 is really quite gross and only worked when there was only
3212 one printer - I think we should now only accept it if they
3213 get it right (tridge) */
3214 if (!CAN_PRINT(conn)) {
3215 END_PROFILE(SMBsplretq);
3216 return ERROR_DOS(ERRDOS,ERRnoaccess);
3219 SSVAL(outbuf,smb_vwv0,0);
3220 SSVAL(outbuf,smb_vwv1,0);
3221 SCVAL(smb_buf(outbuf),0,1);
3222 SSVAL(smb_buf(outbuf),1,0);
3224 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3225 start_index, max_count));
3228 print_queue_struct *queue = NULL;
3229 print_status_struct status;
3230 char *p = smb_buf(outbuf) + 3;
3231 int count = print_queue_status(SNUM(conn), &queue, &status);
3232 int num_to_get = ABS(max_count);
3233 int first = (max_count>0?start_index:start_index+max_count+1);
3234 int i;
3236 if (first >= count)
3237 num_to_get = 0;
3238 else
3239 num_to_get = MIN(num_to_get,count-first);
3242 for (i=first;i<first+num_to_get;i++) {
3243 put_dos_date2(p,0,queue[i].time);
3244 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
3245 SSVAL(p,5, queue[i].job);
3246 SIVAL(p,7,queue[i].size);
3247 SCVAL(p,11,0);
3248 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
3249 p += 28;
3252 if (count > 0) {
3253 outsize = set_message(outbuf,2,28*count+3,False);
3254 SSVAL(outbuf,smb_vwv0,count);
3255 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3256 SCVAL(smb_buf(outbuf),0,1);
3257 SSVAL(smb_buf(outbuf),1,28*count);
3260 SAFE_FREE(queue);
3262 DEBUG(3,("%d entries returned in queue\n",count));
3265 END_PROFILE(SMBsplretq);
3266 return(outsize);
3269 /****************************************************************************
3270 Reply to a printwrite.
3271 ****************************************************************************/
3273 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3275 int numtowrite;
3276 int outsize = set_message(outbuf,0,0,True);
3277 char *data;
3278 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3280 START_PROFILE(SMBsplwr);
3282 if (!CAN_PRINT(conn)) {
3283 END_PROFILE(SMBsplwr);
3284 return ERROR_DOS(ERRDOS,ERRnoaccess);
3287 CHECK_FSP(fsp,conn);
3288 CHECK_WRITE(fsp);
3290 numtowrite = SVAL(smb_buf(inbuf),1);
3291 data = smb_buf(inbuf) + 3;
3293 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3294 END_PROFILE(SMBsplwr);
3295 return(UNIXERROR(ERRHRD,ERRdiskfull));
3298 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3300 END_PROFILE(SMBsplwr);
3301 return(outsize);
3304 /****************************************************************************
3305 The guts of the mkdir command, split out so it may be called by the NT SMB
3306 code.
3307 ****************************************************************************/
3309 NTSTATUS mkdir_internal(connection_struct *conn, pstring directory)
3311 BOOL bad_path = False;
3312 SMB_STRUCT_STAT sbuf;
3313 int ret= -1;
3315 unix_convert(directory,conn,0,&bad_path,&sbuf);
3317 if( strchr_m(directory, ':')) {
3318 return NT_STATUS_NOT_A_DIRECTORY;
3321 if (ms_has_wild(directory)) {
3322 return NT_STATUS_OBJECT_NAME_INVALID;
3325 if (bad_path) {
3326 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3329 if (check_name(directory, conn))
3330 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
3332 if (ret == -1) {
3333 if(errno == ENOENT) {
3334 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3336 return map_nt_error_from_unix(errno);
3339 return NT_STATUS_OK;
3342 /****************************************************************************
3343 Reply to a mkdir.
3344 ****************************************************************************/
3346 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3348 pstring directory;
3349 int outsize;
3350 NTSTATUS status;
3351 START_PROFILE(SMBmkdir);
3353 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False);
3354 if (!NT_STATUS_IS_OK(status)) {
3355 END_PROFILE(SMBmkdir);
3356 return ERROR_NT(status);
3359 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
3361 status = mkdir_internal(conn, directory);
3362 if (!NT_STATUS_IS_OK(status)) {
3363 END_PROFILE(SMBmkdir);
3364 return ERROR_NT(status);
3367 outsize = set_message(outbuf,0,0,True);
3369 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3371 END_PROFILE(SMBmkdir);
3372 return(outsize);
3375 /****************************************************************************
3376 Static function used by reply_rmdir to delete an entire directory
3377 tree recursively. Return False on ok, True on fail.
3378 ****************************************************************************/
3380 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3382 const char *dname = NULL;
3383 BOOL ret = False;
3384 long offset = 0;
3385 struct smb_Dir *dir_hnd = OpenDir(conn, directory);
3387 if(dir_hnd == NULL)
3388 return True;
3390 while((dname = ReadDirName(dir_hnd, &offset))) {
3391 pstring fullname;
3392 SMB_STRUCT_STAT st;
3394 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3395 continue;
3397 if (!is_visible_file(conn, directory, dname, &st, False))
3398 continue;
3400 /* Construct the full name. */
3401 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3402 errno = ENOMEM;
3403 ret = True;
3404 break;
3407 pstrcpy(fullname, directory);
3408 pstrcat(fullname, "/");
3409 pstrcat(fullname, dname);
3411 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
3412 ret = True;
3413 break;
3416 if(st.st_mode & S_IFDIR) {
3417 if(recursive_rmdir(conn, fullname)!=0) {
3418 ret = True;
3419 break;
3421 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
3422 ret = True;
3423 break;
3425 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
3426 ret = True;
3427 break;
3430 CloseDir(dir_hnd);
3431 return ret;
3434 /****************************************************************************
3435 The internals of the rmdir code - called elsewhere.
3436 ****************************************************************************/
3438 BOOL rmdir_internals(connection_struct *conn, char *directory)
3440 BOOL ok;
3441 SMB_STRUCT_STAT st;
3443 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3444 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3446 * Check to see if the only thing in this directory are
3447 * vetoed files/directories. If so then delete them and
3448 * retry. If we fail to delete any of them (and we *don't*
3449 * do a recursive delete) then fail the rmdir.
3451 BOOL all_veto_files = True;
3452 const char *dname;
3453 struct smb_Dir *dir_hnd = OpenDir(conn, directory);
3455 if(dir_hnd != NULL) {
3456 long dirpos = TellDir(dir_hnd);
3457 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
3458 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3459 continue;
3460 if (!is_visible_file(conn, directory, dname, &st, False))
3461 continue;
3462 if(!IS_VETO_PATH(conn, dname)) {
3463 all_veto_files = False;
3464 break;
3468 if(all_veto_files) {
3469 SeekDir(dir_hnd,dirpos);
3470 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
3471 pstring fullname;
3473 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3474 continue;
3475 if (!is_visible_file(conn, directory, dname, &st, False))
3476 continue;
3478 /* Construct the full name. */
3479 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3480 errno = ENOMEM;
3481 break;
3484 pstrcpy(fullname, directory);
3485 pstrcat(fullname, "/");
3486 pstrcat(fullname, dname);
3488 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
3489 break;
3490 if(st.st_mode & S_IFDIR) {
3491 if(lp_recursive_veto_delete(SNUM(conn))) {
3492 if(recursive_rmdir(conn, fullname) != 0)
3493 break;
3495 if(SMB_VFS_RMDIR(conn,fullname) != 0)
3496 break;
3497 } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
3498 break;
3500 CloseDir(dir_hnd);
3501 /* Retry the rmdir */
3502 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3503 } else {
3504 CloseDir(dir_hnd);
3506 } else {
3507 errno = ENOTEMPTY;
3511 if (!ok)
3512 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
3514 return ok;
3517 /****************************************************************************
3518 Reply to a rmdir.
3519 ****************************************************************************/
3521 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3523 pstring directory;
3524 int outsize = 0;
3525 BOOL ok = False;
3526 BOOL bad_path = False;
3527 SMB_STRUCT_STAT sbuf;
3528 NTSTATUS status;
3529 START_PROFILE(SMBrmdir);
3531 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False);
3532 if (!NT_STATUS_IS_OK(status)) {
3533 END_PROFILE(SMBrmdir);
3534 return ERROR_NT(status);
3537 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3539 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3540 if (bad_path) {
3541 END_PROFILE(SMBrmdir);
3542 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3545 if (check_name(directory,conn)) {
3546 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3547 ok = rmdir_internals(conn, directory);
3550 if (!ok) {
3551 END_PROFILE(SMBrmdir);
3552 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRbadpath);
3555 outsize = set_message(outbuf,0,0,True);
3557 DEBUG( 3, ( "rmdir %s\n", directory ) );
3559 END_PROFILE(SMBrmdir);
3560 return(outsize);
3563 /*******************************************************************
3564 Resolve wildcards in a filename rename.
3565 Note that name is in UNIX charset and thus potentially can be more
3566 than fstring buffer (255 bytes) especially in default UTF-8 case.
3567 Therefore, we use pstring inside and all calls should ensure that
3568 name2 is at least pstring-long (they do already)
3569 ********************************************************************/
3571 static BOOL resolve_wildcards(const char *name1, char *name2)
3573 pstring root1,root2;
3574 pstring ext1,ext2;
3575 char *p,*p2, *pname1, *pname2;
3576 int available_space, actual_space;
3579 pname1 = strrchr_m(name1,'/');
3580 pname2 = strrchr_m(name2,'/');
3582 if (!pname1 || !pname2)
3583 return(False);
3585 pstrcpy(root1,pname1);
3586 pstrcpy(root2,pname2);
3587 p = strrchr_m(root1,'.');
3588 if (p) {
3589 *p = 0;
3590 pstrcpy(ext1,p+1);
3591 } else {
3592 pstrcpy(ext1,"");
3594 p = strrchr_m(root2,'.');
3595 if (p) {
3596 *p = 0;
3597 pstrcpy(ext2,p+1);
3598 } else {
3599 pstrcpy(ext2,"");
3602 p = root1;
3603 p2 = root2;
3604 while (*p2) {
3605 if (*p2 == '?') {
3606 *p2 = *p;
3607 p2++;
3608 } else if (*p2 == '*') {
3609 pstrcpy(p2, p);
3610 break;
3611 } else {
3612 p2++;
3614 if (*p)
3615 p++;
3618 p = ext1;
3619 p2 = ext2;
3620 while (*p2) {
3621 if (*p2 == '?') {
3622 *p2 = *p;
3623 p2++;
3624 } else if (*p2 == '*') {
3625 pstrcpy(p2, p);
3626 break;
3627 } else {
3628 p2++;
3630 if (*p)
3631 p++;
3634 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
3636 if (ext2[0]) {
3637 actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
3638 if (actual_space >= available_space - 1) {
3639 DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
3640 actual_space - available_space));
3642 } else {
3643 pstrcpy_base(pname2, root2, name2);
3646 return(True);
3649 /****************************************************************************
3650 Ensure open files have their names updates.
3651 ****************************************************************************/
3653 static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode, char *newname)
3655 files_struct *fsp;
3656 BOOL did_rename = False;
3658 for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
3659 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
3660 fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
3661 fsp->fsp_name, newname ));
3662 string_set(&fsp->fsp_name, newname);
3663 did_rename = True;
3666 if (!did_rename)
3667 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
3668 (unsigned int)dev, (double)inode, newname ));
3671 /****************************************************************************
3672 Rename an open file - given an fsp.
3673 ****************************************************************************/
3675 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, uint16 attrs, BOOL replace_if_exists)
3677 SMB_STRUCT_STAT sbuf;
3678 BOOL bad_path = False;
3679 pstring newname_last_component;
3680 NTSTATUS error = NT_STATUS_OK;
3681 BOOL dest_exists;
3682 BOOL rcdest = True;
3684 ZERO_STRUCT(sbuf);
3685 rcdest = unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf);
3687 /* Quick check for "." and ".." */
3688 if (!bad_path && newname_last_component[0] == '.') {
3689 if (!newname_last_component[1] || (newname_last_component[1] == '.' && !newname_last_component[2])) {
3690 return NT_STATUS_ACCESS_DENIED;
3693 if (!rcdest && bad_path) {
3694 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3697 /* Ensure newname contains a '/' */
3698 if(strrchr_m(newname,'/') == 0) {
3699 pstring tmpstr;
3701 pstrcpy(tmpstr, "./");
3702 pstrcat(tmpstr, newname);
3703 pstrcpy(newname, tmpstr);
3707 * Check for special case with case preserving and not
3708 * case sensitive. If the old last component differs from the original
3709 * last component only by case, then we should allow
3710 * the rename (user is trying to change the case of the
3711 * filename).
3714 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
3715 strequal(newname, fsp->fsp_name)) {
3716 char *p;
3717 pstring newname_modified_last_component;
3720 * Get the last component of the modified name.
3721 * Note that we guarantee that newname contains a '/'
3722 * character above.
3724 p = strrchr_m(newname,'/');
3725 pstrcpy(newname_modified_last_component,p+1);
3727 if(strcsequal(newname_modified_last_component,
3728 newname_last_component) == False) {
3730 * Replace the modified last component with
3731 * the original.
3733 pstrcpy(p+1, newname_last_component);
3738 * If the src and dest names are identical - including case,
3739 * don't do the rename, just return success.
3742 if (strcsequal(fsp->fsp_name, newname)) {
3743 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
3744 newname));
3745 return NT_STATUS_OK;
3748 dest_exists = vfs_object_exist(conn,newname,NULL);
3750 if(!replace_if_exists && dest_exists) {
3751 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
3752 fsp->fsp_name,newname));
3753 return NT_STATUS_OBJECT_NAME_COLLISION;
3756 error = can_rename(conn,newname,attrs,&sbuf);
3758 if (dest_exists && !NT_STATUS_IS_OK(error)) {
3759 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3760 nt_errstr(error), fsp->fsp_name,newname));
3761 if (NT_STATUS_EQUAL(error,NT_STATUS_SHARING_VIOLATION))
3762 error = NT_STATUS_ACCESS_DENIED;
3763 return error;
3766 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
3767 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
3768 fsp->fsp_name,newname));
3769 rename_open_files(conn, fsp->dev, fsp->inode, newname);
3770 return NT_STATUS_OK;
3773 if (errno == ENOTDIR || errno == EISDIR)
3774 error = NT_STATUS_OBJECT_NAME_COLLISION;
3775 else
3776 error = map_nt_error_from_unix(errno);
3778 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
3779 nt_errstr(error), fsp->fsp_name,newname));
3781 return error;
3784 /****************************************************************************
3785 The guts of the rename command, split out so it may be called by the NT SMB
3786 code.
3787 ****************************************************************************/
3789 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, uint16 attrs, BOOL replace_if_exists)
3791 pstring directory;
3792 pstring mask;
3793 pstring last_component_src;
3794 pstring last_component_dest;
3795 char *p;
3796 BOOL has_wild;
3797 BOOL bad_path_src = False;
3798 BOOL bad_path_dest = False;
3799 int count=0;
3800 NTSTATUS error = NT_STATUS_OK;
3801 BOOL rc = True;
3802 BOOL rcdest = True;
3803 SMB_STRUCT_STAT sbuf1, sbuf2;
3805 *directory = *mask = 0;
3807 ZERO_STRUCT(sbuf1);
3808 ZERO_STRUCT(sbuf2);
3810 rc = unix_convert(name,conn,last_component_src,&bad_path_src,&sbuf1);
3811 if (!rc && bad_path_src) {
3812 if (ms_has_wild(last_component_src))
3813 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3814 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3817 /* Quick check for "." and ".." */
3818 if (last_component_src[0] == '.') {
3819 if (!last_component_src[1] || (last_component_src[1] == '.' && !last_component_src[2])) {
3820 return NT_STATUS_OBJECT_NAME_INVALID;
3824 rcdest = unix_convert(newname,conn,last_component_dest,&bad_path_dest,&sbuf2);
3826 /* Quick check for "." and ".." */
3827 if (last_component_dest[0] == '.') {
3828 if (!last_component_dest[1] || (last_component_dest[1] == '.' && !last_component_dest[2])) {
3829 return NT_STATUS_OBJECT_NAME_INVALID;
3834 * Split the old name into directory and last component
3835 * strings. Note that unix_convert may have stripped off a
3836 * leading ./ from both name and newname if the rename is
3837 * at the root of the share. We need to make sure either both
3838 * name and newname contain a / character or neither of them do
3839 * as this is checked in resolve_wildcards().
3842 p = strrchr_m(name,'/');
3843 if (!p) {
3844 pstrcpy(directory,".");
3845 pstrcpy(mask,name);
3846 } else {
3847 *p = 0;
3848 pstrcpy(directory,name);
3849 pstrcpy(mask,p+1);
3850 *p = '/'; /* Replace needed for exceptional test below. */
3854 * We should only check the mangled cache
3855 * here if unix_convert failed. This means
3856 * that the path in 'mask' doesn't exist
3857 * on the file system and so we need to look
3858 * for a possible mangle. This patch from
3859 * Tine Smukavec <valentin.smukavec@hermes.si>.
3862 if (!rc && mangle_is_mangled(mask))
3863 mangle_check_cache( mask, sizeof(pstring)-1 );
3865 has_wild = ms_has_wild(mask);
3867 if (!has_wild) {
3869 * No wildcards - just process the one file.
3871 BOOL is_short_name = mangle_is_8_3(name, True);
3873 /* Add a terminating '/' to the directory name. */
3874 pstrcat(directory,"/");
3875 pstrcat(directory,mask);
3877 /* Ensure newname contains a '/' also */
3878 if(strrchr_m(newname,'/') == 0) {
3879 pstring tmpstr;
3881 pstrcpy(tmpstr, "./");
3882 pstrcat(tmpstr, newname);
3883 pstrcpy(newname, tmpstr);
3886 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
3887 directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
3888 conn->case_sensitive, conn->case_preserve, conn->short_case_preserve, directory,
3889 newname, last_component_dest, is_short_name));
3892 * Check for special case with case preserving and not
3893 * case sensitive, if directory and newname are identical,
3894 * and the old last component differs from the original
3895 * last component only by case, then we should allow
3896 * the rename (user is trying to change the case of the
3897 * filename).
3899 if((conn->case_sensitive == False) &&
3900 (((conn->case_preserve == True) &&
3901 (is_short_name == False)) ||
3902 ((conn->short_case_preserve == True) &&
3903 (is_short_name == True))) &&
3904 strcsequal(directory, newname)) {
3905 pstring modified_last_component;
3908 * Get the last component of the modified name.
3909 * Note that we guarantee that newname contains a '/'
3910 * character above.
3912 p = strrchr_m(newname,'/');
3913 pstrcpy(modified_last_component,p+1);
3915 if(strcsequal(modified_last_component,
3916 last_component_dest) == False) {
3918 * Replace the modified last component with
3919 * the original.
3921 pstrcpy(p+1, last_component_dest);
3925 resolve_wildcards(directory,newname);
3928 * The source object must exist.
3931 if (!vfs_object_exist(conn, directory, &sbuf1)) {
3932 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
3933 directory,newname));
3935 if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
3937 * Must return different errors depending on whether the parent
3938 * directory existed or not.
3941 p = strrchr_m(directory, '/');
3942 if (!p)
3943 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3944 *p = '\0';
3945 if (vfs_object_exist(conn, directory, NULL))
3946 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3947 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3949 error = map_nt_error_from_unix(errno);
3950 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3951 nt_errstr(error), directory,newname));
3953 return error;
3956 if (!rcdest && bad_path_dest) {
3957 if (ms_has_wild(last_component_dest))
3958 return NT_STATUS_OBJECT_NAME_INVALID;
3959 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3962 error = can_rename(conn,directory,attrs,&sbuf1);
3964 if (!NT_STATUS_IS_OK(error)) {
3965 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3966 nt_errstr(error), directory,newname));
3967 return error;
3971 * If the src and dest names are identical - including case,
3972 * don't do the rename, just return success.
3975 if (strcsequal(directory, newname)) {
3976 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3977 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
3978 return NT_STATUS_OK;
3981 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
3982 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
3983 directory,newname));
3984 return NT_STATUS_OBJECT_NAME_COLLISION;
3987 if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
3988 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
3989 directory,newname));
3990 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3991 return NT_STATUS_OK;
3994 if (errno == ENOTDIR || errno == EISDIR)
3995 error = NT_STATUS_OBJECT_NAME_COLLISION;
3996 else
3997 error = map_nt_error_from_unix(errno);
3999 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4000 nt_errstr(error), directory,newname));
4002 return error;
4003 } else {
4005 * Wildcards - process each file that matches.
4007 struct smb_Dir *dir_hnd = NULL;
4008 const char *dname;
4009 pstring destname;
4011 if (check_name(directory,conn))
4012 dir_hnd = OpenDir(conn, directory);
4014 if (dir_hnd) {
4015 long offset = 0;
4016 error = NT_STATUS_NO_SUCH_FILE;
4017 /* Was error = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */
4019 if (strequal(mask,"????????.???"))
4020 pstrcpy(mask,"*");
4022 while ((dname = ReadDirName(dir_hnd, &offset))) {
4023 pstring fname;
4024 BOOL sysdir_entry = False;
4026 pstrcpy(fname,dname);
4028 /* Quick check for "." and ".." */
4029 if (fname[0] == '.') {
4030 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
4031 if (attrs & aDIR) {
4032 sysdir_entry = True;
4033 } else {
4034 continue;
4039 if (!is_visible_file(conn, directory, dname, &sbuf1, False))
4040 continue;
4042 if(!mask_match(fname, mask, conn->case_sensitive))
4043 continue;
4045 if (sysdir_entry) {
4046 error = NT_STATUS_OBJECT_NAME_INVALID;
4047 break;
4050 error = NT_STATUS_ACCESS_DENIED;
4051 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
4052 if (!vfs_object_exist(conn, fname, &sbuf1)) {
4053 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4054 DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
4055 continue;
4057 error = can_rename(conn,fname,attrs,&sbuf1);
4058 if (!NT_STATUS_IS_OK(error)) {
4059 DEBUG(6,("rename %s refused\n", fname));
4060 continue;
4062 pstrcpy(destname,newname);
4064 if (!resolve_wildcards(fname,destname)) {
4065 DEBUG(6,("resolve_wildcards %s %s failed\n",
4066 fname, destname));
4067 continue;
4070 if (strcsequal(fname,destname)) {
4071 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4072 DEBUG(3,("rename_internals: identical names in wildcard rename %s - success\n", fname));
4073 count++;
4074 error = NT_STATUS_OK;
4075 continue;
4078 if (!replace_if_exists &&
4079 vfs_file_exist(conn,destname, NULL)) {
4080 DEBUG(6,("file_exist %s\n", destname));
4081 error = NT_STATUS_OBJECT_NAME_COLLISION;
4082 continue;
4085 if (!SMB_VFS_RENAME(conn,fname,destname)) {
4086 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4087 count++;
4088 error = NT_STATUS_OK;
4090 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
4092 CloseDir(dir_hnd);
4095 if (!NT_STATUS_EQUAL(error,NT_STATUS_NO_SUCH_FILE)) {
4096 if (!rcdest && bad_path_dest) {
4097 if (ms_has_wild(last_component_dest))
4098 return NT_STATUS_OBJECT_NAME_INVALID;
4099 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4104 if (count == 0 && NT_STATUS_IS_OK(error)) {
4105 error = map_nt_error_from_unix(errno);
4108 return error;
4111 /****************************************************************************
4112 Reply to a mv.
4113 ****************************************************************************/
4115 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
4116 int dum_buffsize)
4118 int outsize = 0;
4119 pstring name;
4120 pstring newname;
4121 char *p;
4122 uint16 attrs = SVAL(inbuf,smb_vwv0);
4123 NTSTATUS status;
4125 START_PROFILE(SMBmv);
4127 p = smb_buf(inbuf) + 1;
4128 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True);
4129 if (!NT_STATUS_IS_OK(status)) {
4130 END_PROFILE(SMBmv);
4131 return ERROR_NT(status);
4133 p++;
4134 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True);
4135 if (!NT_STATUS_IS_OK(status)) {
4136 END_PROFILE(SMBmv);
4137 return ERROR_NT(status);
4140 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
4141 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4143 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
4145 status = rename_internals(conn, name, newname, attrs, False);
4146 if (!NT_STATUS_IS_OK(status)) {
4147 END_PROFILE(SMBmv);
4148 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4149 /* We have re-scheduled this call. */
4150 clear_cached_errors();
4151 return -1;
4153 return ERROR_NT(status);
4157 * Win2k needs a changenotify request response before it will
4158 * update after a rename..
4160 process_pending_change_notify_queue((time_t)0);
4161 outsize = set_message(outbuf,0,0,True);
4163 END_PROFILE(SMBmv);
4164 return(outsize);
4167 /*******************************************************************
4168 Copy a file as part of a reply_copy.
4169 ******************************************************************/
4171 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
4172 int count,BOOL target_is_directory, int *err_ret)
4174 int Access,action;
4175 SMB_STRUCT_STAT src_sbuf, sbuf2;
4176 SMB_OFF_T ret=-1;
4177 files_struct *fsp1,*fsp2;
4178 pstring dest;
4179 uint32 dosattrs;
4181 *err_ret = 0;
4183 pstrcpy(dest,dest1);
4184 if (target_is_directory) {
4185 char *p = strrchr_m(src,'/');
4186 if (p)
4187 p++;
4188 else
4189 p = src;
4190 pstrcat(dest,"/");
4191 pstrcat(dest,p);
4194 if (!vfs_file_exist(conn,src,&src_sbuf))
4195 return(False);
4197 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
4198 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),FILE_ATTRIBUTE_NORMAL,INTERNAL_OPEN_ONLY,
4199 &Access,&action);
4201 if (!fsp1)
4202 return(False);
4204 if (!target_is_directory && count)
4205 ofun = FILE_EXISTS_OPEN;
4207 dosattrs = dos_mode(conn, src, &src_sbuf);
4208 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1)
4209 ZERO_STRUCTP(&sbuf2);
4211 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
4212 ofun,dosattrs,INTERNAL_OPEN_ONLY,&Access,&action);
4214 if (!fsp2) {
4215 close_file(fsp1,False);
4216 return(False);
4219 if ((ofun&3) == 1) {
4220 if(SMB_VFS_LSEEK(fsp2,fsp2->fd,0,SEEK_END) == -1) {
4221 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
4223 * Stop the copy from occurring.
4225 ret = -1;
4226 src_sbuf.st_size = 0;
4230 if (src_sbuf.st_size)
4231 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
4233 close_file(fsp1,False);
4235 /* Ensure the modtime is set correctly on the destination file. */
4236 fsp2->pending_modtime = src_sbuf.st_mtime;
4239 * As we are opening fsp1 read-only we only expect
4240 * an error on close on fsp2 if we are out of space.
4241 * Thus we don't look at the error return from the
4242 * close of fsp1.
4244 *err_ret = close_file(fsp2,False);
4246 return(ret == (SMB_OFF_T)src_sbuf.st_size);
4249 /****************************************************************************
4250 Reply to a file copy.
4251 ****************************************************************************/
4253 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4255 int outsize = 0;
4256 pstring name;
4257 pstring directory;
4258 pstring mask,newname;
4259 char *p;
4260 int count=0;
4261 int error = ERRnoaccess;
4262 int err = 0;
4263 BOOL has_wild;
4264 BOOL exists=False;
4265 int tid2 = SVAL(inbuf,smb_vwv0);
4266 int ofun = SVAL(inbuf,smb_vwv1);
4267 int flags = SVAL(inbuf,smb_vwv2);
4268 BOOL target_is_directory=False;
4269 BOOL bad_path1 = False;
4270 BOOL bad_path2 = False;
4271 BOOL rc = True;
4272 SMB_STRUCT_STAT sbuf1, sbuf2;
4273 NTSTATUS status;
4275 START_PROFILE(SMBcopy);
4277 *directory = *mask = 0;
4279 p = smb_buf(inbuf);
4280 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True);
4281 if (!NT_STATUS_IS_OK(status)) {
4282 END_PROFILE(SMBcopy);
4283 return ERROR_NT(status);
4285 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True);
4286 if (!NT_STATUS_IS_OK(status)) {
4287 END_PROFILE(SMBcopy);
4288 return ERROR_NT(status);
4291 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
4293 if (tid2 != conn->cnum) {
4294 /* can't currently handle inter share copies XXXX */
4295 DEBUG(3,("Rejecting inter-share copy\n"));
4296 END_PROFILE(SMBcopy);
4297 return ERROR_DOS(ERRSRV,ERRinvdevice);
4300 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
4301 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4303 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
4304 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
4306 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
4308 if ((flags&1) && target_is_directory) {
4309 END_PROFILE(SMBcopy);
4310 return ERROR_DOS(ERRDOS,ERRbadfile);
4313 if ((flags&2) && !target_is_directory) {
4314 END_PROFILE(SMBcopy);
4315 return ERROR_DOS(ERRDOS,ERRbadpath);
4318 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
4319 /* wants a tree copy! XXXX */
4320 DEBUG(3,("Rejecting tree copy\n"));
4321 END_PROFILE(SMBcopy);
4322 return ERROR_DOS(ERRSRV,ERRerror);
4325 p = strrchr_m(name,'/');
4326 if (!p) {
4327 pstrcpy(directory,"./");
4328 pstrcpy(mask,name);
4329 } else {
4330 *p = 0;
4331 pstrcpy(directory,name);
4332 pstrcpy(mask,p+1);
4336 * We should only check the mangled cache
4337 * here if unix_convert failed. This means
4338 * that the path in 'mask' doesn't exist
4339 * on the file system and so we need to look
4340 * for a possible mangle. This patch from
4341 * Tine Smukavec <valentin.smukavec@hermes.si>.
4344 if (!rc && mangle_is_mangled(mask))
4345 mangle_check_cache( mask, sizeof(pstring)-1 );
4347 has_wild = ms_has_wild(mask);
4349 if (!has_wild) {
4350 pstrcat(directory,"/");
4351 pstrcat(directory,mask);
4352 if (resolve_wildcards(directory,newname) &&
4353 copy_file(directory,newname,conn,ofun, count,target_is_directory,&err))
4354 count++;
4355 if(!count && err) {
4356 errno = err;
4357 END_PROFILE(SMBcopy);
4358 return(UNIXERROR(ERRHRD,ERRgeneral));
4360 if (!count) {
4361 exists = vfs_file_exist(conn,directory,NULL);
4363 } else {
4364 struct smb_Dir *dir_hnd = NULL;
4365 const char *dname;
4366 pstring destname;
4368 if (check_name(directory,conn))
4369 dir_hnd = OpenDir(conn, directory);
4371 if (dir_hnd) {
4372 long offset = 0;
4373 error = ERRbadfile;
4375 if (strequal(mask,"????????.???"))
4376 pstrcpy(mask,"*");
4378 while ((dname = ReadDirName(dir_hnd, &offset))) {
4379 pstring fname;
4380 pstrcpy(fname,dname);
4382 if (!is_visible_file(conn, directory, dname, &sbuf1, False))
4383 continue;
4385 if(!mask_match(fname, mask, conn->case_sensitive))
4386 continue;
4388 error = ERRnoaccess;
4389 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
4390 pstrcpy(destname,newname);
4391 if (resolve_wildcards(fname,destname) &&
4392 copy_file(fname,destname,conn,ofun,
4393 count,target_is_directory,&err))
4394 count++;
4395 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
4397 CloseDir(dir_hnd);
4401 if (count == 0) {
4402 if(err) {
4403 /* Error on close... */
4404 errno = err;
4405 END_PROFILE(SMBcopy);
4406 return(UNIXERROR(ERRHRD,ERRgeneral));
4409 if (exists) {
4410 END_PROFILE(SMBcopy);
4411 return ERROR_DOS(ERRDOS,error);
4412 } else {
4413 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
4414 unix_ERR_class = ERRDOS;
4415 unix_ERR_code = ERRbadpath;
4417 END_PROFILE(SMBcopy);
4418 return(UNIXERROR(ERRDOS,error));
4422 outsize = set_message(outbuf,1,0,True);
4423 SSVAL(outbuf,smb_vwv0,count);
4425 END_PROFILE(SMBcopy);
4426 return(outsize);
4429 /****************************************************************************
4430 Reply to a setdir.
4431 ****************************************************************************/
4433 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4435 int snum;
4436 int outsize = 0;
4437 BOOL ok = False;
4438 pstring newdir;
4439 NTSTATUS status;
4441 START_PROFILE(pathworks_setdir);
4443 snum = SNUM(conn);
4444 if (!CAN_SETDIR(snum)) {
4445 END_PROFILE(pathworks_setdir);
4446 return ERROR_DOS(ERRDOS,ERRnoaccess);
4449 srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status, False);
4450 if (!NT_STATUS_IS_OK(status)) {
4451 END_PROFILE(pathworks_setdir);
4452 return ERROR_NT(status);
4455 if (strlen(newdir) == 0) {
4456 ok = True;
4457 } else {
4458 ok = vfs_directory_exist(conn,newdir,NULL);
4459 if (ok)
4460 string_set(&conn->connectpath,newdir);
4463 if (!ok) {
4464 END_PROFILE(pathworks_setdir);
4465 return ERROR_DOS(ERRDOS,ERRbadpath);
4468 outsize = set_message(outbuf,0,0,True);
4469 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
4471 DEBUG(3,("setdir %s\n", newdir));
4473 END_PROFILE(pathworks_setdir);
4474 return(outsize);
4477 /****************************************************************************
4478 Get a lock pid, dealing with large count requests.
4479 ****************************************************************************/
4481 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
4483 if(!large_file_format)
4484 return SVAL(data,SMB_LPID_OFFSET(data_offset));
4485 else
4486 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
4489 /****************************************************************************
4490 Get a lock count, dealing with large count requests.
4491 ****************************************************************************/
4493 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4495 SMB_BIG_UINT count = 0;
4497 if(!large_file_format) {
4498 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4499 } else {
4501 #if defined(HAVE_LONGLONG)
4502 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4503 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4504 #else /* HAVE_LONGLONG */
4507 * NT4.x seems to be broken in that it sends large file (64 bit)
4508 * lockingX calls even if the CAP_LARGE_FILES was *not*
4509 * negotiated. For boxes without large unsigned ints truncate the
4510 * lock count by dropping the top 32 bits.
4513 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4514 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4515 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4516 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4517 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4520 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4521 #endif /* HAVE_LONGLONG */
4524 return count;
4527 #if !defined(HAVE_LONGLONG)
4528 /****************************************************************************
4529 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
4530 ****************************************************************************/
4532 static uint32 map_lock_offset(uint32 high, uint32 low)
4534 unsigned int i;
4535 uint32 mask = 0;
4536 uint32 highcopy = high;
4539 * Try and find out how many significant bits there are in high.
4542 for(i = 0; highcopy; i++)
4543 highcopy >>= 1;
4546 * We use 31 bits not 32 here as POSIX
4547 * lock offsets may not be negative.
4550 mask = (~0) << (31 - i);
4552 if(low & mask)
4553 return 0; /* Fail. */
4555 high <<= (31 - i);
4557 return (high|low);
4559 #endif /* !defined(HAVE_LONGLONG) */
4561 /****************************************************************************
4562 Get a lock offset, dealing with large offset requests.
4563 ****************************************************************************/
4565 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4567 SMB_BIG_UINT offset = 0;
4569 *err = False;
4571 if(!large_file_format) {
4572 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4573 } else {
4575 #if defined(HAVE_LONGLONG)
4576 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4577 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4578 #else /* HAVE_LONGLONG */
4581 * NT4.x seems to be broken in that it sends large file (64 bit)
4582 * lockingX calls even if the CAP_LARGE_FILES was *not*
4583 * negotiated. For boxes without large unsigned ints mangle the
4584 * lock offset by mapping the top 32 bits onto the lower 32.
4587 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4588 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4589 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4590 uint32 new_low = 0;
4592 if((new_low = map_lock_offset(high, low)) == 0) {
4593 *err = True;
4594 return (SMB_BIG_UINT)-1;
4597 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4598 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4599 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4600 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4603 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4604 #endif /* HAVE_LONGLONG */
4607 return offset;
4610 /****************************************************************************
4611 Reply to a lockingX request.
4612 ****************************************************************************/
4614 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4616 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4617 unsigned char locktype = CVAL(inbuf,smb_vwv3);
4618 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4619 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4620 uint16 num_locks = SVAL(inbuf,smb_vwv7);
4621 SMB_BIG_UINT count = 0, offset = 0;
4622 uint16 lock_pid;
4623 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4624 int i;
4625 char *data;
4626 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4627 BOOL err;
4628 BOOL my_lock_ctx = False;
4629 NTSTATUS status;
4631 START_PROFILE(SMBlockingX);
4633 CHECK_FSP(fsp,conn);
4635 data = smb_buf(inbuf);
4637 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
4638 /* we don't support these - and CANCEL_LOCK makes w2k
4639 and XP reboot so I don't really want to be
4640 compatible! (tridge) */
4641 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
4644 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
4645 /* Need to make this like a cancel.... JRA. */
4646 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
4649 /* Check if this is an oplock break on a file
4650 we have granted an oplock on.
4652 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
4653 /* Client can insist on breaking to none. */
4654 BOOL break_to_none = (oplocklevel == 0);
4656 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4657 (unsigned int)oplocklevel, fsp->fnum ));
4660 * Make sure we have granted an exclusive or batch oplock on this file.
4663 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
4664 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4665 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4667 /* if this is a pure oplock break request then don't send a reply */
4668 if (num_locks == 0 && num_ulocks == 0) {
4669 END_PROFILE(SMBlockingX);
4670 return -1;
4671 } else {
4672 END_PROFILE(SMBlockingX);
4673 return ERROR_DOS(ERRDOS,ERRlock);
4677 if (remove_oplock(fsp, break_to_none) == False) {
4678 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4679 fsp->fsp_name ));
4682 /* if this is a pure oplock break request then don't send a reply */
4683 if (num_locks == 0 && num_ulocks == 0) {
4684 /* Sanity check - ensure a pure oplock break is not a
4685 chained request. */
4686 if(CVAL(inbuf,smb_vwv0) != 0xff)
4687 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4688 (unsigned int)CVAL(inbuf,smb_vwv0) ));
4689 END_PROFILE(SMBlockingX);
4690 return -1;
4695 * We do this check *after* we have checked this is not a oplock break
4696 * response message. JRA.
4699 release_level_2_oplocks_on_change(fsp);
4701 /* Data now points at the beginning of the list
4702 of smb_unlkrng structs */
4703 for(i = 0; i < (int)num_ulocks; i++) {
4704 lock_pid = get_lock_pid( data, i, large_file_format);
4705 count = get_lock_count( data, i, large_file_format);
4706 offset = get_lock_offset( data, i, large_file_format, &err);
4709 * There is no error code marked "stupid client bug".... :-).
4711 if(err) {
4712 END_PROFILE(SMBlockingX);
4713 return ERROR_DOS(ERRDOS,ERRnoaccess);
4716 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4717 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4719 status = do_unlock(fsp,conn,lock_pid,count,offset);
4720 if (NT_STATUS_V(status)) {
4721 END_PROFILE(SMBlockingX);
4722 return ERROR_NT(status);
4726 /* Setup the timeout in seconds. */
4728 lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000);
4730 /* Now do any requested locks */
4731 data += ((large_file_format ? 20 : 10)*num_ulocks);
4733 /* Data now points at the beginning of the list
4734 of smb_lkrng structs */
4736 for(i = 0; i < (int)num_locks; i++) {
4737 lock_pid = get_lock_pid( data, i, large_file_format);
4738 count = get_lock_count( data, i, large_file_format);
4739 offset = get_lock_offset( data, i, large_file_format, &err);
4742 * There is no error code marked "stupid client bug".... :-).
4744 if(err) {
4745 END_PROFILE(SMBlockingX);
4746 return ERROR_DOS(ERRDOS,ERRnoaccess);
4749 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
4750 (double)offset, (double)count, (unsigned int)lock_pid,
4751 fsp->fsp_name, (int)lock_timeout ));
4753 status = do_lock_spin(fsp,conn,lock_pid, count,offset,
4754 ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &my_lock_ctx);
4755 if (NT_STATUS_V(status)) {
4757 * Interesting fact found by IFSTEST /t LockOverlappedTest...
4758 * Even if it's our own lock context, we need to wait here as
4759 * there may be an unlock on the way.
4760 * So I removed a "&& !my_lock_ctx" from the following
4761 * if statement. JRA.
4763 if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
4765 * A blocking lock was requested. Package up
4766 * this smb into a queued request and push it
4767 * onto the blocking lock queue.
4769 if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) {
4770 END_PROFILE(SMBlockingX);
4771 return -1;
4774 break;
4778 /* If any of the above locks failed, then we must unlock
4779 all of the previous locks (X/Open spec). */
4780 if (i != num_locks && num_locks != 0) {
4782 * Ensure we don't do a remove on the lock that just failed,
4783 * as under POSIX rules, if we have a lock already there, we
4784 * will delete it (and we shouldn't) .....
4786 for(i--; i >= 0; i--) {
4787 lock_pid = get_lock_pid( data, i, large_file_format);
4788 count = get_lock_count( data, i, large_file_format);
4789 offset = get_lock_offset( data, i, large_file_format, &err);
4792 * There is no error code marked "stupid client bug".... :-).
4794 if(err) {
4795 END_PROFILE(SMBlockingX);
4796 return ERROR_DOS(ERRDOS,ERRnoaccess);
4799 do_unlock(fsp,conn,lock_pid,count,offset);
4801 END_PROFILE(SMBlockingX);
4802 return ERROR_NT(status);
4805 set_message(outbuf,2,0,True);
4807 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4808 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4810 END_PROFILE(SMBlockingX);
4811 return chain_reply(inbuf,outbuf,length,bufsize);
4814 /****************************************************************************
4815 Reply to a SMBreadbmpx (read block multiplex) request.
4816 ****************************************************************************/
4818 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4820 ssize_t nread = -1;
4821 ssize_t total_read;
4822 char *data;
4823 SMB_OFF_T startpos;
4824 int outsize;
4825 size_t maxcount;
4826 int max_per_packet;
4827 size_t tcount;
4828 int pad;
4829 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4830 START_PROFILE(SMBreadBmpx);
4832 /* this function doesn't seem to work - disable by default */
4833 if (!lp_readbmpx()) {
4834 END_PROFILE(SMBreadBmpx);
4835 return ERROR_DOS(ERRSRV,ERRuseSTD);
4838 outsize = set_message(outbuf,8,0,True);
4840 CHECK_FSP(fsp,conn);
4841 CHECK_READ(fsp);
4843 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
4844 maxcount = SVAL(inbuf,smb_vwv3);
4846 data = smb_buf(outbuf);
4847 pad = ((long)data)%4;
4848 if (pad)
4849 pad = 4 - pad;
4850 data += pad;
4852 max_per_packet = bufsize-(outsize+pad);
4853 tcount = maxcount;
4854 total_read = 0;
4856 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
4857 END_PROFILE(SMBreadBmpx);
4858 return ERROR_DOS(ERRDOS,ERRlock);
4861 do {
4862 size_t N = MIN(max_per_packet,tcount-total_read);
4864 nread = read_file(fsp,data,startpos,N);
4866 if (nread <= 0)
4867 nread = 0;
4869 if (nread < (ssize_t)N)
4870 tcount = total_read + nread;
4872 set_message(outbuf,8,nread,False);
4873 SIVAL(outbuf,smb_vwv0,startpos);
4874 SSVAL(outbuf,smb_vwv2,tcount);
4875 SSVAL(outbuf,smb_vwv6,nread);
4876 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4878 if (!send_smb(smbd_server_fd(),outbuf))
4879 exit_server("reply_readbmpx: send_smb failed.");
4881 total_read += nread;
4882 startpos += nread;
4883 } while (total_read < (ssize_t)tcount);
4885 END_PROFILE(SMBreadBmpx);
4886 return(-1);
4889 /****************************************************************************
4890 Reply to a SMBsetattrE.
4891 ****************************************************************************/
4893 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4895 struct utimbuf unix_times;
4896 int outsize = 0;
4897 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4898 START_PROFILE(SMBsetattrE);
4900 outsize = set_message(outbuf,0,0,True);
4902 if(!fsp || (fsp->conn != conn)) {
4903 END_PROFILE(SMBgetattrE);
4904 return ERROR_DOS(ERRDOS,ERRbadfid);
4908 * Convert the DOS times into unix times. Ignore create
4909 * time as UNIX can't set this.
4912 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4913 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4916 * Patch from Ray Frush <frush@engr.colostate.edu>
4917 * Sometimes times are sent as zero - ignore them.
4920 if ((unix_times.actime == 0) && (unix_times.modtime == 0)) {
4921 /* Ignore request */
4922 if( DEBUGLVL( 3 ) ) {
4923 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4924 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4926 END_PROFILE(SMBsetattrE);
4927 return(outsize);
4928 } else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) {
4929 /* set modify time = to access time if modify time was 0 */
4930 unix_times.modtime = unix_times.actime;
4933 /* Set the date on this file */
4934 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4935 END_PROFILE(SMBsetattrE);
4936 return ERROR_DOS(ERRDOS,ERRnoaccess);
4939 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4940 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4942 END_PROFILE(SMBsetattrE);
4943 return(outsize);
4947 /* Back from the dead for OS/2..... JRA. */
4949 /****************************************************************************
4950 Reply to a SMBwritebmpx (write block multiplex primary) request.
4951 ****************************************************************************/
4953 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4955 size_t numtowrite;
4956 ssize_t nwritten = -1;
4957 int outsize = 0;
4958 SMB_OFF_T startpos;
4959 size_t tcount;
4960 BOOL write_through;
4961 int smb_doff;
4962 char *data;
4963 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4964 START_PROFILE(SMBwriteBmpx);
4966 CHECK_FSP(fsp,conn);
4967 CHECK_WRITE(fsp);
4968 CHECK_ERROR(fsp);
4970 tcount = SVAL(inbuf,smb_vwv1);
4971 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
4972 write_through = BITSETW(inbuf+smb_vwv7,0);
4973 numtowrite = SVAL(inbuf,smb_vwv10);
4974 smb_doff = SVAL(inbuf,smb_vwv11);
4976 data = smb_base(inbuf) + smb_doff;
4978 /* If this fails we need to send an SMBwriteC response,
4979 not an SMBwritebmpx - set this up now so we don't forget */
4980 SCVAL(outbuf,smb_com,SMBwritec);
4982 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) {
4983 END_PROFILE(SMBwriteBmpx);
4984 return(ERROR_DOS(ERRDOS,ERRlock));
4987 nwritten = write_file(fsp,data,startpos,numtowrite);
4989 if(lp_syncalways(SNUM(conn)) || write_through)
4990 sync_file(conn,fsp);
4992 if(nwritten < (ssize_t)numtowrite) {
4993 END_PROFILE(SMBwriteBmpx);
4994 return(UNIXERROR(ERRHRD,ERRdiskfull));
4997 /* If the maximum to be written to this file
4998 is greater than what we just wrote then set
4999 up a secondary struct to be attached to this
5000 fd, we will use this to cache error messages etc. */
5002 if((ssize_t)tcount > nwritten) {
5003 write_bmpx_struct *wbms;
5004 if(fsp->wbmpx_ptr != NULL)
5005 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
5006 else
5007 wbms = SMB_MALLOC_P(write_bmpx_struct);
5008 if(!wbms) {
5009 DEBUG(0,("Out of memory in reply_readmpx\n"));
5010 END_PROFILE(SMBwriteBmpx);
5011 return(ERROR_DOS(ERRSRV,ERRnoresource));
5013 wbms->wr_mode = write_through;
5014 wbms->wr_discard = False; /* No errors yet */
5015 wbms->wr_total_written = nwritten;
5016 wbms->wr_errclass = 0;
5017 wbms->wr_error = 0;
5018 fsp->wbmpx_ptr = wbms;
5021 /* We are returning successfully, set the message type back to
5022 SMBwritebmpx */
5023 SCVAL(outbuf,smb_com,SMBwriteBmpx);
5025 outsize = set_message(outbuf,1,0,True);
5027 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
5029 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
5030 fsp->fnum, (int)numtowrite, (int)nwritten ) );
5032 if (write_through && tcount==nwritten) {
5033 /* We need to send both a primary and a secondary response */
5034 smb_setlen(outbuf,outsize - 4);
5035 if (!send_smb(smbd_server_fd(),outbuf))
5036 exit_server("reply_writebmpx: send_smb failed.");
5038 /* Now the secondary */
5039 outsize = set_message(outbuf,1,0,True);
5040 SCVAL(outbuf,smb_com,SMBwritec);
5041 SSVAL(outbuf,smb_vwv0,nwritten);
5044 END_PROFILE(SMBwriteBmpx);
5045 return(outsize);
5048 /****************************************************************************
5049 Reply to a SMBwritebs (write block multiplex secondary) request.
5050 ****************************************************************************/
5052 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5054 size_t numtowrite;
5055 ssize_t nwritten = -1;
5056 int outsize = 0;
5057 SMB_OFF_T startpos;
5058 size_t tcount;
5059 BOOL write_through;
5060 int smb_doff;
5061 char *data;
5062 write_bmpx_struct *wbms;
5063 BOOL send_response = False;
5064 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5065 START_PROFILE(SMBwriteBs);
5067 CHECK_FSP(fsp,conn);
5068 CHECK_WRITE(fsp);
5070 tcount = SVAL(inbuf,smb_vwv1);
5071 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
5072 numtowrite = SVAL(inbuf,smb_vwv6);
5073 smb_doff = SVAL(inbuf,smb_vwv7);
5075 data = smb_base(inbuf) + smb_doff;
5077 /* We need to send an SMBwriteC response, not an SMBwritebs */
5078 SCVAL(outbuf,smb_com,SMBwritec);
5080 /* This fd should have an auxiliary struct attached,
5081 check that it does */
5082 wbms = fsp->wbmpx_ptr;
5083 if(!wbms) {
5084 END_PROFILE(SMBwriteBs);
5085 return(-1);
5088 /* If write through is set we can return errors, else we must cache them */
5089 write_through = wbms->wr_mode;
5091 /* Check for an earlier error */
5092 if(wbms->wr_discard) {
5093 END_PROFILE(SMBwriteBs);
5094 return -1; /* Just discard the packet */
5097 nwritten = write_file(fsp,data,startpos,numtowrite);
5099 if(lp_syncalways(SNUM(conn)) || write_through)
5100 sync_file(conn,fsp);
5102 if (nwritten < (ssize_t)numtowrite) {
5103 if(write_through) {
5104 /* We are returning an error - we can delete the aux struct */
5105 if (wbms)
5106 free((char *)wbms);
5107 fsp->wbmpx_ptr = NULL;
5108 END_PROFILE(SMBwriteBs);
5109 return(ERROR_DOS(ERRHRD,ERRdiskfull));
5111 END_PROFILE(SMBwriteBs);
5112 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
5115 /* Increment the total written, if this matches tcount
5116 we can discard the auxiliary struct (hurrah !) and return a writeC */
5117 wbms->wr_total_written += nwritten;
5118 if(wbms->wr_total_written >= tcount) {
5119 if (write_through) {
5120 outsize = set_message(outbuf,1,0,True);
5121 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
5122 send_response = True;
5125 free((char *)wbms);
5126 fsp->wbmpx_ptr = NULL;
5129 if(send_response) {
5130 END_PROFILE(SMBwriteBs);
5131 return(outsize);
5134 END_PROFILE(SMBwriteBs);
5135 return(-1);
5138 /****************************************************************************
5139 Reply to a SMBgetattrE.
5140 ****************************************************************************/
5142 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5144 SMB_STRUCT_STAT sbuf;
5145 int outsize = 0;
5146 int mode;
5147 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5148 START_PROFILE(SMBgetattrE);
5150 outsize = set_message(outbuf,11,0,True);
5152 if(!fsp || (fsp->conn != conn)) {
5153 END_PROFILE(SMBgetattrE);
5154 return ERROR_DOS(ERRDOS,ERRbadfid);
5157 /* Do an fstat on this file */
5158 if(fsp_stat(fsp, &sbuf)) {
5159 END_PROFILE(SMBgetattrE);
5160 return(UNIXERROR(ERRDOS,ERRnoaccess));
5163 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
5166 * Convert the times into dos times. Set create
5167 * date to be last modify date as UNIX doesn't save
5168 * this.
5171 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
5172 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
5173 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
5175 if (mode & aDIR) {
5176 SIVAL(outbuf,smb_vwv6,0);
5177 SIVAL(outbuf,smb_vwv8,0);
5178 } else {
5179 uint32 allocation_size = get_allocation_size(fsp, &sbuf);
5180 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
5181 SIVAL(outbuf,smb_vwv8,allocation_size);
5183 SSVAL(outbuf,smb_vwv10, mode);
5185 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
5187 END_PROFILE(SMBgetattrE);
5188 return(outsize);