r560: Fix bugzilla 1279: cannot control individual print jobs using cups
[Samba/gebeck_regimport.git] / source3 / smbd / reply.c
blobac239c7e042f5d699bc4dfc1ba0ef69a08ffbbc3
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 int Protocol;
31 extern int max_send;
32 extern int max_recv;
33 extern char magic_char;
34 extern BOOL case_sensitive;
35 extern BOOL case_preserve;
36 extern BOOL short_case_preserve;
37 extern int global_oplock_break;
38 unsigned int smb_echo_count = 0;
40 extern BOOL global_encrypted_passwords_negotiated;
42 /****************************************************************************
43 Ensure we check the path in *exactly* the same way as W2K.
44 We're assuming here that '/' is not the second byte in any multibyte char
45 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
46 set.
47 ****************************************************************************/
49 NTSTATUS check_path_syntax(pstring destname, const pstring srcname)
51 char *d = destname;
52 const char *s = srcname;
53 NTSTATUS ret = NT_STATUS_OK;
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 ((s[0] == '.') && (s[1] == '\0')) {
65 ret = NT_STATUS_OBJECT_NAME_INVALID;
66 break;
68 if ((d != destname) && (*s != '\0')) {
69 /* We only care about non-leading or trailing '/' or '\\' */
70 *d++ = '/';
72 } else if ((s[0] == '.') && (s[1] == '.') && (IS_DIRECTORY_SEP(s[2]) || s[2] == '\0')) {
73 /* Uh oh - "../" or "..\\" or "..\0" ! */
76 * No mb char starts with '.' so we're safe checking the directory separator here.
79 /* If we just added a '/', delete it. */
81 if ((d > destname) && (*(d-1) == '/')) {
82 *(d-1) = '\0';
83 if (d == (destname + 1)) {
84 d--;
85 } else {
86 d -= 2;
89 /* Are we at the start ? Can't go back further if so. */
90 if (d == destname) {
91 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
92 break;
94 /* Go back one level... */
95 /* We know this is safe as '/' cannot be part of a mb sequence. */
96 /* NOTE - if this assumption is invalid we are not in good shape... */
97 while (d > destname) {
98 if (*d == '/')
99 break;
100 d--;
102 s += 3;
103 } else if ((s[0] == '.') && (IS_DIRECTORY_SEP(s[1]) || (s[1] == '\0'))) {
106 * No mb char starts with '.' so we're safe checking the directory separator here.
109 /* "./" or ".\\" fails with a different error depending on where it is... */
111 if (s == srcname) {
112 ret = NT_STATUS_OBJECT_NAME_INVALID;
113 break;
114 } else {
115 if (s[1] != '\0' && s[2] == '\0') {
116 ret = NT_STATUS_INVALID_PARAMETER;
117 break;
119 ret = NT_STATUS_OBJECT_PATH_NOT_FOUND;
120 break;
122 s++;
123 } else {
124 if (!(*s & 0x80)) {
125 *d++ = *s++;
126 } else {
127 switch(next_mb_char_size(s)) {
128 case 4:
129 *d++ = *s++;
130 case 3:
131 *d++ = *s++;
132 case 2:
133 *d++ = *s++;
134 case 1:
135 *d++ = *s++;
136 break;
137 default:
138 DEBUG(0,("check_path_syntax: character length assumptions invalid !\n"));
139 *d = '\0';
140 return NT_STATUS_INVALID_PARAMETER;
145 *d = '\0';
146 return ret;
149 /****************************************************************************
150 Pull a string and check the path - provide for error return.
151 ****************************************************************************/
153 size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags, NTSTATUS *err)
155 pstring tmppath;
156 char *tmppath_ptr = tmppath;
157 size_t ret;
158 #ifdef DEVELOPER
159 SMB_ASSERT(dest_len == sizeof(pstring));
160 #endif
162 if (src_len == 0) {
163 ret = srvstr_pull_buf( inbuf, tmppath_ptr, src, dest_len, flags);
164 } else {
165 ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags);
167 *err = check_path_syntax(dest, tmppath);
168 return ret;
171 /****************************************************************************
172 Reply to a special message.
173 ****************************************************************************/
175 int reply_special(char *inbuf,char *outbuf)
177 int outsize = 4;
178 int msg_type = CVAL(inbuf,0);
179 int msg_flags = CVAL(inbuf,1);
180 fstring name1,name2;
181 char name_type = 0;
183 static BOOL already_got_session = False;
185 *name1 = *name2 = 0;
187 memset(outbuf,'\0',smb_size);
189 smb_setlen(outbuf,0);
191 switch (msg_type) {
192 case 0x81: /* session request */
194 if (already_got_session) {
195 exit_server("multiple session request not permitted");
198 SCVAL(outbuf,0,0x82);
199 SCVAL(outbuf,3,0);
200 if (name_len(inbuf+4) > 50 ||
201 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
202 DEBUG(0,("Invalid name length in session request\n"));
203 return(0);
205 name_extract(inbuf,4,name1);
206 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
207 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
208 name1,name2));
210 set_local_machine_name(name1, True);
211 set_remote_machine_name(name2, True);
213 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
214 get_local_machine_name(), get_remote_machine_name(),
215 name_type));
217 if (name_type == 'R') {
218 /* We are being asked for a pathworks session ---
219 no thanks! */
220 SCVAL(outbuf, 0,0x83);
221 break;
224 /* only add the client's machine name to the list
225 of possibly valid usernames if we are operating
226 in share mode security */
227 if (lp_security() == SEC_SHARE) {
228 add_session_user(get_remote_machine_name());
231 reload_services(True);
232 reopen_logs();
234 claim_connection(NULL,"",0,True,FLAG_MSG_GENERAL|FLAG_MSG_SMBD);
236 already_got_session = True;
237 break;
239 case 0x89: /* session keepalive request
240 (some old clients produce this?) */
241 SCVAL(outbuf,0,SMBkeepalive);
242 SCVAL(outbuf,3,0);
243 break;
245 case 0x82: /* positive session response */
246 case 0x83: /* negative session response */
247 case 0x84: /* retarget session response */
248 DEBUG(0,("Unexpected session response\n"));
249 break;
251 case SMBkeepalive: /* session keepalive */
252 default:
253 return(0);
256 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
257 msg_type, msg_flags));
259 return(outsize);
262 /****************************************************************************
263 Reply to a tcon.
264 ****************************************************************************/
266 int reply_tcon(connection_struct *conn,
267 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
269 const char *service;
270 pstring service_buf;
271 pstring password;
272 pstring dev;
273 int outsize = 0;
274 uint16 vuid = SVAL(inbuf,smb_uid);
275 int pwlen=0;
276 NTSTATUS nt_status;
277 char *p;
278 DATA_BLOB password_blob;
280 START_PROFILE(SMBtcon);
282 *service_buf = *password = *dev = 0;
284 p = smb_buf(inbuf)+1;
285 p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service_buf), STR_TERMINATE) + 1;
286 pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1;
287 p += pwlen;
288 p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1;
290 p = strrchr_m(service_buf,'\\');
291 if (p) {
292 service = p+1;
293 } else {
294 service = service_buf;
297 password_blob = data_blob(password, pwlen+1);
299 conn = make_connection(service,password_blob,dev,vuid,&nt_status);
301 data_blob_clear_free(&password_blob);
303 if (!conn) {
304 END_PROFILE(SMBtcon);
305 return ERROR_NT(nt_status);
308 outsize = set_message(outbuf,2,0,True);
309 SSVAL(outbuf,smb_vwv0,max_recv);
310 SSVAL(outbuf,smb_vwv1,conn->cnum);
311 SSVAL(outbuf,smb_tid,conn->cnum);
313 DEBUG(3,("tcon service=%s cnum=%d\n",
314 service, conn->cnum));
316 END_PROFILE(SMBtcon);
317 return(outsize);
320 /****************************************************************************
321 Reply to a tcon and X.
322 ****************************************************************************/
324 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
326 fstring service;
327 DATA_BLOB password;
329 /* what the cleint thinks the device is */
330 fstring client_devicetype;
331 /* what the server tells the client the share represents */
332 const char *server_devicetype;
333 NTSTATUS nt_status;
334 uint16 vuid = SVAL(inbuf,smb_uid);
335 int passlen = SVAL(inbuf,smb_vwv3);
336 pstring path;
337 char *p, *q;
338 extern BOOL global_encrypted_passwords_negotiated;
340 START_PROFILE(SMBtconX);
342 *service = *client_devicetype = 0;
344 /* we might have to close an old one */
345 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
346 close_cnum(conn,vuid);
349 if (passlen > MAX_PASS_LEN) {
350 return ERROR_DOS(ERRDOS,ERRbuftoosmall);
353 if (global_encrypted_passwords_negotiated) {
354 password = data_blob(smb_buf(inbuf),passlen);
355 } else {
356 password = data_blob(smb_buf(inbuf),passlen+1);
357 /* Ensure correct termination */
358 password.data[passlen]=0;
361 p = smb_buf(inbuf) + passlen;
362 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
365 * the service name can be either: \\server\share
366 * or share directly like on the DELL PowerVault 705
368 if (*path=='\\') {
369 q = strchr_m(path+2,'\\');
370 if (!q) {
371 END_PROFILE(SMBtconX);
372 return(ERROR_DOS(ERRDOS,ERRnosuchshare));
374 fstrcpy(service,q+1);
376 else
377 fstrcpy(service,path);
379 p += srvstr_pull(inbuf, client_devicetype, p, sizeof(client_devicetype), 6, STR_ASCII);
381 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
383 conn = make_connection(service,password,client_devicetype,vuid,&nt_status);
385 data_blob_clear_free(&password);
387 if (!conn) {
388 END_PROFILE(SMBtconX);
389 return ERROR_NT(nt_status);
392 if ( IS_IPC(conn) )
393 server_devicetype = "IPC";
394 else if ( IS_PRINT(conn) )
395 server_devicetype = "LPT1:";
396 else
397 server_devicetype = "A:";
399 if (Protocol < PROTOCOL_NT1) {
400 set_message(outbuf,2,0,True);
401 p = smb_buf(outbuf);
402 p += srvstr_push(outbuf, p, server_devicetype, -1,
403 STR_TERMINATE|STR_ASCII);
404 set_message_end(outbuf,p);
405 } else {
406 /* NT sets the fstype of IPC$ to the null string */
407 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
409 set_message(outbuf,3,0,True);
411 p = smb_buf(outbuf);
412 p += srvstr_push(outbuf, p, server_devicetype, -1,
413 STR_TERMINATE|STR_ASCII);
414 p += srvstr_push(outbuf, p, fstype, -1,
415 STR_TERMINATE);
417 set_message_end(outbuf,p);
419 /* what does setting this bit do? It is set by NT4 and
420 may affect the ability to autorun mounted cdroms */
421 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
422 (lp_csc_policy(SNUM(conn)) << 2));
424 init_dfsroot(conn, inbuf, outbuf);
428 DEBUG(3,("tconX service=%s \n",
429 service));
431 /* set the incoming and outgoing tid to the just created one */
432 SSVAL(inbuf,smb_tid,conn->cnum);
433 SSVAL(outbuf,smb_tid,conn->cnum);
435 END_PROFILE(SMBtconX);
436 return chain_reply(inbuf,outbuf,length,bufsize);
439 /****************************************************************************
440 Reply to an unknown type.
441 ****************************************************************************/
443 int reply_unknown(char *inbuf,char *outbuf)
445 int type;
446 type = CVAL(inbuf,smb_com);
448 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
449 smb_fn_name(type), type, type));
451 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
454 /****************************************************************************
455 Reply to an ioctl.
456 ****************************************************************************/
458 int reply_ioctl(connection_struct *conn,
459 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
461 uint16 device = SVAL(inbuf,smb_vwv1);
462 uint16 function = SVAL(inbuf,smb_vwv2);
463 uint32 ioctl_code = (device << 16) + function;
464 int replysize, outsize;
465 char *p;
466 START_PROFILE(SMBioctl);
468 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
470 switch (ioctl_code) {
471 case IOCTL_QUERY_JOB_INFO:
472 replysize = 32;
473 break;
474 default:
475 END_PROFILE(SMBioctl);
476 return(ERROR_DOS(ERRSRV,ERRnosupport));
479 outsize = set_message(outbuf,8,replysize+1,True);
480 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
481 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
482 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
483 p = smb_buf(outbuf) + 1; /* Allow for alignment */
485 switch (ioctl_code) {
486 case IOCTL_QUERY_JOB_INFO:
488 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
489 if (!fsp) {
490 END_PROFILE(SMBioctl);
491 return(UNIXERROR(ERRDOS,ERRbadfid));
493 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
494 srvstr_push(outbuf, p+2, global_myname(), 15, STR_TERMINATE|STR_ASCII);
495 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
496 break;
500 END_PROFILE(SMBioctl);
501 return outsize;
504 /****************************************************************************
505 Reply to a chkpth.
506 ****************************************************************************/
508 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
510 int outsize = 0;
511 int mode;
512 pstring name;
513 BOOL ok = False;
514 BOOL bad_path = False;
515 SMB_STRUCT_STAT sbuf;
516 NTSTATUS status;
518 START_PROFILE(SMBchkpth);
520 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
521 if (!NT_STATUS_IS_OK(status)) {
522 END_PROFILE(SMBchkpth);
523 return ERROR_NT(status);
526 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
528 unix_convert(name,conn,0,&bad_path,&sbuf);
530 mode = SVAL(inbuf,smb_vwv0);
532 if (check_name(name,conn)) {
533 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,name,&sbuf) == 0)
534 if (!(ok = S_ISDIR(sbuf.st_mode))) {
535 END_PROFILE(SMBchkpth);
536 return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath);
540 if (!ok) {
541 /* We special case this - as when a Windows machine
542 is parsing a path is steps through the components
543 one at a time - if a component fails it expects
544 ERRbadpath, not ERRbadfile.
546 if(errno == ENOENT) {
548 * Windows returns different error codes if
549 * the parent directory is valid but not the
550 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
551 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
552 * if the path is invalid.
554 if (bad_path) {
555 END_PROFILE(SMBchkpth);
556 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
557 } else {
558 END_PROFILE(SMBchkpth);
559 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
561 } else if (errno == ENOTDIR) {
562 END_PROFILE(SMBchkpth);
563 return ERROR_NT(NT_STATUS_NOT_A_DIRECTORY);
566 END_PROFILE(SMBchkpth);
567 return(UNIXERROR(ERRDOS,ERRbadpath));
570 outsize = set_message(outbuf,0,0,True);
572 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
574 END_PROFILE(SMBchkpth);
575 return(outsize);
578 /****************************************************************************
579 Reply to a getatr.
580 ****************************************************************************/
582 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
584 pstring fname;
585 int outsize = 0;
586 SMB_STRUCT_STAT sbuf;
587 BOOL ok = False;
588 int mode=0;
589 SMB_OFF_T size=0;
590 time_t mtime=0;
591 BOOL bad_path = False;
592 char *p;
593 NTSTATUS status;
595 START_PROFILE(SMBgetatr);
597 p = smb_buf(inbuf) + 1;
598 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
599 if (!NT_STATUS_IS_OK(status)) {
600 END_PROFILE(SMBgetatr);
601 return ERROR_NT(status);
604 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
606 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
607 under WfWg - weird! */
608 if (! (*fname)) {
609 mode = aHIDDEN | aDIR;
610 if (!CAN_WRITE(conn))
611 mode |= aRONLY;
612 size = 0;
613 mtime = 0;
614 ok = True;
615 } else {
616 unix_convert(fname,conn,0,&bad_path,&sbuf);
617 if (check_name(fname,conn)) {
618 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,fname,&sbuf) == 0) {
619 mode = dos_mode(conn,fname,&sbuf);
620 size = sbuf.st_size;
621 mtime = sbuf.st_mtime;
622 if (mode & aDIR)
623 size = 0;
624 ok = True;
625 } else {
626 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
631 if (!ok) {
632 END_PROFILE(SMBgetatr);
633 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadfile);
636 outsize = set_message(outbuf,10,0,True);
638 SSVAL(outbuf,smb_vwv0,mode);
639 if(lp_dos_filetime_resolution(SNUM(conn)) )
640 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
641 else
642 put_dos_date3(outbuf,smb_vwv1,mtime);
643 SIVAL(outbuf,smb_vwv3,(uint32)size);
645 if (Protocol >= PROTOCOL_NT1)
646 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
648 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
650 END_PROFILE(SMBgetatr);
651 return(outsize);
654 /****************************************************************************
655 Reply to a setatr.
656 ****************************************************************************/
658 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
660 pstring fname;
661 int outsize = 0;
662 BOOL ok=False;
663 int mode;
664 time_t mtime;
665 SMB_STRUCT_STAT sbuf;
666 BOOL bad_path = False;
667 char *p;
668 NTSTATUS status;
670 START_PROFILE(SMBsetatr);
672 p = smb_buf(inbuf) + 1;
673 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
674 if (!NT_STATUS_IS_OK(status)) {
675 END_PROFILE(SMBsetatr);
676 return ERROR_NT(status);
679 unix_convert(fname,conn,0,&bad_path,&sbuf);
681 mode = SVAL(inbuf,smb_vwv0);
682 mtime = make_unix_date3(inbuf+smb_vwv1);
684 if (mode != FILE_ATTRIBUTE_NORMAL) {
685 if (VALID_STAT_OF_DIR(sbuf))
686 mode |= aDIR;
687 else
688 mode &= ~aDIR;
690 if (check_name(fname,conn)) {
691 ok = (file_set_dosmode(conn,fname,mode,NULL) == 0);
693 } else {
694 ok = True;
697 if (ok)
698 ok = set_filetime(conn,fname,mtime);
700 if (!ok) {
701 END_PROFILE(SMBsetatr);
702 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
705 outsize = set_message(outbuf,0,0,True);
707 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
709 END_PROFILE(SMBsetatr);
710 return(outsize);
713 /****************************************************************************
714 Reply to a dskattr.
715 ****************************************************************************/
717 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
719 int outsize = 0;
720 SMB_BIG_UINT dfree,dsize,bsize;
721 START_PROFILE(SMBdskattr);
723 SMB_VFS_DISK_FREE(conn,".",True,&bsize,&dfree,&dsize);
725 outsize = set_message(outbuf,5,0,True);
727 if (Protocol <= PROTOCOL_LANMAN2) {
728 double total_space, free_space;
729 /* we need to scale this to a number that DOS6 can handle. We
730 use floating point so we can handle large drives on systems
731 that don't have 64 bit integers
733 we end up displaying a maximum of 2G to DOS systems
735 total_space = dsize * (double)bsize;
736 free_space = dfree * (double)bsize;
738 dsize = (total_space+63*512) / (64*512);
739 dfree = (free_space+63*512) / (64*512);
741 if (dsize > 0xFFFF) dsize = 0xFFFF;
742 if (dfree > 0xFFFF) dfree = 0xFFFF;
744 SSVAL(outbuf,smb_vwv0,dsize);
745 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
746 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
747 SSVAL(outbuf,smb_vwv3,dfree);
748 } else {
749 SSVAL(outbuf,smb_vwv0,dsize);
750 SSVAL(outbuf,smb_vwv1,bsize/512);
751 SSVAL(outbuf,smb_vwv2,512);
752 SSVAL(outbuf,smb_vwv3,dfree);
755 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
757 END_PROFILE(SMBdskattr);
758 return(outsize);
761 /****************************************************************************
762 Reply to a search.
763 Can be called from SMBsearch, SMBffirst or SMBfunique.
764 ****************************************************************************/
766 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
768 pstring mask;
769 pstring directory;
770 pstring fname;
771 SMB_OFF_T size;
772 int mode;
773 time_t date;
774 int dirtype;
775 int outsize = 0;
776 unsigned int numentries = 0;
777 unsigned int maxentries = 0;
778 BOOL finished = False;
779 char *p;
780 BOOL ok = False;
781 int status_len;
782 pstring path;
783 char status[21];
784 int dptr_num= -1;
785 BOOL check_descend = False;
786 BOOL expect_close = False;
787 BOOL can_open = True;
788 BOOL bad_path = False;
789 NTSTATUS nt_status;
790 START_PROFILE(SMBsearch);
792 *mask = *directory = *fname = 0;
794 /* If we were called as SMBffirst then we must expect close. */
795 if(CVAL(inbuf,smb_com) == SMBffirst)
796 expect_close = True;
798 outsize = set_message(outbuf,1,3,True);
799 maxentries = SVAL(inbuf,smb_vwv0);
800 dirtype = SVAL(inbuf,smb_vwv1);
801 p = smb_buf(inbuf) + 1;
802 p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &nt_status);
803 if (!NT_STATUS_IS_OK(nt_status)) {
804 END_PROFILE(SMBsearch);
805 return ERROR_NT(nt_status);
807 p++;
808 status_len = SVAL(p, 0);
809 p += 2;
811 /* dirtype &= ~aDIR; */
813 if (status_len == 0) {
814 SMB_STRUCT_STAT sbuf;
815 pstring dir2;
817 pstrcpy(directory,path);
818 pstrcpy(dir2,path);
819 unix_convert(directory,conn,0,&bad_path,&sbuf);
820 unix_format(dir2);
822 if (!check_name(directory,conn))
823 can_open = False;
825 p = strrchr_m(dir2,'/');
826 if (p == NULL) {
827 pstrcpy(mask,dir2);
828 *dir2 = 0;
829 } else {
830 *p = 0;
831 pstrcpy(mask,p+1);
834 p = strrchr_m(directory,'/');
835 if (!p)
836 *directory = 0;
837 else
838 *p = 0;
840 if (strlen(directory) == 0)
841 pstrcpy(directory,".");
842 memset((char *)status,'\0',21);
843 SCVAL(status,0,(dirtype & 0x1F));
844 } else {
845 int status_dirtype;
847 memcpy(status,p,21);
848 status_dirtype = CVAL(status,0) & 0x1F;
849 if (status_dirtype != (dirtype & 0x1F))
850 dirtype = status_dirtype;
852 conn->dirptr = dptr_fetch(status+12,&dptr_num);
853 if (!conn->dirptr)
854 goto SearchEmpty;
855 string_set(&conn->dirpath,dptr_path(dptr_num));
856 pstrcpy(mask, dptr_wcard(dptr_num));
859 if (can_open) {
860 p = smb_buf(outbuf) + 3;
861 ok = True;
863 if (status_len == 0) {
864 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
865 if (dptr_num < 0) {
866 if(dptr_num == -2) {
867 END_PROFILE(SMBsearch);
868 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnofids);
870 END_PROFILE(SMBsearch);
871 return ERROR_DOS(ERRDOS,ERRnofids);
873 dptr_set_wcard(dptr_num, strdup(mask));
874 dptr_set_attr(dptr_num, dirtype);
875 } else {
876 dirtype = dptr_attr(dptr_num);
879 DEBUG(4,("dptr_num is %d\n",dptr_num));
881 if (ok) {
882 if ((dirtype&0x1F) == aVOLID) {
883 memcpy(p,status,21);
884 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
885 dptr_fill(p+12,dptr_num);
886 if (dptr_zero(p+12) && (status_len==0))
887 numentries = 1;
888 else
889 numentries = 0;
890 p += DIR_STRUCT_SIZE;
891 } else {
892 unsigned int i;
893 maxentries = MIN(maxentries, ((BUFFER_SIZE - (p - outbuf))/DIR_STRUCT_SIZE));
895 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
896 conn->dirpath,lp_dontdescend(SNUM(conn))));
897 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
898 check_descend = True;
900 for (i=numentries;(i<maxentries) && !finished;i++) {
901 finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
902 if (!finished) {
903 memcpy(p,status,21);
904 make_dir_struct(p,mask,fname,size,mode,date);
905 dptr_fill(p+12,dptr_num);
906 numentries++;
908 p += DIR_STRUCT_SIZE;
911 } /* if (ok ) */
915 SearchEmpty:
917 /* If we were called as SMBffirst with smb_search_id == NULL
918 and no entries were found then return error and close dirptr
919 (X/Open spec) */
921 if(ok && expect_close && numentries == 0 && status_len == 0) {
922 if (Protocol < PROTOCOL_NT1) {
923 SCVAL(outbuf,smb_rcls,ERRDOS);
924 SSVAL(outbuf,smb_err,ERRnofiles);
926 /* Also close the dptr - we know it's gone */
927 dptr_close(&dptr_num);
928 } else if (numentries == 0 || !ok) {
929 if (Protocol < PROTOCOL_NT1) {
930 SCVAL(outbuf,smb_rcls,ERRDOS);
931 SSVAL(outbuf,smb_err,ERRnofiles);
933 dptr_close(&dptr_num);
936 /* If we were called as SMBfunique, then we can close the dirptr now ! */
937 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
938 dptr_close(&dptr_num);
940 SSVAL(outbuf,smb_vwv0,numentries);
941 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
942 SCVAL(smb_buf(outbuf),0,5);
943 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
945 if (Protocol >= PROTOCOL_NT1)
946 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
948 outsize += DIR_STRUCT_SIZE*numentries;
949 smb_setlen(outbuf,outsize - 4);
951 if ((! *directory) && dptr_path(dptr_num))
952 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
954 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
955 smb_fn_name(CVAL(inbuf,smb_com)),
956 mask, directory, dirtype, numentries, maxentries ) );
958 END_PROFILE(SMBsearch);
959 return(outsize);
962 /****************************************************************************
963 Reply to a fclose (stop directory search).
964 ****************************************************************************/
966 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
968 int outsize = 0;
969 int status_len;
970 pstring path;
971 char status[21];
972 int dptr_num= -2;
973 char *p;
974 NTSTATUS err;
976 START_PROFILE(SMBfclose);
978 outsize = set_message(outbuf,1,0,True);
979 p = smb_buf(inbuf) + 1;
980 p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err);
981 if (!NT_STATUS_IS_OK(err)) {
982 END_PROFILE(SMBfclose);
983 return ERROR_NT(err);
985 p++;
986 status_len = SVAL(p,0);
987 p += 2;
989 if (status_len == 0) {
990 END_PROFILE(SMBfclose);
991 return ERROR_DOS(ERRSRV,ERRsrverror);
994 memcpy(status,p,21);
996 if(dptr_fetch(status+12,&dptr_num)) {
997 /* Close the dptr - we know it's gone */
998 dptr_close(&dptr_num);
1001 SSVAL(outbuf,smb_vwv0,0);
1003 DEBUG(3,("search close\n"));
1005 END_PROFILE(SMBfclose);
1006 return(outsize);
1009 /****************************************************************************
1010 Reply to an open.
1011 ****************************************************************************/
1013 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1015 pstring fname;
1016 int outsize = 0;
1017 int fmode=0;
1018 int share_mode;
1019 SMB_OFF_T size = 0;
1020 time_t mtime=0;
1021 int rmode=0;
1022 SMB_STRUCT_STAT sbuf;
1023 BOOL bad_path = False;
1024 files_struct *fsp;
1025 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1026 uint16 dos_attr = SVAL(inbuf,smb_vwv1);
1027 NTSTATUS status;
1028 START_PROFILE(SMBopen);
1030 share_mode = SVAL(inbuf,smb_vwv0);
1032 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
1033 if (!NT_STATUS_IS_OK(status)) {
1034 END_PROFILE(SMBopen);
1035 return ERROR_NT(status);
1038 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1040 unix_convert(fname,conn,0,&bad_path,&sbuf);
1042 fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1043 (uint32)dos_attr, oplock_request,&rmode,NULL);
1045 if (!fsp) {
1046 END_PROFILE(SMBopen);
1047 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1050 size = sbuf.st_size;
1051 fmode = dos_mode(conn,fname,&sbuf);
1052 mtime = sbuf.st_mtime;
1054 if (fmode & aDIR) {
1055 DEBUG(3,("attempt to open a directory %s\n",fname));
1056 close_file(fsp,False);
1057 END_PROFILE(SMBopen);
1058 return ERROR_DOS(ERRDOS,ERRnoaccess);
1061 outsize = set_message(outbuf,7,0,True);
1062 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1063 SSVAL(outbuf,smb_vwv1,fmode);
1064 if(lp_dos_filetime_resolution(SNUM(conn)) )
1065 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1066 else
1067 put_dos_date3(outbuf,smb_vwv2,mtime);
1068 SIVAL(outbuf,smb_vwv4,(uint32)size);
1069 SSVAL(outbuf,smb_vwv6,rmode);
1071 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1072 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1074 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1075 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1076 END_PROFILE(SMBopen);
1077 return(outsize);
1080 /****************************************************************************
1081 Reply to an open and X.
1082 ****************************************************************************/
1084 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1086 pstring fname;
1087 int smb_mode = SVAL(inbuf,smb_vwv3);
1088 int smb_attr = SVAL(inbuf,smb_vwv5);
1089 /* Breakout the oplock request bits so we can set the
1090 reply bits separately. */
1091 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1092 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1093 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1094 #if 0
1095 int open_flags = SVAL(inbuf,smb_vwv2);
1096 int smb_sattr = SVAL(inbuf,smb_vwv4);
1097 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1098 #endif
1099 int smb_ofun = SVAL(inbuf,smb_vwv8);
1100 SMB_OFF_T size=0;
1101 int fmode=0,mtime=0,rmode=0;
1102 SMB_STRUCT_STAT sbuf;
1103 int smb_action = 0;
1104 BOOL bad_path = False;
1105 files_struct *fsp;
1106 NTSTATUS status;
1107 START_PROFILE(SMBopenX);
1109 /* If it's an IPC, pass off the pipe handler. */
1110 if (IS_IPC(conn)) {
1111 if (lp_nt_pipe_support()) {
1112 END_PROFILE(SMBopenX);
1113 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1114 } else {
1115 END_PROFILE(SMBopenX);
1116 return ERROR_DOS(ERRSRV,ERRaccess);
1120 /* XXXX we need to handle passed times, sattr and flags */
1121 srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status);
1122 if (!NT_STATUS_IS_OK(status)) {
1123 END_PROFILE(SMBopenX);
1124 return ERROR_NT(status);
1127 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1129 unix_convert(fname,conn,0,&bad_path,&sbuf);
1131 fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,(uint32)smb_attr,
1132 oplock_request, &rmode,&smb_action);
1134 if (!fsp) {
1135 END_PROFILE(SMBopenX);
1136 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1139 size = sbuf.st_size;
1140 fmode = dos_mode(conn,fname,&sbuf);
1141 mtime = sbuf.st_mtime;
1142 if (fmode & aDIR) {
1143 close_file(fsp,False);
1144 END_PROFILE(SMBopenX);
1145 return ERROR_DOS(ERRDOS,ERRnoaccess);
1148 /* If the caller set the extended oplock request bit
1149 and we granted one (by whatever means) - set the
1150 correct bit for extended oplock reply.
1153 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn)))
1154 smb_action |= EXTENDED_OPLOCK_GRANTED;
1156 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1157 smb_action |= EXTENDED_OPLOCK_GRANTED;
1159 /* If the caller set the core oplock request bit
1160 and we granted one (by whatever means) - set the
1161 correct bit for core oplock reply.
1164 if (core_oplock_request && lp_fake_oplocks(SNUM(conn)))
1165 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1167 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1168 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1170 set_message(outbuf,15,0,True);
1171 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1172 SSVAL(outbuf,smb_vwv3,fmode);
1173 if(lp_dos_filetime_resolution(SNUM(conn)) )
1174 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1175 else
1176 put_dos_date3(outbuf,smb_vwv4,mtime);
1177 SIVAL(outbuf,smb_vwv6,(uint32)size);
1178 SSVAL(outbuf,smb_vwv8,rmode);
1179 SSVAL(outbuf,smb_vwv11,smb_action);
1181 END_PROFILE(SMBopenX);
1182 return chain_reply(inbuf,outbuf,length,bufsize);
1185 /****************************************************************************
1186 Reply to a SMBulogoffX.
1187 ****************************************************************************/
1189 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1191 uint16 vuid = SVAL(inbuf,smb_uid);
1192 user_struct *vuser = get_valid_user_struct(vuid);
1193 START_PROFILE(SMBulogoffX);
1195 if(vuser == 0)
1196 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1198 /* in user level security we are supposed to close any files
1199 open by this user */
1200 if ((vuser != 0) && (lp_security() != SEC_SHARE))
1201 file_close_user(vuid);
1203 invalidate_vuid(vuid);
1205 set_message(outbuf,2,0,True);
1207 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1209 END_PROFILE(SMBulogoffX);
1210 return chain_reply(inbuf,outbuf,length,bufsize);
1213 /****************************************************************************
1214 Reply to a mknew or a create.
1215 ****************************************************************************/
1217 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1219 pstring fname;
1220 int com;
1221 int outsize = 0;
1222 int createmode;
1223 int ofun = 0;
1224 BOOL bad_path = False;
1225 files_struct *fsp;
1226 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1227 SMB_STRUCT_STAT sbuf;
1228 NTSTATUS status;
1229 START_PROFILE(SMBcreate);
1231 com = SVAL(inbuf,smb_com);
1233 createmode = SVAL(inbuf,smb_vwv0);
1234 srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status);
1235 if (!NT_STATUS_IS_OK(status)) {
1236 END_PROFILE(SMBcreate);
1237 return ERROR_NT(status);
1240 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1242 unix_convert(fname,conn,0,&bad_path,&sbuf);
1244 if (createmode & aVOLID)
1245 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1247 if(com == SMBmknew) {
1248 /* We should fail if file exists. */
1249 ofun = FILE_CREATE_IF_NOT_EXIST;
1250 } else {
1251 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1252 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1255 /* Open file in dos compatibility share mode. */
1256 fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1257 ofun, (uint32)createmode, oplock_request, NULL, NULL);
1259 if (!fsp) {
1260 END_PROFILE(SMBcreate);
1261 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1264 outsize = set_message(outbuf,1,0,True);
1265 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1267 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1268 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1270 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1271 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1273 DEBUG( 2, ( "new file %s\n", fname ) );
1274 DEBUG( 3, ( "mknew %s fd=%d dmode=%d\n", fname, fsp->fd, createmode ) );
1276 END_PROFILE(SMBcreate);
1277 return(outsize);
1280 /****************************************************************************
1281 Reply to a create temporary file.
1282 ****************************************************************************/
1284 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1286 pstring fname;
1287 int outsize = 0;
1288 int createattr;
1289 BOOL bad_path = False;
1290 files_struct *fsp;
1291 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1292 int tmpfd;
1293 SMB_STRUCT_STAT sbuf;
1294 char *p, *s;
1295 NTSTATUS status;
1296 unsigned int namelen;
1298 START_PROFILE(SMBctemp);
1300 createattr = SVAL(inbuf,smb_vwv0);
1301 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
1302 if (!NT_STATUS_IS_OK(status)) {
1303 END_PROFILE(SMBctemp);
1304 return ERROR_NT(status);
1306 if (*fname) {
1307 pstrcat(fname,"/TMXXXXXX");
1308 } else {
1309 pstrcat(fname,"TMXXXXXX");
1312 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1314 unix_convert(fname,conn,0,&bad_path,&sbuf);
1316 tmpfd = smb_mkstemp(fname);
1317 if (tmpfd == -1) {
1318 END_PROFILE(SMBctemp);
1319 return(UNIXERROR(ERRDOS,ERRnoaccess));
1322 SMB_VFS_STAT(conn,fname,&sbuf);
1324 /* Open file in dos compatibility share mode. */
1325 /* We should fail if file does not exist. */
1326 fsp = open_file_shared(conn,fname,&sbuf,
1327 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1328 FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
1329 (uint32)createattr, oplock_request, NULL, NULL);
1331 /* close fd from smb_mkstemp() */
1332 close(tmpfd);
1334 if (!fsp) {
1335 END_PROFILE(SMBctemp);
1336 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1339 outsize = set_message(outbuf,1,0,True);
1340 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1342 /* the returned filename is relative to the directory */
1343 s = strrchr_m(fname, '/');
1344 if (!s)
1345 s = fname;
1346 else
1347 s++;
1349 p = smb_buf(outbuf);
1350 #if 0
1351 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
1352 thing in the byte section. JRA */
1353 SSVALS(p, 0, -1); /* what is this? not in spec */
1354 #endif
1355 namelen = srvstr_push(outbuf, p, s, -1, STR_ASCII|STR_TERMINATE);
1356 p += namelen;
1357 outsize = set_message_end(outbuf, p);
1359 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1360 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1362 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1363 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1365 DEBUG( 2, ( "created temp file %s\n", fname ) );
1366 DEBUG( 3, ( "ctemp %s fd=%d umode=%o\n",
1367 fname, fsp->fd, sbuf.st_mode ) );
1369 END_PROFILE(SMBctemp);
1370 return(outsize);
1373 /*******************************************************************
1374 Check if a user is allowed to rename a file.
1375 ********************************************************************/
1377 static NTSTATUS can_rename(char *fname,connection_struct *conn, SMB_STRUCT_STAT *pst)
1379 int smb_action;
1380 int access_mode;
1381 files_struct *fsp;
1383 if (!CAN_WRITE(conn))
1384 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1386 if (S_ISDIR(pst->st_mode))
1387 return NT_STATUS_OK;
1389 /* We need a better way to return NT status codes from open... */
1390 unix_ERR_class = 0;
1391 unix_ERR_code = 0;
1393 fsp = open_file_shared1(conn, fname, pst, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1394 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action);
1396 if (!fsp) {
1397 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1398 if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1399 ret = NT_STATUS_SHARING_VIOLATION;
1400 unix_ERR_class = 0;
1401 unix_ERR_code = 0;
1402 unix_ERR_ntstatus = NT_STATUS_OK;
1403 return ret;
1405 close_file(fsp,False);
1406 return NT_STATUS_OK;
1409 /*******************************************************************
1410 Check if a user is allowed to delete a file.
1411 ********************************************************************/
1413 static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype, BOOL bad_path)
1415 SMB_STRUCT_STAT sbuf;
1416 int fmode;
1417 int smb_action;
1418 int access_mode;
1419 files_struct *fsp;
1421 DEBUG(10,("can_delete: %s, dirtype = %d\n",
1422 fname, dirtype ));
1424 if (!CAN_WRITE(conn))
1425 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1427 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
1428 if(errno == ENOENT) {
1429 if (bad_path)
1430 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1431 else
1432 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1434 return map_nt_error_from_unix(errno);
1437 fmode = dos_mode(conn,fname,&sbuf);
1439 /* Can't delete a directory. */
1440 if (fmode & aDIR)
1441 return NT_STATUS_FILE_IS_A_DIRECTORY;
1442 #if 0 /* JRATEST */
1443 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
1444 return NT_STATUS_OBJECT_NAME_INVALID;
1445 #endif /* JRATEST */
1447 if (!lp_delete_readonly(SNUM(conn))) {
1448 if (fmode & aRONLY)
1449 return NT_STATUS_CANNOT_DELETE;
1451 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1452 return NT_STATUS_NO_SUCH_FILE;
1454 /* We need a better way to return NT status codes from open... */
1455 unix_ERR_class = 0;
1456 unix_ERR_code = 0;
1458 fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1459 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action);
1461 if (!fsp) {
1462 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1463 if (!NT_STATUS_IS_OK(unix_ERR_ntstatus))
1464 ret = unix_ERR_ntstatus;
1465 else if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1466 ret = NT_STATUS_SHARING_VIOLATION;
1467 unix_ERR_class = 0;
1468 unix_ERR_code = 0;
1469 unix_ERR_ntstatus = NT_STATUS_OK;
1470 return ret;
1472 close_file(fsp,False);
1473 return NT_STATUS_OK;
1476 /****************************************************************************
1477 The guts of the unlink command, split out so it may be called by the NT SMB
1478 code.
1479 ****************************************************************************/
1481 NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
1483 pstring directory;
1484 pstring mask;
1485 char *p;
1486 int count=0;
1487 NTSTATUS error = NT_STATUS_OK;
1488 BOOL has_wild;
1489 BOOL bad_path = False;
1490 BOOL rc = True;
1491 SMB_STRUCT_STAT sbuf;
1493 *directory = *mask = 0;
1495 /* We must check for wildcards in the name given
1496 * directly by the client - before any unmangling.
1497 * This prevents an unmangling of a UNIX name containing
1498 * a DOS wildcard like '*' or '?' from unmangling into
1499 * a wildcard delete which was not intended.
1500 * FIX for #226. JRA.
1503 has_wild = ms_has_wild(name);
1505 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1507 p = strrchr_m(name,'/');
1508 if (!p) {
1509 pstrcpy(directory,".");
1510 pstrcpy(mask,name);
1511 } else {
1512 *p = 0;
1513 pstrcpy(directory,name);
1514 pstrcpy(mask,p+1);
1518 * We should only check the mangled cache
1519 * here if unix_convert failed. This means
1520 * that the path in 'mask' doesn't exist
1521 * on the file system and so we need to look
1522 * for a possible mangle. This patch from
1523 * Tine Smukavec <valentin.smukavec@hermes.si>.
1526 if (!rc && mangle_is_mangled(mask))
1527 mangle_check_cache( mask );
1529 if (!has_wild) {
1530 pstrcat(directory,"/");
1531 pstrcat(directory,mask);
1532 error = can_delete(directory,conn,dirtype,bad_path);
1533 if (!NT_STATUS_IS_OK(error))
1534 return error;
1536 if (SMB_VFS_UNLINK(conn,directory) == 0) {
1537 count++;
1539 } else {
1540 void *dirptr = NULL;
1541 const char *dname;
1543 if (check_name(directory,conn))
1544 dirptr = OpenDir(conn, directory, True);
1546 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1547 the pattern matches against the long name, otherwise the short name
1548 We don't implement this yet XXXX
1551 if (dirptr) {
1552 error = NT_STATUS_NO_SUCH_FILE;
1554 if (strequal(mask,"????????.???"))
1555 pstrcpy(mask,"*");
1557 while ((dname = ReadDirName(dirptr))) {
1558 pstring fname;
1559 BOOL sys_direntry = False;
1560 pstrcpy(fname,dname);
1562 /* Quick check for "." and ".." */
1563 if (fname[0] == '.') {
1564 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
1565 if ((dirtype & aDIR)) {
1566 sys_direntry = True;
1567 } else {
1568 continue;
1573 if(!mask_match(fname, mask, case_sensitive))
1574 continue;
1576 if (sys_direntry) {
1577 error = NT_STATUS_OBJECT_NAME_INVALID;
1578 break;
1581 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1582 error = can_delete(fname,conn,dirtype,bad_path);
1583 if (!NT_STATUS_IS_OK(error)) {
1584 continue;
1586 if (SMB_VFS_UNLINK(conn,fname) == 0)
1587 count++;
1588 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
1590 CloseDir(dirptr);
1594 if (count == 0 && NT_STATUS_IS_OK(error)) {
1595 error = map_nt_error_from_unix(errno);
1598 return error;
1601 /****************************************************************************
1602 Reply to a unlink
1603 ****************************************************************************/
1605 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
1606 int dum_buffsize)
1608 int outsize = 0;
1609 pstring name;
1610 int dirtype;
1611 NTSTATUS status;
1612 START_PROFILE(SMBunlink);
1614 dirtype = SVAL(inbuf,smb_vwv0);
1616 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
1617 if (!NT_STATUS_IS_OK(status)) {
1618 END_PROFILE(SMBunlink);
1619 return ERROR_NT(status);
1622 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1624 DEBUG(3,("reply_unlink : %s\n",name));
1626 status = unlink_internals(conn, dirtype, name);
1627 if (!NT_STATUS_IS_OK(status))
1628 return ERROR_NT(status);
1631 * Win2k needs a changenotify request response before it will
1632 * update after a rename..
1634 process_pending_change_notify_queue((time_t)0);
1636 outsize = set_message(outbuf,0,0,True);
1638 END_PROFILE(SMBunlink);
1639 return outsize;
1642 /****************************************************************************
1643 Fail for readbraw.
1644 ****************************************************************************/
1646 void fail_readraw(void)
1648 pstring errstr;
1649 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
1650 strerror(errno) );
1651 exit_server(errstr);
1654 /****************************************************************************
1655 Use sendfile in readbraw.
1656 ****************************************************************************/
1658 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
1659 ssize_t mincount, char *outbuf)
1661 ssize_t ret=0;
1663 #if defined(WITH_SENDFILE)
1665 * We can only use sendfile on a non-chained packet and on a file
1666 * that is exclusively oplocked. reply_readbraw has already checked the length.
1669 if ((nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) &&
1670 EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && lp_use_sendfile(SNUM(conn)) ) {
1671 DATA_BLOB header;
1673 _smb_setlen(outbuf,nread);
1674 header.data = outbuf;
1675 header.length = 4;
1676 header.free = NULL;
1678 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) {
1680 * Special hack for broken Linux with no 64 bit clean sendfile. If we
1681 * return ENOSYS then pretend we just got a normal read.
1683 if (errno == ENOSYS)
1684 goto normal_read;
1686 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
1687 fsp->fsp_name, strerror(errno) ));
1688 exit_server("send_file_readbraw sendfile failed");
1693 normal_read:
1694 #endif
1696 if (nread > 0) {
1697 ret = read_file(fsp,outbuf+4,startpos,nread);
1698 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1699 if (ret < mincount)
1700 ret = 0;
1701 #else
1702 if (ret < nread)
1703 ret = 0;
1704 #endif
1707 _smb_setlen(outbuf,ret);
1708 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
1709 fail_readraw();
1712 /****************************************************************************
1713 Reply to a readbraw (core+ protocol).
1714 ****************************************************************************/
1716 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
1718 extern struct current_user current_user;
1719 ssize_t maxcount,mincount;
1720 size_t nread = 0;
1721 SMB_OFF_T startpos;
1722 char *header = outbuf;
1723 files_struct *fsp;
1724 START_PROFILE(SMBreadbraw);
1726 if (srv_is_signing_active()) {
1727 exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
1731 * Special check if an oplock break has been issued
1732 * and the readraw request croses on the wire, we must
1733 * return a zero length response here.
1736 if(global_oplock_break) {
1737 _smb_setlen(header,0);
1738 if (write_data(smbd_server_fd(),header,4) != 4)
1739 fail_readraw();
1740 DEBUG(5,("readbraw - oplock break finished\n"));
1741 END_PROFILE(SMBreadbraw);
1742 return -1;
1745 fsp = file_fsp(inbuf,smb_vwv0);
1747 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1749 * fsp could be NULL here so use the value from the packet. JRA.
1751 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
1752 _smb_setlen(header,0);
1753 if (write_data(smbd_server_fd(),header,4) != 4)
1754 fail_readraw();
1755 END_PROFILE(SMBreadbraw);
1756 return(-1);
1759 CHECK_FSP(fsp,conn);
1761 flush_write_cache(fsp, READRAW_FLUSH);
1763 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
1764 if(CVAL(inbuf,smb_wct) == 10) {
1766 * This is a large offset (64 bit) read.
1768 #ifdef LARGE_SMB_OFF_T
1770 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
1772 #else /* !LARGE_SMB_OFF_T */
1775 * Ensure we haven't been sent a >32 bit offset.
1778 if(IVAL(inbuf,smb_vwv8) != 0) {
1779 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
1780 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
1781 _smb_setlen(header,0);
1782 if (write_data(smbd_server_fd(),header,4) != 4)
1783 fail_readraw();
1784 END_PROFILE(SMBreadbraw);
1785 return(-1);
1788 #endif /* LARGE_SMB_OFF_T */
1790 if(startpos < 0) {
1791 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
1792 _smb_setlen(header,0);
1793 if (write_data(smbd_server_fd(),header,4) != 4)
1794 fail_readraw();
1795 END_PROFILE(SMBreadbraw);
1796 return(-1);
1799 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
1800 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
1802 /* ensure we don't overrun the packet size */
1803 maxcount = MIN(65535,maxcount);
1805 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1806 SMB_OFF_T size = fsp->size;
1807 SMB_OFF_T sizeneeded = startpos + maxcount;
1809 if (size < sizeneeded) {
1810 SMB_STRUCT_STAT st;
1811 if (SMB_VFS_FSTAT(fsp,fsp->fd,&st) == 0)
1812 size = st.st_size;
1813 if (!fsp->can_write)
1814 fsp->size = size;
1817 if (startpos >= size)
1818 nread = 0;
1819 else
1820 nread = MIN(maxcount,(size - startpos));
1823 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1824 if (nread < mincount)
1825 nread = 0;
1826 #endif
1828 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
1829 (int)maxcount, (int)mincount, (int)nread ) );
1831 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf);
1833 DEBUG(5,("readbraw finished\n"));
1834 END_PROFILE(SMBreadbraw);
1835 return -1;
1838 /****************************************************************************
1839 Reply to a lockread (core+ protocol).
1840 ****************************************************************************/
1842 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
1844 ssize_t nread = -1;
1845 char *data;
1846 int outsize = 0;
1847 SMB_OFF_T startpos;
1848 size_t numtoread;
1849 NTSTATUS status;
1850 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1851 BOOL my_lock_ctx = False;
1852 START_PROFILE(SMBlockread);
1854 CHECK_FSP(fsp,conn);
1855 CHECK_READ(fsp);
1857 release_level_2_oplocks_on_change(fsp);
1859 numtoread = SVAL(inbuf,smb_vwv1);
1860 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
1862 outsize = set_message(outbuf,5,3,True);
1863 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1864 data = smb_buf(outbuf) + 3;
1867 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
1868 * protocol request that predates the read/write lock concept.
1869 * Thus instead of asking for a read lock here we need to ask
1870 * for a write lock. JRA.
1871 * Note that the requested lock size is unaffected by max_recv.
1874 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid),
1875 (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, &my_lock_ctx);
1877 if (NT_STATUS_V(status)) {
1878 #if 0
1880 * We used to make lockread a blocking lock. It turns out
1881 * that this isn't on W2k. Found by the Samba 4 RAW-READ torture
1882 * tester. JRA.
1885 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
1887 * A blocking lock was requested. Package up
1888 * this smb into a queued request and push it
1889 * onto the blocking lock queue.
1891 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)startpos,
1892 (SMB_BIG_UINT)numtoread)) {
1893 END_PROFILE(SMBlockread);
1894 return -1;
1897 #endif
1898 END_PROFILE(SMBlockread);
1899 return ERROR_NT(status);
1903 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
1906 if (numtoread > max_recv) {
1907 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
1908 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
1909 (unsigned int)numtoread, (unsigned int)max_recv ));
1910 numtoread = MIN(numtoread,max_recv);
1912 nread = read_file(fsp,data,startpos,numtoread);
1914 if (nread < 0) {
1915 END_PROFILE(SMBlockread);
1916 return(UNIXERROR(ERRDOS,ERRnoaccess));
1919 outsize += nread;
1920 SSVAL(outbuf,smb_vwv0,nread);
1921 SSVAL(outbuf,smb_vwv5,nread+3);
1922 SSVAL(smb_buf(outbuf),1,nread);
1924 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
1925 fsp->fnum, (int)numtoread, (int)nread));
1927 END_PROFILE(SMBlockread);
1928 return(outsize);
1931 /****************************************************************************
1932 Reply to a read.
1933 ****************************************************************************/
1935 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
1937 size_t numtoread;
1938 ssize_t nread = 0;
1939 char *data;
1940 SMB_OFF_T startpos;
1941 int outsize = 0;
1942 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1943 START_PROFILE(SMBread);
1945 CHECK_FSP(fsp,conn);
1946 CHECK_READ(fsp);
1948 numtoread = SVAL(inbuf,smb_vwv1);
1949 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
1951 outsize = set_message(outbuf,5,3,True);
1952 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1954 * The requested read size cannot be greater than max_recv. JRA.
1956 if (numtoread > max_recv) {
1957 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
1958 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
1959 (unsigned int)numtoread, (unsigned int)max_recv ));
1960 numtoread = MIN(numtoread,max_recv);
1963 data = smb_buf(outbuf) + 3;
1965 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1966 END_PROFILE(SMBread);
1967 return ERROR_DOS(ERRDOS,ERRlock);
1970 if (numtoread > 0)
1971 nread = read_file(fsp,data,startpos,numtoread);
1973 if (nread < 0) {
1974 END_PROFILE(SMBread);
1975 return(UNIXERROR(ERRDOS,ERRnoaccess));
1978 outsize += nread;
1979 SSVAL(outbuf,smb_vwv0,nread);
1980 SSVAL(outbuf,smb_vwv5,nread+3);
1981 SCVAL(smb_buf(outbuf),0,1);
1982 SSVAL(smb_buf(outbuf),1,nread);
1984 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
1985 fsp->fnum, (int)numtoread, (int)nread ) );
1987 END_PROFILE(SMBread);
1988 return(outsize);
1991 /****************************************************************************
1992 Reply to a read and X - possibly using sendfile.
1993 ****************************************************************************/
1995 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length,
1996 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
1998 ssize_t nread = -1;
1999 char *data = smb_buf(outbuf);
2001 #if defined(WITH_SENDFILE)
2003 * We can only use sendfile on a non-chained packet and on a file
2004 * that is exclusively oplocked.
2007 if ((CVAL(inbuf,smb_vwv0) == 0xFF) && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) &&
2008 lp_use_sendfile(SNUM(conn)) && (lp_write_cache_size(SNUM(conn)) == 0) ) {
2009 SMB_STRUCT_STAT sbuf;
2010 DATA_BLOB header;
2012 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1)
2013 return(UNIXERROR(ERRDOS,ERRnoaccess));
2015 if (startpos > sbuf.st_size)
2016 goto normal_read;
2018 if (smb_maxcnt > (sbuf.st_size - startpos))
2019 smb_maxcnt = (sbuf.st_size - startpos);
2021 if (smb_maxcnt == 0)
2022 goto normal_read;
2025 * Set up the packet header before send. We
2026 * assume here the sendfile will work (get the
2027 * correct amount of data).
2030 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2031 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
2032 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2033 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
2034 SCVAL(outbuf,smb_vwv0,0xFF);
2035 set_message(outbuf,12,smb_maxcnt,False);
2036 header.data = outbuf;
2037 header.length = data - outbuf;
2038 header.free = NULL;
2040 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt) == -1) {
2042 * Special hack for broken Linux with no 64 bit clean sendfile. If we
2043 * return ENOSYS then pretend we just got a normal read.
2045 if (errno == ENOSYS)
2046 goto normal_read;
2048 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2049 fsp->fsp_name, strerror(errno) ));
2050 exit_server("send_file_readX sendfile failed");
2053 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2054 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2055 return -1;
2058 normal_read:
2060 #endif
2062 nread = read_file(fsp,data,startpos,smb_maxcnt);
2064 if (nread < 0) {
2065 END_PROFILE(SMBreadX);
2066 return(UNIXERROR(ERRDOS,ERRnoaccess));
2069 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2070 SSVAL(outbuf,smb_vwv5,nread);
2071 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2072 SSVAL(smb_buf(outbuf),-2,nread);
2074 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2075 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2077 return nread;
2080 /****************************************************************************
2081 Reply to a read and X.
2082 ****************************************************************************/
2084 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2086 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2087 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2088 ssize_t nread = -1;
2089 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2090 #if 0
2091 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2092 #endif
2094 START_PROFILE(SMBreadX);
2096 /* If it's an IPC, pass off the pipe handler. */
2097 if (IS_IPC(conn)) {
2098 END_PROFILE(SMBreadX);
2099 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2102 CHECK_FSP(fsp,conn);
2103 CHECK_READ(fsp);
2105 set_message(outbuf,12,0,True);
2107 if(CVAL(inbuf,smb_wct) == 12) {
2108 #ifdef LARGE_SMB_OFF_T
2110 * This is a large offset (64 bit) read.
2112 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2114 #else /* !LARGE_SMB_OFF_T */
2117 * Ensure we haven't been sent a >32 bit offset.
2120 if(IVAL(inbuf,smb_vwv10) != 0) {
2121 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2122 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2123 END_PROFILE(SMBreadX);
2124 return ERROR_DOS(ERRDOS,ERRbadaccess);
2127 #endif /* LARGE_SMB_OFF_T */
2131 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
2132 END_PROFILE(SMBreadX);
2133 return ERROR_DOS(ERRDOS,ERRlock);
2136 nread = send_file_readX(conn, inbuf, outbuf, length, fsp, startpos, smb_maxcnt);
2137 if (nread != -1)
2138 nread = chain_reply(inbuf,outbuf,length,bufsize);
2140 END_PROFILE(SMBreadX);
2141 return nread;
2144 /****************************************************************************
2145 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2146 ****************************************************************************/
2148 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2150 ssize_t nwritten=0;
2151 ssize_t total_written=0;
2152 size_t numtowrite=0;
2153 size_t tcount;
2154 SMB_OFF_T startpos;
2155 char *data=NULL;
2156 BOOL write_through;
2157 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2158 int outsize = 0;
2159 START_PROFILE(SMBwritebraw);
2161 if (srv_is_signing_active()) {
2162 exit_server("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2165 CHECK_FSP(fsp,conn);
2166 CHECK_WRITE(fsp);
2168 tcount = IVAL(inbuf,smb_vwv1);
2169 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2170 write_through = BITSETW(inbuf+smb_vwv7,0);
2172 /* We have to deal with slightly different formats depending
2173 on whether we are using the core+ or lanman1.0 protocol */
2175 if(Protocol <= PROTOCOL_COREPLUS) {
2176 numtowrite = SVAL(smb_buf(inbuf),-2);
2177 data = smb_buf(inbuf);
2178 } else {
2179 numtowrite = SVAL(inbuf,smb_vwv10);
2180 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2183 /* force the error type */
2184 SCVAL(inbuf,smb_com,SMBwritec);
2185 SCVAL(outbuf,smb_com,SMBwritec);
2187 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2188 END_PROFILE(SMBwritebraw);
2189 return(ERROR_DOS(ERRDOS,ERRlock));
2192 if (numtowrite>0)
2193 nwritten = write_file(fsp,data,startpos,numtowrite);
2195 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2196 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2198 if (nwritten < (ssize_t)numtowrite) {
2199 END_PROFILE(SMBwritebraw);
2200 return(UNIXERROR(ERRHRD,ERRdiskfull));
2203 total_written = nwritten;
2205 /* Return a message to the redirector to tell it to send more bytes */
2206 SCVAL(outbuf,smb_com,SMBwritebraw);
2207 SSVALS(outbuf,smb_vwv0,-1);
2208 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2209 if (!send_smb(smbd_server_fd(),outbuf))
2210 exit_server("reply_writebraw: send_smb failed.");
2212 /* Now read the raw data into the buffer and write it */
2213 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2214 exit_server("secondary writebraw failed");
2217 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2218 numtowrite = smb_len(inbuf);
2220 /* Set up outbuf to return the correct return */
2221 outsize = set_message(outbuf,1,0,True);
2222 SCVAL(outbuf,smb_com,SMBwritec);
2223 SSVAL(outbuf,smb_vwv0,total_written);
2225 if (numtowrite != 0) {
2227 if (numtowrite > BUFFER_SIZE) {
2228 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2229 (unsigned int)numtowrite ));
2230 exit_server("secondary writebraw failed");
2233 if (tcount > nwritten+numtowrite) {
2234 DEBUG(3,("Client overestimated the write %d %d %d\n",
2235 (int)tcount,(int)nwritten,(int)numtowrite));
2238 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2239 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2240 strerror(errno) ));
2241 exit_server("secondary writebraw failed");
2244 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2246 if (nwritten < (ssize_t)numtowrite) {
2247 SCVAL(outbuf,smb_rcls,ERRHRD);
2248 SSVAL(outbuf,smb_err,ERRdiskfull);
2251 if (nwritten > 0)
2252 total_written += nwritten;
2255 if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn)))
2256 sync_file(conn,fsp);
2258 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2259 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2261 /* we won't return a status if write through is not selected - this follows what WfWg does */
2262 END_PROFILE(SMBwritebraw);
2263 if (!write_through && total_written==tcount) {
2265 #if RABBIT_PELLET_FIX
2267 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2268 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2270 if (!send_keepalive(smbd_server_fd()))
2271 exit_server("reply_writebraw: send of keepalive failed");
2272 #endif
2273 return(-1);
2276 return(outsize);
2279 /****************************************************************************
2280 Reply to a writeunlock (core+).
2281 ****************************************************************************/
2283 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
2284 int size, int dum_buffsize)
2286 ssize_t nwritten = -1;
2287 size_t numtowrite;
2288 SMB_OFF_T startpos;
2289 char *data;
2290 NTSTATUS status = NT_STATUS_OK;
2291 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2292 int outsize = 0;
2293 START_PROFILE(SMBwriteunlock);
2295 CHECK_FSP(fsp,conn);
2296 CHECK_WRITE(fsp);
2298 numtowrite = SVAL(inbuf,smb_vwv1);
2299 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2300 data = smb_buf(inbuf) + 3;
2302 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos,
2303 WRITE_LOCK,False)) {
2304 END_PROFILE(SMBwriteunlock);
2305 return ERROR_DOS(ERRDOS,ERRlock);
2308 /* The special X/Open SMB protocol handling of
2309 zero length writes is *NOT* done for
2310 this call */
2311 if(numtowrite == 0)
2312 nwritten = 0;
2313 else
2314 nwritten = write_file(fsp,data,startpos,numtowrite);
2316 if (lp_syncalways(SNUM(conn)))
2317 sync_file(conn,fsp);
2319 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2320 END_PROFILE(SMBwriteunlock);
2321 return(UNIXERROR(ERRHRD,ERRdiskfull));
2324 if (numtowrite) {
2325 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite,
2326 (SMB_BIG_UINT)startpos);
2327 if (NT_STATUS_V(status)) {
2328 END_PROFILE(SMBwriteunlock);
2329 return ERROR_NT(status);
2333 outsize = set_message(outbuf,1,0,True);
2335 SSVAL(outbuf,smb_vwv0,nwritten);
2337 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2338 fsp->fnum, (int)numtowrite, (int)nwritten));
2340 END_PROFILE(SMBwriteunlock);
2341 return outsize;
2344 /****************************************************************************
2345 Reply to a write.
2346 ****************************************************************************/
2348 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2350 size_t numtowrite;
2351 ssize_t nwritten = -1;
2352 SMB_OFF_T startpos;
2353 char *data;
2354 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2355 int outsize = 0;
2356 START_PROFILE(SMBwrite);
2358 /* If it's an IPC, pass off the pipe handler. */
2359 if (IS_IPC(conn)) {
2360 END_PROFILE(SMBwrite);
2361 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2364 CHECK_FSP(fsp,conn);
2365 CHECK_WRITE(fsp);
2367 numtowrite = SVAL(inbuf,smb_vwv1);
2368 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2369 data = smb_buf(inbuf) + 3;
2371 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2372 END_PROFILE(SMBwrite);
2373 return ERROR_DOS(ERRDOS,ERRlock);
2377 * X/Open SMB protocol says that if smb_vwv1 is
2378 * zero then the file size should be extended or
2379 * truncated to the size given in smb_vwv[2-3].
2382 if(numtowrite == 0) {
2384 * This is actually an allocate call, and set EOF. JRA.
2386 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2387 if (nwritten < 0) {
2388 END_PROFILE(SMBwrite);
2389 return ERROR_NT(NT_STATUS_DISK_FULL);
2391 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2392 if (nwritten < 0) {
2393 END_PROFILE(SMBwrite);
2394 return ERROR_NT(NT_STATUS_DISK_FULL);
2396 } else
2397 nwritten = write_file(fsp,data,startpos,numtowrite);
2399 if (lp_syncalways(SNUM(conn)))
2400 sync_file(conn,fsp);
2402 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2403 END_PROFILE(SMBwrite);
2404 return(UNIXERROR(ERRHRD,ERRdiskfull));
2407 outsize = set_message(outbuf,1,0,True);
2409 SSVAL(outbuf,smb_vwv0,nwritten);
2411 if (nwritten < (ssize_t)numtowrite) {
2412 SCVAL(outbuf,smb_rcls,ERRHRD);
2413 SSVAL(outbuf,smb_err,ERRdiskfull);
2416 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2418 END_PROFILE(SMBwrite);
2419 return(outsize);
2422 /****************************************************************************
2423 Reply to a write and X.
2424 ****************************************************************************/
2426 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2428 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2429 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2430 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2431 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2432 ssize_t nwritten = -1;
2433 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2434 unsigned int smblen = smb_len(inbuf);
2435 char *data;
2436 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2437 START_PROFILE(SMBwriteX);
2439 /* If it's an IPC, pass off the pipe handler. */
2440 if (IS_IPC(conn)) {
2441 END_PROFILE(SMBwriteX);
2442 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2445 CHECK_FSP(fsp,conn);
2446 CHECK_WRITE(fsp);
2448 /* Deal with possible LARGE_WRITEX */
2449 if (large_writeX)
2450 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2452 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2453 END_PROFILE(SMBwriteX);
2454 return ERROR_DOS(ERRDOS,ERRbadmem);
2457 data = smb_base(inbuf) + smb_doff;
2459 if(CVAL(inbuf,smb_wct) == 14) {
2460 #ifdef LARGE_SMB_OFF_T
2462 * This is a large offset (64 bit) write.
2464 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2466 #else /* !LARGE_SMB_OFF_T */
2469 * Ensure we haven't been sent a >32 bit offset.
2472 if(IVAL(inbuf,smb_vwv12) != 0) {
2473 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2474 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2475 END_PROFILE(SMBwriteX);
2476 return ERROR_DOS(ERRDOS,ERRbadaccess);
2479 #endif /* LARGE_SMB_OFF_T */
2482 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2483 END_PROFILE(SMBwriteX);
2484 return ERROR_DOS(ERRDOS,ERRlock);
2487 /* X/Open SMB protocol says that, unlike SMBwrite
2488 if the length is zero then NO truncation is
2489 done, just a write of zero. To truncate a file,
2490 use SMBwrite. */
2492 if(numtowrite == 0)
2493 nwritten = 0;
2494 else
2495 nwritten = write_file(fsp,data,startpos,numtowrite);
2497 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2498 END_PROFILE(SMBwriteX);
2499 return(UNIXERROR(ERRHRD,ERRdiskfull));
2502 set_message(outbuf,6,0,True);
2504 SSVAL(outbuf,smb_vwv2,nwritten);
2505 if (large_writeX)
2506 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2508 if (nwritten < (ssize_t)numtowrite) {
2509 SCVAL(outbuf,smb_rcls,ERRHRD);
2510 SSVAL(outbuf,smb_err,ERRdiskfull);
2513 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2514 fsp->fnum, (int)numtowrite, (int)nwritten));
2516 if (lp_syncalways(SNUM(conn)) || write_through)
2517 sync_file(conn,fsp);
2519 END_PROFILE(SMBwriteX);
2520 return chain_reply(inbuf,outbuf,length,bufsize);
2523 /****************************************************************************
2524 Reply to a lseek.
2525 ****************************************************************************/
2527 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2529 SMB_OFF_T startpos;
2530 SMB_OFF_T res= -1;
2531 int mode,umode;
2532 int outsize = 0;
2533 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2534 START_PROFILE(SMBlseek);
2536 CHECK_FSP(fsp,conn);
2538 flush_write_cache(fsp, SEEK_FLUSH);
2540 mode = SVAL(inbuf,smb_vwv1) & 3;
2541 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
2542 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
2544 switch (mode) {
2545 case 0:
2546 umode = SEEK_SET;
2547 res = startpos;
2548 break;
2549 case 1:
2550 umode = SEEK_CUR;
2551 res = fsp->pos + startpos;
2552 break;
2553 case 2:
2554 umode = SEEK_END;
2555 break;
2556 default:
2557 umode = SEEK_SET;
2558 res = startpos;
2559 break;
2562 if (umode == SEEK_END) {
2563 if((res = SMB_VFS_LSEEK(fsp,fsp->fd,startpos,umode)) == -1) {
2564 if(errno == EINVAL) {
2565 SMB_OFF_T current_pos = startpos;
2566 SMB_STRUCT_STAT sbuf;
2568 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) {
2569 END_PROFILE(SMBlseek);
2570 return(UNIXERROR(ERRDOS,ERRnoaccess));
2573 current_pos += sbuf.st_size;
2574 if(current_pos < 0)
2575 res = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_SET);
2579 if(res == -1) {
2580 END_PROFILE(SMBlseek);
2581 return(UNIXERROR(ERRDOS,ERRnoaccess));
2585 fsp->pos = res;
2587 outsize = set_message(outbuf,2,0,True);
2588 SIVAL(outbuf,smb_vwv0,res);
2590 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2591 fsp->fnum, (double)startpos, (double)res, mode));
2593 END_PROFILE(SMBlseek);
2594 return(outsize);
2597 /****************************************************************************
2598 Reply to a flush.
2599 ****************************************************************************/
2601 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2603 int outsize = set_message(outbuf,0,0,True);
2604 uint16 fnum = SVAL(inbuf,smb_vwv0);
2605 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2606 START_PROFILE(SMBflush);
2608 if (fnum != 0xFFFF)
2609 CHECK_FSP(fsp,conn);
2611 if (!fsp) {
2612 file_sync_all(conn);
2613 } else {
2614 sync_file(conn,fsp);
2617 DEBUG(3,("flush\n"));
2618 END_PROFILE(SMBflush);
2619 return(outsize);
2622 /****************************************************************************
2623 Reply to a exit.
2624 ****************************************************************************/
2626 int reply_exit(connection_struct *conn,
2627 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2629 int outsize;
2630 START_PROFILE(SMBexit);
2632 file_close_pid(SVAL(inbuf,smb_pid));
2634 outsize = set_message(outbuf,0,0,True);
2636 DEBUG(3,("exit\n"));
2638 END_PROFILE(SMBexit);
2639 return(outsize);
2642 /****************************************************************************
2643 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2644 ****************************************************************************/
2646 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2647 int dum_buffsize)
2649 extern struct current_user current_user;
2650 int outsize = 0;
2651 time_t mtime;
2652 int32 eclass = 0, err = 0;
2653 files_struct *fsp = NULL;
2654 START_PROFILE(SMBclose);
2656 outsize = set_message(outbuf,0,0,True);
2658 /* If it's an IPC, pass off to the pipe handler. */
2659 if (IS_IPC(conn)) {
2660 END_PROFILE(SMBclose);
2661 return reply_pipe_close(conn, inbuf,outbuf);
2664 fsp = file_fsp(inbuf,smb_vwv0);
2667 * We can only use CHECK_FSP if we know it's not a directory.
2670 if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
2671 END_PROFILE(SMBclose);
2672 return ERROR_DOS(ERRDOS,ERRbadfid);
2675 if(fsp->is_directory) {
2677 * Special case - close NT SMB directory handle.
2679 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2680 close_file(fsp,True);
2681 } else {
2683 * Close ordinary file.
2685 int close_err;
2686 pstring file_name;
2688 /* Save the name for time set in close. */
2689 pstrcpy( file_name, fsp->fsp_name);
2691 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2692 fsp->fd, fsp->fnum,
2693 conn->num_files_open));
2696 * close_file() returns the unix errno if an error
2697 * was detected on close - normally this is due to
2698 * a disk full error. If not then it was probably an I/O error.
2701 if((close_err = close_file(fsp,True)) != 0) {
2702 errno = close_err;
2703 END_PROFILE(SMBclose);
2704 return (UNIXERROR(ERRHRD,ERRgeneral));
2708 * Now take care of any time sent in the close.
2711 mtime = make_unix_date3(inbuf+smb_vwv1);
2713 /* try and set the date */
2714 set_filetime(conn, file_name, mtime);
2718 /* We have a cached error */
2719 if(eclass || err) {
2720 END_PROFILE(SMBclose);
2721 return ERROR_DOS(eclass,err);
2724 END_PROFILE(SMBclose);
2725 return(outsize);
2728 /****************************************************************************
2729 Reply to a writeclose (Core+ protocol).
2730 ****************************************************************************/
2732 int reply_writeclose(connection_struct *conn,
2733 char *inbuf,char *outbuf, int size, int dum_buffsize)
2735 size_t numtowrite;
2736 ssize_t nwritten = -1;
2737 int outsize = 0;
2738 int close_err = 0;
2739 SMB_OFF_T startpos;
2740 char *data;
2741 time_t mtime;
2742 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2743 START_PROFILE(SMBwriteclose);
2745 CHECK_FSP(fsp,conn);
2746 CHECK_WRITE(fsp);
2748 numtowrite = SVAL(inbuf,smb_vwv1);
2749 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2750 mtime = make_unix_date3(inbuf+smb_vwv4);
2751 data = smb_buf(inbuf) + 1;
2753 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2754 END_PROFILE(SMBwriteclose);
2755 return ERROR_DOS(ERRDOS,ERRlock);
2758 nwritten = write_file(fsp,data,startpos,numtowrite);
2760 set_filetime(conn, fsp->fsp_name,mtime);
2763 * More insanity. W2K only closes the file if writelen > 0.
2764 * JRA.
2767 if (numtowrite) {
2768 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
2769 fsp->fsp_name ));
2770 close_err = close_file(fsp,True);
2773 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2774 fsp->fnum, (int)numtowrite, (int)nwritten,
2775 conn->num_files_open));
2777 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2778 END_PROFILE(SMBwriteclose);
2779 return(UNIXERROR(ERRHRD,ERRdiskfull));
2782 if(close_err != 0) {
2783 errno = close_err;
2784 END_PROFILE(SMBwriteclose);
2785 return(UNIXERROR(ERRHRD,ERRgeneral));
2788 outsize = set_message(outbuf,1,0,True);
2790 SSVAL(outbuf,smb_vwv0,nwritten);
2791 END_PROFILE(SMBwriteclose);
2792 return(outsize);
2795 /****************************************************************************
2796 Reply to a lock.
2797 ****************************************************************************/
2799 int reply_lock(connection_struct *conn,
2800 char *inbuf,char *outbuf, int length, int dum_buffsize)
2802 int outsize = set_message(outbuf,0,0,True);
2803 SMB_BIG_UINT count,offset;
2804 NTSTATUS status;
2805 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2806 BOOL my_lock_ctx = False;
2808 START_PROFILE(SMBlock);
2810 CHECK_FSP(fsp,conn);
2812 release_level_2_oplocks_on_change(fsp);
2814 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2815 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2817 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2818 fsp->fd, fsp->fnum, (double)offset, (double)count));
2820 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &my_lock_ctx);
2821 if (NT_STATUS_V(status)) {
2822 #if 0
2823 /* Tests using Samba4 against W2K show this call never creates a blocking lock. */
2824 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
2826 * A blocking lock was requested. Package up
2827 * this smb into a queued request and push it
2828 * onto the blocking lock queue.
2830 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), offset, count)) {
2831 END_PROFILE(SMBlock);
2832 return -1;
2835 #endif
2836 END_PROFILE(SMBlock);
2837 return ERROR_NT(status);
2840 END_PROFILE(SMBlock);
2841 return(outsize);
2844 /****************************************************************************
2845 Reply to a unlock.
2846 ****************************************************************************/
2848 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
2849 int dum_buffsize)
2851 int outsize = set_message(outbuf,0,0,True);
2852 SMB_BIG_UINT count,offset;
2853 NTSTATUS status;
2854 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2855 START_PROFILE(SMBunlock);
2857 CHECK_FSP(fsp,conn);
2859 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2860 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2862 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
2863 if (NT_STATUS_V(status)) {
2864 END_PROFILE(SMBunlock);
2865 return ERROR_NT(status);
2868 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2869 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
2871 END_PROFILE(SMBunlock);
2872 return(outsize);
2875 /****************************************************************************
2876 Reply to a tdis.
2877 ****************************************************************************/
2879 int reply_tdis(connection_struct *conn,
2880 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2882 int outsize = set_message(outbuf,0,0,True);
2883 uint16 vuid;
2884 START_PROFILE(SMBtdis);
2886 vuid = SVAL(inbuf,smb_uid);
2888 if (!conn) {
2889 DEBUG(4,("Invalid connection in tdis\n"));
2890 END_PROFILE(SMBtdis);
2891 return ERROR_DOS(ERRSRV,ERRinvnid);
2894 conn->used = False;
2896 close_cnum(conn,vuid);
2898 END_PROFILE(SMBtdis);
2899 return outsize;
2902 /****************************************************************************
2903 Reply to a echo.
2904 ****************************************************************************/
2906 int reply_echo(connection_struct *conn,
2907 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2909 int smb_reverb = SVAL(inbuf,smb_vwv0);
2910 int seq_num;
2911 unsigned int data_len = smb_buflen(inbuf);
2912 int outsize = set_message(outbuf,1,data_len,True);
2913 START_PROFILE(SMBecho);
2915 if (data_len > BUFFER_SIZE) {
2916 DEBUG(0,("reply_echo: data_len too large.\n"));
2917 END_PROFILE(SMBecho);
2918 return -1;
2921 /* copy any incoming data back out */
2922 if (data_len > 0)
2923 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2925 if (smb_reverb > 100) {
2926 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2927 smb_reverb = 100;
2930 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
2931 SSVAL(outbuf,smb_vwv0,seq_num);
2933 smb_setlen(outbuf,outsize - 4);
2935 if (!send_smb(smbd_server_fd(),outbuf))
2936 exit_server("reply_echo: send_smb failed.");
2939 DEBUG(3,("echo %d times\n", smb_reverb));
2941 smb_echo_count++;
2943 END_PROFILE(SMBecho);
2944 return -1;
2947 /****************************************************************************
2948 Reply to a printopen.
2949 ****************************************************************************/
2951 int reply_printopen(connection_struct *conn,
2952 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2954 int outsize = 0;
2955 files_struct *fsp;
2956 START_PROFILE(SMBsplopen);
2958 if (!CAN_PRINT(conn)) {
2959 END_PROFILE(SMBsplopen);
2960 return ERROR_DOS(ERRDOS,ERRnoaccess);
2963 /* Open for exclusive use, write only. */
2964 fsp = print_fsp_open(conn, NULL);
2966 if (!fsp) {
2967 END_PROFILE(SMBsplopen);
2968 return(UNIXERROR(ERRDOS,ERRnoaccess));
2971 outsize = set_message(outbuf,1,0,True);
2972 SSVAL(outbuf,smb_vwv0,fsp->fnum);
2974 DEBUG(3,("openprint fd=%d fnum=%d\n",
2975 fsp->fd, fsp->fnum));
2977 END_PROFILE(SMBsplopen);
2978 return(outsize);
2981 /****************************************************************************
2982 Reply to a printclose.
2983 ****************************************************************************/
2985 int reply_printclose(connection_struct *conn,
2986 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2988 int outsize = set_message(outbuf,0,0,True);
2989 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2990 int close_err = 0;
2991 START_PROFILE(SMBsplclose);
2993 CHECK_FSP(fsp,conn);
2995 if (!CAN_PRINT(conn)) {
2996 END_PROFILE(SMBsplclose);
2997 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
3000 DEBUG(3,("printclose fd=%d fnum=%d\n",
3001 fsp->fd,fsp->fnum));
3003 close_err = close_file(fsp,True);
3005 if(close_err != 0) {
3006 errno = close_err;
3007 END_PROFILE(SMBsplclose);
3008 return(UNIXERROR(ERRHRD,ERRgeneral));
3011 END_PROFILE(SMBsplclose);
3012 return(outsize);
3015 /****************************************************************************
3016 Reply to a printqueue.
3017 ****************************************************************************/
3019 int reply_printqueue(connection_struct *conn,
3020 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3022 int outsize = set_message(outbuf,2,3,True);
3023 int max_count = SVAL(inbuf,smb_vwv0);
3024 int start_index = SVAL(inbuf,smb_vwv1);
3025 START_PROFILE(SMBsplretq);
3027 /* we used to allow the client to get the cnum wrong, but that
3028 is really quite gross and only worked when there was only
3029 one printer - I think we should now only accept it if they
3030 get it right (tridge) */
3031 if (!CAN_PRINT(conn)) {
3032 END_PROFILE(SMBsplretq);
3033 return ERROR_DOS(ERRDOS,ERRnoaccess);
3036 SSVAL(outbuf,smb_vwv0,0);
3037 SSVAL(outbuf,smb_vwv1,0);
3038 SCVAL(smb_buf(outbuf),0,1);
3039 SSVAL(smb_buf(outbuf),1,0);
3041 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3042 start_index, max_count));
3045 print_queue_struct *queue = NULL;
3046 print_status_struct status;
3047 char *p = smb_buf(outbuf) + 3;
3048 int count = print_queue_status(SNUM(conn), &queue, &status);
3049 int num_to_get = ABS(max_count);
3050 int first = (max_count>0?start_index:start_index+max_count+1);
3051 int i;
3053 if (first >= count)
3054 num_to_get = 0;
3055 else
3056 num_to_get = MIN(num_to_get,count-first);
3059 for (i=first;i<first+num_to_get;i++) {
3060 put_dos_date2(p,0,queue[i].time);
3061 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
3062 SSVAL(p,5, queue[i].job);
3063 SIVAL(p,7,queue[i].size);
3064 SCVAL(p,11,0);
3065 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
3066 p += 28;
3069 if (count > 0) {
3070 outsize = set_message(outbuf,2,28*count+3,False);
3071 SSVAL(outbuf,smb_vwv0,count);
3072 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3073 SCVAL(smb_buf(outbuf),0,1);
3074 SSVAL(smb_buf(outbuf),1,28*count);
3077 SAFE_FREE(queue);
3079 DEBUG(3,("%d entries returned in queue\n",count));
3082 END_PROFILE(SMBsplretq);
3083 return(outsize);
3086 /****************************************************************************
3087 Reply to a printwrite.
3088 ****************************************************************************/
3090 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3092 int numtowrite;
3093 int outsize = set_message(outbuf,0,0,True);
3094 char *data;
3095 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3097 START_PROFILE(SMBsplwr);
3099 if (!CAN_PRINT(conn)) {
3100 END_PROFILE(SMBsplwr);
3101 return ERROR_DOS(ERRDOS,ERRnoaccess);
3104 CHECK_FSP(fsp,conn);
3105 CHECK_WRITE(fsp);
3107 numtowrite = SVAL(smb_buf(inbuf),1);
3108 data = smb_buf(inbuf) + 3;
3110 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3111 END_PROFILE(SMBsplwr);
3112 return(UNIXERROR(ERRHRD,ERRdiskfull));
3115 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3117 END_PROFILE(SMBsplwr);
3118 return(outsize);
3121 /****************************************************************************
3122 The guts of the mkdir command, split out so it may be called by the NT SMB
3123 code.
3124 ****************************************************************************/
3126 NTSTATUS mkdir_internal(connection_struct *conn, pstring directory)
3128 BOOL bad_path = False;
3129 SMB_STRUCT_STAT sbuf;
3130 int ret= -1;
3132 unix_convert(directory,conn,0,&bad_path,&sbuf);
3134 if( strchr_m(directory, ':')) {
3135 return NT_STATUS_NOT_A_DIRECTORY;
3138 if (ms_has_wild(directory)) {
3139 return NT_STATUS_OBJECT_NAME_INVALID;
3142 if (check_name(directory, conn))
3143 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory));
3145 if (ret == -1) {
3146 if(errno == ENOENT) {
3147 if (bad_path)
3148 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3149 else
3150 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3152 return map_nt_error_from_unix(errno);
3155 return NT_STATUS_OK;
3158 /****************************************************************************
3159 Reply to a mkdir.
3160 ****************************************************************************/
3162 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3164 pstring directory;
3165 int outsize;
3166 NTSTATUS status;
3167 START_PROFILE(SMBmkdir);
3169 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
3170 if (!NT_STATUS_IS_OK(status)) {
3171 END_PROFILE(SMBmkdir);
3172 return ERROR_NT(status);
3175 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
3177 status = mkdir_internal(conn, directory);
3178 if (!NT_STATUS_IS_OK(status)) {
3179 END_PROFILE(SMBmkdir);
3180 return ERROR_NT(status);
3183 outsize = set_message(outbuf,0,0,True);
3185 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3187 END_PROFILE(SMBmkdir);
3188 return(outsize);
3191 /****************************************************************************
3192 Static function used by reply_rmdir to delete an entire directory
3193 tree recursively. Return False on ok, True on fail.
3194 ****************************************************************************/
3196 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3198 const char *dname = NULL;
3199 BOOL ret = False;
3200 void *dirptr = OpenDir(conn, directory, False);
3202 if(dirptr == NULL)
3203 return True;
3205 while((dname = ReadDirName(dirptr))) {
3206 pstring fullname;
3207 SMB_STRUCT_STAT st;
3209 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3210 continue;
3212 /* Construct the full name. */
3213 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3214 errno = ENOMEM;
3215 ret = True;
3216 break;
3219 pstrcpy(fullname, directory);
3220 pstrcat(fullname, "/");
3221 pstrcat(fullname, dname);
3223 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
3224 ret = True;
3225 break;
3228 if(st.st_mode & S_IFDIR) {
3229 if(recursive_rmdir(conn, fullname)!=0) {
3230 ret = True;
3231 break;
3233 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
3234 ret = True;
3235 break;
3237 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
3238 ret = True;
3239 break;
3242 CloseDir(dirptr);
3243 return ret;
3246 /****************************************************************************
3247 The internals of the rmdir code - called elsewhere.
3248 ****************************************************************************/
3250 BOOL rmdir_internals(connection_struct *conn, char *directory)
3252 BOOL ok;
3254 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3255 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3257 * Check to see if the only thing in this directory are
3258 * vetoed files/directories. If so then delete them and
3259 * retry. If we fail to delete any of them (and we *don't*
3260 * do a recursive delete) then fail the rmdir.
3262 BOOL all_veto_files = True;
3263 const char *dname;
3264 void *dirptr = OpenDir(conn, directory, False);
3266 if(dirptr != NULL) {
3267 int dirpos = TellDir(dirptr);
3268 while ((dname = ReadDirName(dirptr))) {
3269 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3270 continue;
3271 if(!IS_VETO_PATH(conn, dname)) {
3272 all_veto_files = False;
3273 break;
3277 if(all_veto_files) {
3278 SeekDir(dirptr,dirpos);
3279 while ((dname = ReadDirName(dirptr))) {
3280 pstring fullname;
3281 SMB_STRUCT_STAT st;
3283 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3284 continue;
3286 /* Construct the full name. */
3287 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3288 errno = ENOMEM;
3289 break;
3292 pstrcpy(fullname, directory);
3293 pstrcat(fullname, "/");
3294 pstrcat(fullname, dname);
3296 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
3297 break;
3298 if(st.st_mode & S_IFDIR) {
3299 if(lp_recursive_veto_delete(SNUM(conn))) {
3300 if(recursive_rmdir(conn, fullname) != 0)
3301 break;
3303 if(SMB_VFS_RMDIR(conn,fullname) != 0)
3304 break;
3305 } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
3306 break;
3308 CloseDir(dirptr);
3309 /* Retry the rmdir */
3310 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3311 } else {
3312 CloseDir(dirptr);
3314 } else {
3315 errno = ENOTEMPTY;
3319 if (!ok)
3320 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
3322 return ok;
3325 /****************************************************************************
3326 Reply to a rmdir.
3327 ****************************************************************************/
3329 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3331 pstring directory;
3332 int outsize = 0;
3333 BOOL ok = False;
3334 BOOL bad_path = False;
3335 SMB_STRUCT_STAT sbuf;
3336 NTSTATUS status;
3337 START_PROFILE(SMBrmdir);
3339 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
3340 if (!NT_STATUS_IS_OK(status)) {
3341 END_PROFILE(SMBrmdir);
3342 return ERROR_NT(status);
3345 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3347 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3349 if (check_name(directory,conn)) {
3350 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3351 ok = rmdir_internals(conn, directory);
3354 if (!ok) {
3355 END_PROFILE(SMBrmdir);
3356 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRbadpath);
3359 outsize = set_message(outbuf,0,0,True);
3361 DEBUG( 3, ( "rmdir %s\n", directory ) );
3363 END_PROFILE(SMBrmdir);
3364 return(outsize);
3367 /*******************************************************************
3368 Resolve wildcards in a filename rename.
3369 Note that name is in UNIX charset and thus potentially can be more
3370 than fstring buffer (255 bytes) especially in default UTF-8 case.
3371 Therefore, we use pstring inside and all calls should ensure that
3372 name2 is at least pstring-long (they do already)
3373 ********************************************************************/
3375 static BOOL resolve_wildcards(const char *name1, char *name2)
3377 pstring root1,root2;
3378 pstring ext1,ext2;
3379 char *p,*p2, *pname1, *pname2;
3380 int available_space, actual_space;
3383 pname1 = strrchr_m(name1,'/');
3384 pname2 = strrchr_m(name2,'/');
3386 if (!pname1 || !pname2)
3387 return(False);
3389 pstrcpy(root1,pname1);
3390 pstrcpy(root2,pname2);
3391 p = strrchr_m(root1,'.');
3392 if (p) {
3393 *p = 0;
3394 pstrcpy(ext1,p+1);
3395 } else {
3396 pstrcpy(ext1,"");
3398 p = strrchr_m(root2,'.');
3399 if (p) {
3400 *p = 0;
3401 pstrcpy(ext2,p+1);
3402 } else {
3403 pstrcpy(ext2,"");
3406 p = root1;
3407 p2 = root2;
3408 while (*p2) {
3409 if (*p2 == '?') {
3410 *p2 = *p;
3411 p2++;
3412 } else if (*p2 == '*') {
3413 pstrcpy(p2, p);
3414 break;
3415 } else {
3416 p2++;
3418 if (*p)
3419 p++;
3422 p = ext1;
3423 p2 = ext2;
3424 while (*p2) {
3425 if (*p2 == '?') {
3426 *p2 = *p;
3427 p2++;
3428 } else if (*p2 == '*') {
3429 pstrcpy(p2, p);
3430 break;
3431 } else {
3432 p2++;
3434 if (*p)
3435 p++;
3438 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
3440 if (ext2[0]) {
3441 actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
3442 if (actual_space >= available_space - 1) {
3443 DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
3444 actual_space - available_space));
3446 } else {
3447 pstrcpy_base(pname2, root2, name2);
3450 return(True);
3453 /****************************************************************************
3454 Ensure open files have their names updates.
3455 ****************************************************************************/
3457 static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode, char *newname)
3459 files_struct *fsp;
3460 BOOL did_rename = False;
3462 for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
3463 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
3464 fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
3465 fsp->fsp_name, newname ));
3466 string_set(&fsp->fsp_name, newname);
3467 did_rename = True;
3470 if (!did_rename)
3471 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
3472 (unsigned int)dev, (double)inode, newname ));
3475 /****************************************************************************
3476 Rename an open file - given an fsp.
3477 ****************************************************************************/
3479 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, BOOL replace_if_exists)
3481 SMB_STRUCT_STAT sbuf;
3482 BOOL bad_path = False;
3483 pstring newname_last_component;
3484 NTSTATUS error = NT_STATUS_OK;
3485 BOOL dest_exists;
3486 BOOL rcdest = True;
3488 ZERO_STRUCT(sbuf);
3489 rcdest = unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf);
3491 /* Quick check for "." and ".." */
3492 if (!bad_path && newname_last_component[0] == '.') {
3493 if (!newname_last_component[1] || (newname_last_component[1] == '.' && !newname_last_component[2])) {
3494 return NT_STATUS_ACCESS_DENIED;
3497 if (!rcdest && bad_path) {
3498 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3501 /* Ensure newname contains a '/' */
3502 if(strrchr_m(newname,'/') == 0) {
3503 pstring tmpstr;
3505 pstrcpy(tmpstr, "./");
3506 pstrcat(tmpstr, newname);
3507 pstrcpy(newname, tmpstr);
3511 * Check for special case with case preserving and not
3512 * case sensitive. If the old last component differs from the original
3513 * last component only by case, then we should allow
3514 * the rename (user is trying to change the case of the
3515 * filename).
3518 if((case_sensitive == False) && (case_preserve == True) &&
3519 strequal(newname, fsp->fsp_name)) {
3520 char *p;
3521 pstring newname_modified_last_component;
3524 * Get the last component of the modified name.
3525 * Note that we guarantee that newname contains a '/'
3526 * character above.
3528 p = strrchr_m(newname,'/');
3529 pstrcpy(newname_modified_last_component,p+1);
3531 if(strcsequal(newname_modified_last_component,
3532 newname_last_component) == False) {
3534 * Replace the modified last component with
3535 * the original.
3537 pstrcpy(p+1, newname_last_component);
3542 * If the src and dest names are identical - including case,
3543 * don't do the rename, just return success.
3546 if (strcsequal(fsp->fsp_name, newname)) {
3547 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
3548 newname));
3549 return NT_STATUS_OK;
3552 dest_exists = vfs_object_exist(conn,newname,NULL);
3554 if(!replace_if_exists && dest_exists) {
3555 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
3556 fsp->fsp_name,newname));
3557 return NT_STATUS_OBJECT_NAME_COLLISION;
3560 error = can_rename(newname,conn,&sbuf);
3562 if (dest_exists && !NT_STATUS_IS_OK(error)) {
3563 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3564 nt_errstr(error), fsp->fsp_name,newname));
3565 if (NT_STATUS_EQUAL(error,NT_STATUS_SHARING_VIOLATION))
3566 error = NT_STATUS_ACCESS_DENIED;
3567 return error;
3570 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
3571 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
3572 fsp->fsp_name,newname));
3573 rename_open_files(conn, fsp->dev, fsp->inode, newname);
3574 return NT_STATUS_OK;
3577 if (errno == ENOTDIR || errno == EISDIR)
3578 error = NT_STATUS_OBJECT_NAME_COLLISION;
3579 else
3580 error = map_nt_error_from_unix(errno);
3582 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
3583 nt_errstr(error), fsp->fsp_name,newname));
3585 return error;
3588 /****************************************************************************
3589 The guts of the rename command, split out so it may be called by the NT SMB
3590 code.
3591 ****************************************************************************/
3593 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, uint16 attrs, BOOL replace_if_exists)
3595 pstring directory;
3596 pstring mask;
3597 pstring last_component_src;
3598 pstring last_component_dest;
3599 char *p;
3600 BOOL has_wild;
3601 BOOL bad_path_src = False;
3602 BOOL bad_path_dest = False;
3603 int count=0;
3604 NTSTATUS error = NT_STATUS_OK;
3605 BOOL rc = True;
3606 BOOL rcdest = True;
3607 SMB_STRUCT_STAT sbuf1, sbuf2;
3609 *directory = *mask = 0;
3611 ZERO_STRUCT(sbuf1);
3612 ZERO_STRUCT(sbuf2);
3614 rc = unix_convert(name,conn,last_component_src,&bad_path_src,&sbuf1);
3615 if (!rc && bad_path_src) {
3616 if (ms_has_wild(last_component_src))
3617 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3618 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3621 /* Quick check for "." and ".." */
3622 if (last_component_src[0] == '.') {
3623 if (!last_component_src[1] || (last_component_src[1] == '.' && !last_component_src[2])) {
3624 return NT_STATUS_OBJECT_NAME_INVALID;
3628 rcdest = unix_convert(newname,conn,last_component_dest,&bad_path_dest,&sbuf2);
3630 /* Quick check for "." and ".." */
3631 if (last_component_dest[0] == '.') {
3632 if (!last_component_dest[1] || (last_component_dest[1] == '.' && !last_component_dest[2])) {
3633 return NT_STATUS_OBJECT_NAME_INVALID;
3638 * Split the old name into directory and last component
3639 * strings. Note that unix_convert may have stripped off a
3640 * leading ./ from both name and newname if the rename is
3641 * at the root of the share. We need to make sure either both
3642 * name and newname contain a / character or neither of them do
3643 * as this is checked in resolve_wildcards().
3646 p = strrchr_m(name,'/');
3647 if (!p) {
3648 pstrcpy(directory,".");
3649 pstrcpy(mask,name);
3650 } else {
3651 *p = 0;
3652 pstrcpy(directory,name);
3653 pstrcpy(mask,p+1);
3654 *p = '/'; /* Replace needed for exceptional test below. */
3658 * We should only check the mangled cache
3659 * here if unix_convert failed. This means
3660 * that the path in 'mask' doesn't exist
3661 * on the file system and so we need to look
3662 * for a possible mangle. This patch from
3663 * Tine Smukavec <valentin.smukavec@hermes.si>.
3666 if (!rc && mangle_is_mangled(mask))
3667 mangle_check_cache( mask );
3669 has_wild = ms_has_wild(mask);
3671 if (!has_wild) {
3673 * No wildcards - just process the one file.
3675 BOOL is_short_name = mangle_is_8_3(name, True);
3677 /* Add a terminating '/' to the directory name. */
3678 pstrcat(directory,"/");
3679 pstrcat(directory,mask);
3681 /* Ensure newname contains a '/' also */
3682 if(strrchr_m(newname,'/') == 0) {
3683 pstring tmpstr;
3685 pstrcpy(tmpstr, "./");
3686 pstrcat(tmpstr, newname);
3687 pstrcpy(newname, tmpstr);
3690 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
3691 directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
3692 case_sensitive, case_preserve, short_case_preserve, directory,
3693 newname, last_component_dest, is_short_name));
3696 * Check for special case with case preserving and not
3697 * case sensitive, if directory and newname are identical,
3698 * and the old last component differs from the original
3699 * last component only by case, then we should allow
3700 * the rename (user is trying to change the case of the
3701 * filename).
3703 if((case_sensitive == False) &&
3704 (((case_preserve == True) &&
3705 (is_short_name == False)) ||
3706 ((short_case_preserve == True) &&
3707 (is_short_name == True))) &&
3708 strcsequal(directory, newname)) {
3709 pstring modified_last_component;
3712 * Get the last component of the modified name.
3713 * Note that we guarantee that newname contains a '/'
3714 * character above.
3716 p = strrchr_m(newname,'/');
3717 pstrcpy(modified_last_component,p+1);
3719 if(strcsequal(modified_last_component,
3720 last_component_dest) == False) {
3722 * Replace the modified last component with
3723 * the original.
3725 pstrcpy(p+1, last_component_dest);
3729 resolve_wildcards(directory,newname);
3732 * The source object must exist.
3735 if (!vfs_object_exist(conn, directory, &sbuf1)) {
3736 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
3737 directory,newname));
3739 if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
3741 * Must return different errors depending on whether the parent
3742 * directory existed or not.
3745 p = strrchr_m(directory, '/');
3746 if (!p)
3747 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3748 *p = '\0';
3749 if (vfs_object_exist(conn, directory, NULL))
3750 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3751 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3753 error = map_nt_error_from_unix(errno);
3754 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3755 nt_errstr(error), directory,newname));
3757 return error;
3760 if (!rcdest && bad_path_dest) {
3761 if (ms_has_wild(last_component_dest))
3762 return NT_STATUS_OBJECT_NAME_INVALID;
3763 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3766 error = can_rename(directory,conn,&sbuf1);
3768 if (!NT_STATUS_IS_OK(error)) {
3769 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3770 nt_errstr(error), directory,newname));
3771 return error;
3775 * If the src and dest names are identical - including case,
3776 * don't do the rename, just return success.
3779 if (strcsequal(directory, newname)) {
3780 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3781 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
3782 return NT_STATUS_OK;
3785 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
3786 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
3787 directory,newname));
3788 return NT_STATUS_OBJECT_NAME_COLLISION;
3791 if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
3792 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
3793 directory,newname));
3794 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3795 return NT_STATUS_OK;
3798 if (errno == ENOTDIR || errno == EISDIR)
3799 error = NT_STATUS_OBJECT_NAME_COLLISION;
3800 else
3801 error = map_nt_error_from_unix(errno);
3803 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3804 nt_errstr(error), directory,newname));
3806 return error;
3807 } else {
3809 * Wildcards - process each file that matches.
3811 void *dirptr = NULL;
3812 const char *dname;
3813 pstring destname;
3815 if (check_name(directory,conn))
3816 dirptr = OpenDir(conn, directory, True);
3818 if (dirptr) {
3819 error = NT_STATUS_NO_SUCH_FILE;
3820 /* Was error = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */
3822 if (strequal(mask,"????????.???"))
3823 pstrcpy(mask,"*");
3825 while ((dname = ReadDirName(dirptr))) {
3826 pstring fname;
3827 BOOL sysdir_entry = False;
3829 pstrcpy(fname,dname);
3831 /* Quick check for "." and ".." */
3832 if (fname[0] == '.') {
3833 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
3834 if (attrs & aDIR) {
3835 sysdir_entry = True;
3836 } else {
3837 continue;
3842 if(!mask_match(fname, mask, case_sensitive))
3843 continue;
3845 if (sysdir_entry) {
3846 error = NT_STATUS_OBJECT_NAME_INVALID;
3847 break;
3850 error = NT_STATUS_ACCESS_DENIED;
3851 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3852 if (!vfs_object_exist(conn, fname, &sbuf1)) {
3853 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3854 DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
3855 continue;
3857 error = can_rename(fname,conn,&sbuf1);
3858 if (!NT_STATUS_IS_OK(error)) {
3859 DEBUG(6,("rename %s refused\n", fname));
3860 continue;
3862 pstrcpy(destname,newname);
3864 if (!resolve_wildcards(fname,destname)) {
3865 DEBUG(6,("resolve_wildcards %s %s failed\n",
3866 fname, destname));
3867 continue;
3870 if (strcsequal(fname,destname)) {
3871 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3872 DEBUG(3,("rename_internals: identical names in wildcard rename %s - success\n", fname));
3873 count++;
3874 error = NT_STATUS_OK;
3875 continue;
3878 if (!replace_if_exists &&
3879 vfs_file_exist(conn,destname, NULL)) {
3880 DEBUG(6,("file_exist %s\n", destname));
3881 error = NT_STATUS_OBJECT_NAME_COLLISION;
3882 continue;
3885 if (!SMB_VFS_RENAME(conn,fname,destname)) {
3886 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3887 count++;
3888 error = NT_STATUS_OK;
3890 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3892 CloseDir(dirptr);
3895 if (!NT_STATUS_EQUAL(error,NT_STATUS_NO_SUCH_FILE)) {
3896 if (!rcdest && bad_path_dest) {
3897 if (ms_has_wild(last_component_dest))
3898 return NT_STATUS_OBJECT_NAME_INVALID;
3899 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3904 if (count == 0 && NT_STATUS_IS_OK(error)) {
3905 error = map_nt_error_from_unix(errno);
3908 return error;
3911 /****************************************************************************
3912 Reply to a mv.
3913 ****************************************************************************/
3915 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
3916 int dum_buffsize)
3918 int outsize = 0;
3919 pstring name;
3920 pstring newname;
3921 char *p;
3922 uint16 attrs = SVAL(inbuf,smb_vwv0);
3923 NTSTATUS status;
3925 START_PROFILE(SMBmv);
3927 p = smb_buf(inbuf) + 1;
3928 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status);
3929 if (!NT_STATUS_IS_OK(status)) {
3930 END_PROFILE(SMBmv);
3931 return ERROR_NT(status);
3933 p++;
3934 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status);
3935 if (!NT_STATUS_IS_OK(status)) {
3936 END_PROFILE(SMBmv);
3937 return ERROR_NT(status);
3940 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3941 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3943 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3945 status = rename_internals(conn, name, newname, attrs, False);
3946 if (!NT_STATUS_IS_OK(status)) {
3947 END_PROFILE(SMBmv);
3948 return ERROR_NT(status);
3952 * Win2k needs a changenotify request response before it will
3953 * update after a rename..
3955 process_pending_change_notify_queue((time_t)0);
3956 outsize = set_message(outbuf,0,0,True);
3958 END_PROFILE(SMBmv);
3959 return(outsize);
3962 /*******************************************************************
3963 Copy a file as part of a reply_copy.
3964 ******************************************************************/
3966 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3967 int count,BOOL target_is_directory, int *err_ret)
3969 int Access,action;
3970 SMB_STRUCT_STAT src_sbuf, sbuf2;
3971 SMB_OFF_T ret=-1;
3972 files_struct *fsp1,*fsp2;
3973 pstring dest;
3974 uint32 dosattrs;
3976 *err_ret = 0;
3978 pstrcpy(dest,dest1);
3979 if (target_is_directory) {
3980 char *p = strrchr_m(src,'/');
3981 if (p)
3982 p++;
3983 else
3984 p = src;
3985 pstrcat(dest,"/");
3986 pstrcat(dest,p);
3989 if (!vfs_file_exist(conn,src,&src_sbuf))
3990 return(False);
3992 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
3993 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),FILE_ATTRIBUTE_NORMAL,0,&Access,&action);
3995 if (!fsp1)
3996 return(False);
3998 if (!target_is_directory && count)
3999 ofun = FILE_EXISTS_OPEN;
4001 dosattrs = dos_mode(conn, src, &src_sbuf);
4002 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1)
4003 ZERO_STRUCTP(&sbuf2);
4005 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
4006 ofun,dosattrs,0,&Access,&action);
4008 if (!fsp2) {
4009 close_file(fsp1,False);
4010 return(False);
4013 if ((ofun&3) == 1) {
4014 if(SMB_VFS_LSEEK(fsp2,fsp2->fd,0,SEEK_END) == -1) {
4015 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
4017 * Stop the copy from occurring.
4019 ret = -1;
4020 src_sbuf.st_size = 0;
4024 if (src_sbuf.st_size)
4025 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
4027 close_file(fsp1,False);
4029 /* Ensure the modtime is set correctly on the destination file. */
4030 fsp2->pending_modtime = src_sbuf.st_mtime;
4033 * As we are opening fsp1 read-only we only expect
4034 * an error on close on fsp2 if we are out of space.
4035 * Thus we don't look at the error return from the
4036 * close of fsp1.
4038 *err_ret = close_file(fsp2,False);
4040 return(ret == (SMB_OFF_T)src_sbuf.st_size);
4043 /****************************************************************************
4044 Reply to a file copy.
4045 ****************************************************************************/
4047 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4049 int outsize = 0;
4050 pstring name;
4051 pstring directory;
4052 pstring mask,newname;
4053 char *p;
4054 int count=0;
4055 int error = ERRnoaccess;
4056 int err = 0;
4057 BOOL has_wild;
4058 BOOL exists=False;
4059 int tid2 = SVAL(inbuf,smb_vwv0);
4060 int ofun = SVAL(inbuf,smb_vwv1);
4061 int flags = SVAL(inbuf,smb_vwv2);
4062 BOOL target_is_directory=False;
4063 BOOL bad_path1 = False;
4064 BOOL bad_path2 = False;
4065 BOOL rc = True;
4066 SMB_STRUCT_STAT sbuf1, sbuf2;
4067 NTSTATUS status;
4069 START_PROFILE(SMBcopy);
4071 *directory = *mask = 0;
4073 p = smb_buf(inbuf);
4074 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status);
4075 if (!NT_STATUS_IS_OK(status)) {
4076 END_PROFILE(SMBcopy);
4077 return ERROR_NT(status);
4079 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status);
4080 if (!NT_STATUS_IS_OK(status)) {
4081 END_PROFILE(SMBcopy);
4082 return ERROR_NT(status);
4085 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
4087 if (tid2 != conn->cnum) {
4088 /* can't currently handle inter share copies XXXX */
4089 DEBUG(3,("Rejecting inter-share copy\n"));
4090 END_PROFILE(SMBcopy);
4091 return ERROR_DOS(ERRSRV,ERRinvdevice);
4094 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
4095 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4097 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
4098 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
4100 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
4102 if ((flags&1) && target_is_directory) {
4103 END_PROFILE(SMBcopy);
4104 return ERROR_DOS(ERRDOS,ERRbadfile);
4107 if ((flags&2) && !target_is_directory) {
4108 END_PROFILE(SMBcopy);
4109 return ERROR_DOS(ERRDOS,ERRbadpath);
4112 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
4113 /* wants a tree copy! XXXX */
4114 DEBUG(3,("Rejecting tree copy\n"));
4115 END_PROFILE(SMBcopy);
4116 return ERROR_DOS(ERRSRV,ERRerror);
4119 p = strrchr_m(name,'/');
4120 if (!p) {
4121 pstrcpy(directory,"./");
4122 pstrcpy(mask,name);
4123 } else {
4124 *p = 0;
4125 pstrcpy(directory,name);
4126 pstrcpy(mask,p+1);
4130 * We should only check the mangled cache
4131 * here if unix_convert failed. This means
4132 * that the path in 'mask' doesn't exist
4133 * on the file system and so we need to look
4134 * for a possible mangle. This patch from
4135 * Tine Smukavec <valentin.smukavec@hermes.si>.
4138 if (!rc && mangle_is_mangled(mask))
4139 mangle_check_cache( mask );
4141 has_wild = ms_has_wild(mask);
4143 if (!has_wild) {
4144 pstrcat(directory,"/");
4145 pstrcat(directory,mask);
4146 if (resolve_wildcards(directory,newname) &&
4147 copy_file(directory,newname,conn,ofun, count,target_is_directory,&err))
4148 count++;
4149 if(!count && err) {
4150 errno = err;
4151 END_PROFILE(SMBcopy);
4152 return(UNIXERROR(ERRHRD,ERRgeneral));
4154 if (!count) {
4155 exists = vfs_file_exist(conn,directory,NULL);
4157 } else {
4158 void *dirptr = NULL;
4159 const char *dname;
4160 pstring destname;
4162 if (check_name(directory,conn))
4163 dirptr = OpenDir(conn, directory, True);
4165 if (dirptr) {
4166 error = ERRbadfile;
4168 if (strequal(mask,"????????.???"))
4169 pstrcpy(mask,"*");
4171 while ((dname = ReadDirName(dirptr))) {
4172 pstring fname;
4173 pstrcpy(fname,dname);
4175 if(!mask_match(fname, mask, case_sensitive))
4176 continue;
4178 error = ERRnoaccess;
4179 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
4180 pstrcpy(destname,newname);
4181 if (resolve_wildcards(fname,destname) &&
4182 copy_file(fname,destname,conn,ofun,
4183 count,target_is_directory,&err))
4184 count++;
4185 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
4187 CloseDir(dirptr);
4191 if (count == 0) {
4192 if(err) {
4193 /* Error on close... */
4194 errno = err;
4195 END_PROFILE(SMBcopy);
4196 return(UNIXERROR(ERRHRD,ERRgeneral));
4199 if (exists) {
4200 END_PROFILE(SMBcopy);
4201 return ERROR_DOS(ERRDOS,error);
4202 } else {
4203 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
4204 unix_ERR_class = ERRDOS;
4205 unix_ERR_code = ERRbadpath;
4207 END_PROFILE(SMBcopy);
4208 return(UNIXERROR(ERRDOS,error));
4212 outsize = set_message(outbuf,1,0,True);
4213 SSVAL(outbuf,smb_vwv0,count);
4215 END_PROFILE(SMBcopy);
4216 return(outsize);
4219 /****************************************************************************
4220 Reply to a setdir.
4221 ****************************************************************************/
4223 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4225 int snum;
4226 int outsize = 0;
4227 BOOL ok = False;
4228 pstring newdir;
4229 NTSTATUS status;
4231 START_PROFILE(pathworks_setdir);
4233 snum = SNUM(conn);
4234 if (!CAN_SETDIR(snum)) {
4235 END_PROFILE(pathworks_setdir);
4236 return ERROR_DOS(ERRDOS,ERRnoaccess);
4239 srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status);
4240 if (!NT_STATUS_IS_OK(status)) {
4241 END_PROFILE(pathworks_setdir);
4242 return ERROR_NT(status);
4245 if (strlen(newdir) == 0) {
4246 ok = True;
4247 } else {
4248 ok = vfs_directory_exist(conn,newdir,NULL);
4249 if (ok)
4250 string_set(&conn->connectpath,newdir);
4253 if (!ok) {
4254 END_PROFILE(pathworks_setdir);
4255 return ERROR_DOS(ERRDOS,ERRbadpath);
4258 outsize = set_message(outbuf,0,0,True);
4259 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
4261 DEBUG(3,("setdir %s\n", newdir));
4263 END_PROFILE(pathworks_setdir);
4264 return(outsize);
4267 /****************************************************************************
4268 Get a lock pid, dealing with large count requests.
4269 ****************************************************************************/
4271 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
4273 if(!large_file_format)
4274 return SVAL(data,SMB_LPID_OFFSET(data_offset));
4275 else
4276 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
4279 /****************************************************************************
4280 Get a lock count, dealing with large count requests.
4281 ****************************************************************************/
4283 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4285 SMB_BIG_UINT count = 0;
4287 if(!large_file_format) {
4288 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4289 } else {
4291 #if defined(HAVE_LONGLONG)
4292 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4293 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4294 #else /* HAVE_LONGLONG */
4297 * NT4.x seems to be broken in that it sends large file (64 bit)
4298 * lockingX calls even if the CAP_LARGE_FILES was *not*
4299 * negotiated. For boxes without large unsigned ints truncate the
4300 * lock count by dropping the top 32 bits.
4303 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4304 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4305 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4306 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4307 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4310 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4311 #endif /* HAVE_LONGLONG */
4314 return count;
4317 #if !defined(HAVE_LONGLONG)
4318 /****************************************************************************
4319 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
4320 ****************************************************************************/
4322 static uint32 map_lock_offset(uint32 high, uint32 low)
4324 unsigned int i;
4325 uint32 mask = 0;
4326 uint32 highcopy = high;
4329 * Try and find out how many significant bits there are in high.
4332 for(i = 0; highcopy; i++)
4333 highcopy >>= 1;
4336 * We use 31 bits not 32 here as POSIX
4337 * lock offsets may not be negative.
4340 mask = (~0) << (31 - i);
4342 if(low & mask)
4343 return 0; /* Fail. */
4345 high <<= (31 - i);
4347 return (high|low);
4349 #endif /* !defined(HAVE_LONGLONG) */
4351 /****************************************************************************
4352 Get a lock offset, dealing with large offset requests.
4353 ****************************************************************************/
4355 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4357 SMB_BIG_UINT offset = 0;
4359 *err = False;
4361 if(!large_file_format) {
4362 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4363 } else {
4365 #if defined(HAVE_LONGLONG)
4366 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4367 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4368 #else /* HAVE_LONGLONG */
4371 * NT4.x seems to be broken in that it sends large file (64 bit)
4372 * lockingX calls even if the CAP_LARGE_FILES was *not*
4373 * negotiated. For boxes without large unsigned ints mangle the
4374 * lock offset by mapping the top 32 bits onto the lower 32.
4377 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4378 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4379 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4380 uint32 new_low = 0;
4382 if((new_low = map_lock_offset(high, low)) == 0) {
4383 *err = True;
4384 return (SMB_BIG_UINT)-1;
4387 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4388 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4389 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4390 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4393 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4394 #endif /* HAVE_LONGLONG */
4397 return offset;
4400 /****************************************************************************
4401 Reply to a lockingX request.
4402 ****************************************************************************/
4404 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4406 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4407 unsigned char locktype = CVAL(inbuf,smb_vwv3);
4408 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4409 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4410 uint16 num_locks = SVAL(inbuf,smb_vwv7);
4411 SMB_BIG_UINT count = 0, offset = 0;
4412 uint16 lock_pid;
4413 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4414 int i;
4415 char *data;
4416 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4417 BOOL err;
4418 BOOL my_lock_ctx = False;
4419 NTSTATUS status;
4421 START_PROFILE(SMBlockingX);
4423 CHECK_FSP(fsp,conn);
4425 data = smb_buf(inbuf);
4427 if (locktype & (LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_CHANGE_LOCKTYPE)) {
4428 /* we don't support these - and CANCEL_LOCK makes w2k
4429 and XP reboot so I don't really want to be
4430 compatible! (tridge) */
4431 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
4434 /* Check if this is an oplock break on a file
4435 we have granted an oplock on.
4437 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
4438 /* Client can insist on breaking to none. */
4439 BOOL break_to_none = (oplocklevel == 0);
4441 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4442 (unsigned int)oplocklevel, fsp->fnum ));
4445 * Make sure we have granted an exclusive or batch oplock on this file.
4448 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
4449 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4450 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4452 /* if this is a pure oplock break request then don't send a reply */
4453 if (num_locks == 0 && num_ulocks == 0) {
4454 END_PROFILE(SMBlockingX);
4455 return -1;
4456 } else {
4457 END_PROFILE(SMBlockingX);
4458 return ERROR_DOS(ERRDOS,ERRlock);
4462 if (remove_oplock(fsp, break_to_none) == False) {
4463 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4464 fsp->fsp_name ));
4467 /* if this is a pure oplock break request then don't send a reply */
4468 if (num_locks == 0 && num_ulocks == 0) {
4469 /* Sanity check - ensure a pure oplock break is not a
4470 chained request. */
4471 if(CVAL(inbuf,smb_vwv0) != 0xff)
4472 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4473 (unsigned int)CVAL(inbuf,smb_vwv0) ));
4474 END_PROFILE(SMBlockingX);
4475 return -1;
4480 * We do this check *after* we have checked this is not a oplock break
4481 * response message. JRA.
4484 release_level_2_oplocks_on_change(fsp);
4486 /* Data now points at the beginning of the list
4487 of smb_unlkrng structs */
4488 for(i = 0; i < (int)num_ulocks; i++) {
4489 lock_pid = get_lock_pid( data, i, large_file_format);
4490 count = get_lock_count( data, i, large_file_format);
4491 offset = get_lock_offset( data, i, large_file_format, &err);
4494 * There is no error code marked "stupid client bug".... :-).
4496 if(err) {
4497 END_PROFILE(SMBlockingX);
4498 return ERROR_DOS(ERRDOS,ERRnoaccess);
4501 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4502 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4504 status = do_unlock(fsp,conn,lock_pid,count,offset);
4505 if (NT_STATUS_V(status)) {
4506 END_PROFILE(SMBlockingX);
4507 return ERROR_NT(status);
4511 /* Setup the timeout in seconds. */
4513 lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000);
4515 /* Now do any requested locks */
4516 data += ((large_file_format ? 20 : 10)*num_ulocks);
4518 /* Data now points at the beginning of the list
4519 of smb_lkrng structs */
4521 for(i = 0; i < (int)num_locks; i++) {
4522 lock_pid = get_lock_pid( data, i, large_file_format);
4523 count = get_lock_count( data, i, large_file_format);
4524 offset = get_lock_offset( data, i, large_file_format, &err);
4527 * There is no error code marked "stupid client bug".... :-).
4529 if(err) {
4530 END_PROFILE(SMBlockingX);
4531 return ERROR_DOS(ERRDOS,ERRnoaccess);
4534 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
4535 (double)offset, (double)count, (unsigned int)lock_pid,
4536 fsp->fsp_name, (int)lock_timeout ));
4538 status = do_lock_spin(fsp,conn,lock_pid, count,offset,
4539 ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &my_lock_ctx);
4540 if (NT_STATUS_V(status)) {
4542 * Interesting fact found by IFSTEST /t LockOverlappedTest...
4543 * Even if it's our own lock context, we need to wait here as
4544 * there may be an unlock on the way.
4545 * So I removed a "&& !my_lock_ctx" from the following
4546 * if statement. JRA.
4548 if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
4550 * A blocking lock was requested. Package up
4551 * this smb into a queued request and push it
4552 * onto the blocking lock queue.
4554 if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) {
4555 END_PROFILE(SMBlockingX);
4556 return -1;
4559 break;
4563 /* If any of the above locks failed, then we must unlock
4564 all of the previous locks (X/Open spec). */
4565 if (i != num_locks && num_locks != 0) {
4567 * Ensure we don't do a remove on the lock that just failed,
4568 * as under POSIX rules, if we have a lock already there, we
4569 * will delete it (and we shouldn't) .....
4571 for(i--; i >= 0; i--) {
4572 lock_pid = get_lock_pid( data, i, large_file_format);
4573 count = get_lock_count( data, i, large_file_format);
4574 offset = get_lock_offset( data, i, large_file_format, &err);
4577 * There is no error code marked "stupid client bug".... :-).
4579 if(err) {
4580 END_PROFILE(SMBlockingX);
4581 return ERROR_DOS(ERRDOS,ERRnoaccess);
4584 do_unlock(fsp,conn,lock_pid,count,offset);
4586 END_PROFILE(SMBlockingX);
4587 return ERROR_NT(status);
4590 set_message(outbuf,2,0,True);
4592 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4593 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4595 END_PROFILE(SMBlockingX);
4596 return chain_reply(inbuf,outbuf,length,bufsize);
4599 /****************************************************************************
4600 Reply to a SMBreadbmpx (read block multiplex) request.
4601 ****************************************************************************/
4603 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4605 ssize_t nread = -1;
4606 ssize_t total_read;
4607 char *data;
4608 SMB_OFF_T startpos;
4609 int outsize;
4610 size_t maxcount;
4611 int max_per_packet;
4612 size_t tcount;
4613 int pad;
4614 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4615 START_PROFILE(SMBreadBmpx);
4617 /* this function doesn't seem to work - disable by default */
4618 if (!lp_readbmpx()) {
4619 END_PROFILE(SMBreadBmpx);
4620 return ERROR_DOS(ERRSRV,ERRuseSTD);
4623 outsize = set_message(outbuf,8,0,True);
4625 CHECK_FSP(fsp,conn);
4626 CHECK_READ(fsp);
4628 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
4629 maxcount = SVAL(inbuf,smb_vwv3);
4631 data = smb_buf(outbuf);
4632 pad = ((long)data)%4;
4633 if (pad)
4634 pad = 4 - pad;
4635 data += pad;
4637 max_per_packet = bufsize-(outsize+pad);
4638 tcount = maxcount;
4639 total_read = 0;
4641 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
4642 END_PROFILE(SMBreadBmpx);
4643 return ERROR_DOS(ERRDOS,ERRlock);
4646 do {
4647 size_t N = MIN(max_per_packet,tcount-total_read);
4649 nread = read_file(fsp,data,startpos,N);
4651 if (nread <= 0)
4652 nread = 0;
4654 if (nread < (ssize_t)N)
4655 tcount = total_read + nread;
4657 set_message(outbuf,8,nread,False);
4658 SIVAL(outbuf,smb_vwv0,startpos);
4659 SSVAL(outbuf,smb_vwv2,tcount);
4660 SSVAL(outbuf,smb_vwv6,nread);
4661 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4663 if (!send_smb(smbd_server_fd(),outbuf))
4664 exit_server("reply_readbmpx: send_smb failed.");
4666 total_read += nread;
4667 startpos += nread;
4668 } while (total_read < (ssize_t)tcount);
4670 END_PROFILE(SMBreadBmpx);
4671 return(-1);
4674 /****************************************************************************
4675 Reply to a SMBsetattrE.
4676 ****************************************************************************/
4678 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4680 struct utimbuf unix_times;
4681 int outsize = 0;
4682 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4683 START_PROFILE(SMBsetattrE);
4685 outsize = set_message(outbuf,0,0,True);
4687 if(!fsp || (fsp->conn != conn)) {
4688 END_PROFILE(SMBgetattrE);
4689 return ERROR_DOS(ERRDOS,ERRbadfid);
4693 * Convert the DOS times into unix times. Ignore create
4694 * time as UNIX can't set this.
4697 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4698 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4701 * Patch from Ray Frush <frush@engr.colostate.edu>
4702 * Sometimes times are sent as zero - ignore them.
4705 if ((unix_times.actime == 0) && (unix_times.modtime == 0)) {
4706 /* Ignore request */
4707 if( DEBUGLVL( 3 ) ) {
4708 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4709 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4711 END_PROFILE(SMBsetattrE);
4712 return(outsize);
4713 } else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) {
4714 /* set modify time = to access time if modify time was 0 */
4715 unix_times.modtime = unix_times.actime;
4718 /* Set the date on this file */
4719 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4720 END_PROFILE(SMBsetattrE);
4721 return ERROR_DOS(ERRDOS,ERRnoaccess);
4724 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4725 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4727 END_PROFILE(SMBsetattrE);
4728 return(outsize);
4732 /* Back from the dead for OS/2..... JRA. */
4734 /****************************************************************************
4735 Reply to a SMBwritebmpx (write block multiplex primary) request.
4736 ****************************************************************************/
4738 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4740 size_t numtowrite;
4741 ssize_t nwritten = -1;
4742 int outsize = 0;
4743 SMB_OFF_T startpos;
4744 size_t tcount;
4745 BOOL write_through;
4746 int smb_doff;
4747 char *data;
4748 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4749 START_PROFILE(SMBwriteBmpx);
4751 CHECK_FSP(fsp,conn);
4752 CHECK_WRITE(fsp);
4753 CHECK_ERROR(fsp);
4755 tcount = SVAL(inbuf,smb_vwv1);
4756 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
4757 write_through = BITSETW(inbuf+smb_vwv7,0);
4758 numtowrite = SVAL(inbuf,smb_vwv10);
4759 smb_doff = SVAL(inbuf,smb_vwv11);
4761 data = smb_base(inbuf) + smb_doff;
4763 /* If this fails we need to send an SMBwriteC response,
4764 not an SMBwritebmpx - set this up now so we don't forget */
4765 SCVAL(outbuf,smb_com,SMBwritec);
4767 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK,False)) {
4768 END_PROFILE(SMBwriteBmpx);
4769 return(ERROR_DOS(ERRDOS,ERRlock));
4772 nwritten = write_file(fsp,data,startpos,numtowrite);
4774 if(lp_syncalways(SNUM(conn)) || write_through)
4775 sync_file(conn,fsp);
4777 if(nwritten < (ssize_t)numtowrite) {
4778 END_PROFILE(SMBwriteBmpx);
4779 return(UNIXERROR(ERRHRD,ERRdiskfull));
4782 /* If the maximum to be written to this file
4783 is greater than what we just wrote then set
4784 up a secondary struct to be attached to this
4785 fd, we will use this to cache error messages etc. */
4787 if((ssize_t)tcount > nwritten) {
4788 write_bmpx_struct *wbms;
4789 if(fsp->wbmpx_ptr != NULL)
4790 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4791 else
4792 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
4793 if(!wbms) {
4794 DEBUG(0,("Out of memory in reply_readmpx\n"));
4795 END_PROFILE(SMBwriteBmpx);
4796 return(ERROR_DOS(ERRSRV,ERRnoresource));
4798 wbms->wr_mode = write_through;
4799 wbms->wr_discard = False; /* No errors yet */
4800 wbms->wr_total_written = nwritten;
4801 wbms->wr_errclass = 0;
4802 wbms->wr_error = 0;
4803 fsp->wbmpx_ptr = wbms;
4806 /* We are returning successfully, set the message type back to
4807 SMBwritebmpx */
4808 SCVAL(outbuf,smb_com,SMBwriteBmpx);
4810 outsize = set_message(outbuf,1,0,True);
4812 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
4814 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4815 fsp->fnum, (int)numtowrite, (int)nwritten ) );
4817 if (write_through && tcount==nwritten) {
4818 /* We need to send both a primary and a secondary response */
4819 smb_setlen(outbuf,outsize - 4);
4820 if (!send_smb(smbd_server_fd(),outbuf))
4821 exit_server("reply_writebmpx: send_smb failed.");
4823 /* Now the secondary */
4824 outsize = set_message(outbuf,1,0,True);
4825 SCVAL(outbuf,smb_com,SMBwritec);
4826 SSVAL(outbuf,smb_vwv0,nwritten);
4829 END_PROFILE(SMBwriteBmpx);
4830 return(outsize);
4833 /****************************************************************************
4834 Reply to a SMBwritebs (write block multiplex secondary) request.
4835 ****************************************************************************/
4837 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4839 size_t numtowrite;
4840 ssize_t nwritten = -1;
4841 int outsize = 0;
4842 SMB_OFF_T startpos;
4843 size_t tcount;
4844 BOOL write_through;
4845 int smb_doff;
4846 char *data;
4847 write_bmpx_struct *wbms;
4848 BOOL send_response = False;
4849 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4850 START_PROFILE(SMBwriteBs);
4852 CHECK_FSP(fsp,conn);
4853 CHECK_WRITE(fsp);
4855 tcount = SVAL(inbuf,smb_vwv1);
4856 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
4857 numtowrite = SVAL(inbuf,smb_vwv6);
4858 smb_doff = SVAL(inbuf,smb_vwv7);
4860 data = smb_base(inbuf) + smb_doff;
4862 /* We need to send an SMBwriteC response, not an SMBwritebs */
4863 SCVAL(outbuf,smb_com,SMBwritec);
4865 /* This fd should have an auxiliary struct attached,
4866 check that it does */
4867 wbms = fsp->wbmpx_ptr;
4868 if(!wbms) {
4869 END_PROFILE(SMBwriteBs);
4870 return(-1);
4873 /* If write through is set we can return errors, else we must cache them */
4874 write_through = wbms->wr_mode;
4876 /* Check for an earlier error */
4877 if(wbms->wr_discard) {
4878 END_PROFILE(SMBwriteBs);
4879 return -1; /* Just discard the packet */
4882 nwritten = write_file(fsp,data,startpos,numtowrite);
4884 if(lp_syncalways(SNUM(conn)) || write_through)
4885 sync_file(conn,fsp);
4887 if (nwritten < (ssize_t)numtowrite) {
4888 if(write_through) {
4889 /* We are returning an error - we can delete the aux struct */
4890 if (wbms)
4891 free((char *)wbms);
4892 fsp->wbmpx_ptr = NULL;
4893 END_PROFILE(SMBwriteBs);
4894 return(ERROR_DOS(ERRHRD,ERRdiskfull));
4896 END_PROFILE(SMBwriteBs);
4897 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4900 /* Increment the total written, if this matches tcount
4901 we can discard the auxiliary struct (hurrah !) and return a writeC */
4902 wbms->wr_total_written += nwritten;
4903 if(wbms->wr_total_written >= tcount) {
4904 if (write_through) {
4905 outsize = set_message(outbuf,1,0,True);
4906 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
4907 send_response = True;
4910 free((char *)wbms);
4911 fsp->wbmpx_ptr = NULL;
4914 if(send_response) {
4915 END_PROFILE(SMBwriteBs);
4916 return(outsize);
4919 END_PROFILE(SMBwriteBs);
4920 return(-1);
4923 /****************************************************************************
4924 Reply to a SMBgetattrE.
4925 ****************************************************************************/
4927 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4929 SMB_STRUCT_STAT sbuf;
4930 int outsize = 0;
4931 int mode;
4932 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4933 START_PROFILE(SMBgetattrE);
4935 outsize = set_message(outbuf,11,0,True);
4937 if(!fsp || (fsp->conn != conn)) {
4938 END_PROFILE(SMBgetattrE);
4939 return ERROR_DOS(ERRDOS,ERRbadfid);
4942 /* Do an fstat on this file */
4943 if(fsp_stat(fsp, &sbuf)) {
4944 END_PROFILE(SMBgetattrE);
4945 return(UNIXERROR(ERRDOS,ERRnoaccess));
4948 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4951 * Convert the times into dos times. Set create
4952 * date to be last modify date as UNIX doesn't save
4953 * this.
4956 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4957 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4958 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4960 if (mode & aDIR) {
4961 SIVAL(outbuf,smb_vwv6,0);
4962 SIVAL(outbuf,smb_vwv8,0);
4963 } else {
4964 uint32 allocation_size = get_allocation_size(fsp, &sbuf);
4965 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4966 SIVAL(outbuf,smb_vwv8,allocation_size);
4968 SSVAL(outbuf,smb_vwv10, mode);
4970 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
4972 END_PROFILE(SMBgetattrE);
4973 return(outsize);