Fix typo in check_path_syntax.
[Samba/gebeck_regimport.git] / source3 / smbd / reply.c
blob7498821185ac701536903b3f01124a3cea458096
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 continue;
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;
1585 if (SMB_VFS_UNLINK(conn,fname) == 0)
1586 count++;
1587 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
1589 CloseDir(dirptr);
1593 if (count == 0 && NT_STATUS_IS_OK(error)) {
1594 error = map_nt_error_from_unix(errno);
1597 return error;
1600 /****************************************************************************
1601 Reply to a unlink
1602 ****************************************************************************/
1604 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
1605 int dum_buffsize)
1607 int outsize = 0;
1608 pstring name;
1609 int dirtype;
1610 NTSTATUS status;
1611 START_PROFILE(SMBunlink);
1613 dirtype = SVAL(inbuf,smb_vwv0);
1615 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
1616 if (!NT_STATUS_IS_OK(status)) {
1617 END_PROFILE(SMBunlink);
1618 return ERROR_NT(status);
1621 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1623 DEBUG(3,("reply_unlink : %s\n",name));
1625 status = unlink_internals(conn, dirtype, name);
1626 if (!NT_STATUS_IS_OK(status))
1627 return ERROR_NT(status);
1630 * Win2k needs a changenotify request response before it will
1631 * update after a rename..
1633 process_pending_change_notify_queue((time_t)0);
1635 outsize = set_message(outbuf,0,0,True);
1637 END_PROFILE(SMBunlink);
1638 return outsize;
1641 /****************************************************************************
1642 Fail for readbraw.
1643 ****************************************************************************/
1645 void fail_readraw(void)
1647 pstring errstr;
1648 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
1649 strerror(errno) );
1650 exit_server(errstr);
1653 /****************************************************************************
1654 Use sendfile in readbraw.
1655 ****************************************************************************/
1657 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
1658 ssize_t mincount, char *outbuf)
1660 ssize_t ret=0;
1662 #if defined(WITH_SENDFILE)
1664 * We can only use sendfile on a non-chained packet and on a file
1665 * that is exclusively oplocked. reply_readbraw has already checked the length.
1668 if ((nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) &&
1669 EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && lp_use_sendfile(SNUM(conn)) ) {
1670 DATA_BLOB header;
1672 _smb_setlen(outbuf,nread);
1673 header.data = outbuf;
1674 header.length = 4;
1675 header.free = NULL;
1677 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) {
1679 * Special hack for broken Linux with no 64 bit clean sendfile. If we
1680 * return ENOSYS then pretend we just got a normal read.
1682 if (errno == ENOSYS)
1683 goto normal_read;
1685 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
1686 fsp->fsp_name, strerror(errno) ));
1687 exit_server("send_file_readbraw sendfile failed");
1692 normal_read:
1693 #endif
1695 if (nread > 0) {
1696 ret = read_file(fsp,outbuf+4,startpos,nread);
1697 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1698 if (ret < mincount)
1699 ret = 0;
1700 #else
1701 if (ret < nread)
1702 ret = 0;
1703 #endif
1706 _smb_setlen(outbuf,ret);
1707 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
1708 fail_readraw();
1711 /****************************************************************************
1712 Reply to a readbraw (core+ protocol).
1713 ****************************************************************************/
1715 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
1717 extern struct current_user current_user;
1718 ssize_t maxcount,mincount;
1719 size_t nread = 0;
1720 SMB_OFF_T startpos;
1721 char *header = outbuf;
1722 files_struct *fsp;
1723 START_PROFILE(SMBreadbraw);
1725 if (srv_is_signing_active()) {
1726 exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
1730 * Special check if an oplock break has been issued
1731 * and the readraw request croses on the wire, we must
1732 * return a zero length response here.
1735 if(global_oplock_break) {
1736 _smb_setlen(header,0);
1737 if (write_data(smbd_server_fd(),header,4) != 4)
1738 fail_readraw();
1739 DEBUG(5,("readbraw - oplock break finished\n"));
1740 END_PROFILE(SMBreadbraw);
1741 return -1;
1744 fsp = file_fsp(inbuf,smb_vwv0);
1746 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1748 * fsp could be NULL here so use the value from the packet. JRA.
1750 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
1751 _smb_setlen(header,0);
1752 if (write_data(smbd_server_fd(),header,4) != 4)
1753 fail_readraw();
1754 END_PROFILE(SMBreadbraw);
1755 return(-1);
1758 CHECK_FSP(fsp,conn);
1760 flush_write_cache(fsp, READRAW_FLUSH);
1762 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
1763 if(CVAL(inbuf,smb_wct) == 10) {
1765 * This is a large offset (64 bit) read.
1767 #ifdef LARGE_SMB_OFF_T
1769 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
1771 #else /* !LARGE_SMB_OFF_T */
1774 * Ensure we haven't been sent a >32 bit offset.
1777 if(IVAL(inbuf,smb_vwv8) != 0) {
1778 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
1779 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
1780 _smb_setlen(header,0);
1781 if (write_data(smbd_server_fd(),header,4) != 4)
1782 fail_readraw();
1783 END_PROFILE(SMBreadbraw);
1784 return(-1);
1787 #endif /* LARGE_SMB_OFF_T */
1789 if(startpos < 0) {
1790 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
1791 _smb_setlen(header,0);
1792 if (write_data(smbd_server_fd(),header,4) != 4)
1793 fail_readraw();
1794 END_PROFILE(SMBreadbraw);
1795 return(-1);
1798 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
1799 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
1801 /* ensure we don't overrun the packet size */
1802 maxcount = MIN(65535,maxcount);
1804 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1805 SMB_OFF_T size = fsp->size;
1806 SMB_OFF_T sizeneeded = startpos + maxcount;
1808 if (size < sizeneeded) {
1809 SMB_STRUCT_STAT st;
1810 if (SMB_VFS_FSTAT(fsp,fsp->fd,&st) == 0)
1811 size = st.st_size;
1812 if (!fsp->can_write)
1813 fsp->size = size;
1816 if (startpos >= size)
1817 nread = 0;
1818 else
1819 nread = MIN(maxcount,(size - startpos));
1822 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1823 if (nread < mincount)
1824 nread = 0;
1825 #endif
1827 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
1828 (int)maxcount, (int)mincount, (int)nread ) );
1830 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf);
1832 DEBUG(5,("readbraw finished\n"));
1833 END_PROFILE(SMBreadbraw);
1834 return -1;
1837 /****************************************************************************
1838 Reply to a lockread (core+ protocol).
1839 ****************************************************************************/
1841 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
1843 ssize_t nread = -1;
1844 char *data;
1845 int outsize = 0;
1846 SMB_OFF_T startpos;
1847 size_t numtoread;
1848 NTSTATUS status;
1849 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1850 BOOL my_lock_ctx = False;
1851 START_PROFILE(SMBlockread);
1853 CHECK_FSP(fsp,conn);
1854 CHECK_READ(fsp);
1856 release_level_2_oplocks_on_change(fsp);
1858 numtoread = SVAL(inbuf,smb_vwv1);
1859 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
1861 outsize = set_message(outbuf,5,3,True);
1862 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1863 data = smb_buf(outbuf) + 3;
1866 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
1867 * protocol request that predates the read/write lock concept.
1868 * Thus instead of asking for a read lock here we need to ask
1869 * for a write lock. JRA.
1870 * Note that the requested lock size is unaffected by max_recv.
1873 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid),
1874 (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, &my_lock_ctx);
1876 if (NT_STATUS_V(status)) {
1877 #if 0
1879 * We used to make lockread a blocking lock. It turns out
1880 * that this isn't on W2k. Found by the Samba 4 RAW-READ torture
1881 * tester. JRA.
1884 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
1886 * A blocking lock was requested. Package up
1887 * this smb into a queued request and push it
1888 * onto the blocking lock queue.
1890 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)startpos,
1891 (SMB_BIG_UINT)numtoread)) {
1892 END_PROFILE(SMBlockread);
1893 return -1;
1896 #endif
1897 END_PROFILE(SMBlockread);
1898 return ERROR_NT(status);
1902 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
1905 if (numtoread > max_recv) {
1906 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
1907 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
1908 (unsigned int)numtoread, (unsigned int)max_recv ));
1909 numtoread = MIN(numtoread,max_recv);
1911 nread = read_file(fsp,data,startpos,numtoread);
1913 if (nread < 0) {
1914 END_PROFILE(SMBlockread);
1915 return(UNIXERROR(ERRDOS,ERRnoaccess));
1918 outsize += nread;
1919 SSVAL(outbuf,smb_vwv0,nread);
1920 SSVAL(outbuf,smb_vwv5,nread+3);
1921 SSVAL(smb_buf(outbuf),1,nread);
1923 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
1924 fsp->fnum, (int)numtoread, (int)nread));
1926 END_PROFILE(SMBlockread);
1927 return(outsize);
1930 /****************************************************************************
1931 Reply to a read.
1932 ****************************************************************************/
1934 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
1936 size_t numtoread;
1937 ssize_t nread = 0;
1938 char *data;
1939 SMB_OFF_T startpos;
1940 int outsize = 0;
1941 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1942 START_PROFILE(SMBread);
1944 CHECK_FSP(fsp,conn);
1945 CHECK_READ(fsp);
1947 numtoread = SVAL(inbuf,smb_vwv1);
1948 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
1950 outsize = set_message(outbuf,5,3,True);
1951 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1953 * The requested read size cannot be greater than max_recv. JRA.
1955 if (numtoread > max_recv) {
1956 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
1957 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
1958 (unsigned int)numtoread, (unsigned int)max_recv ));
1959 numtoread = MIN(numtoread,max_recv);
1962 data = smb_buf(outbuf) + 3;
1964 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1965 END_PROFILE(SMBread);
1966 return ERROR_DOS(ERRDOS,ERRlock);
1969 if (numtoread > 0)
1970 nread = read_file(fsp,data,startpos,numtoread);
1972 if (nread < 0) {
1973 END_PROFILE(SMBread);
1974 return(UNIXERROR(ERRDOS,ERRnoaccess));
1977 outsize += nread;
1978 SSVAL(outbuf,smb_vwv0,nread);
1979 SSVAL(outbuf,smb_vwv5,nread+3);
1980 SCVAL(smb_buf(outbuf),0,1);
1981 SSVAL(smb_buf(outbuf),1,nread);
1983 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
1984 fsp->fnum, (int)numtoread, (int)nread ) );
1986 END_PROFILE(SMBread);
1987 return(outsize);
1990 /****************************************************************************
1991 Reply to a read and X - possibly using sendfile.
1992 ****************************************************************************/
1994 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length,
1995 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
1997 ssize_t nread = -1;
1998 char *data = smb_buf(outbuf);
2000 #if defined(WITH_SENDFILE)
2002 * We can only use sendfile on a non-chained packet and on a file
2003 * that is exclusively oplocked.
2006 if ((CVAL(inbuf,smb_vwv0) == 0xFF) && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) &&
2007 lp_use_sendfile(SNUM(conn)) && (lp_write_cache_size(SNUM(conn)) == 0) ) {
2008 SMB_STRUCT_STAT sbuf;
2009 DATA_BLOB header;
2011 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1)
2012 return(UNIXERROR(ERRDOS,ERRnoaccess));
2014 if (startpos > sbuf.st_size)
2015 goto normal_read;
2017 if (smb_maxcnt > (sbuf.st_size - startpos))
2018 smb_maxcnt = (sbuf.st_size - startpos);
2020 if (smb_maxcnt == 0)
2021 goto normal_read;
2024 * Set up the packet header before send. We
2025 * assume here the sendfile will work (get the
2026 * correct amount of data).
2029 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2030 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
2031 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2032 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
2033 SCVAL(outbuf,smb_vwv0,0xFF);
2034 set_message(outbuf,12,smb_maxcnt,False);
2035 header.data = outbuf;
2036 header.length = data - outbuf;
2037 header.free = NULL;
2039 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt) == -1) {
2041 * Special hack for broken Linux with no 64 bit clean sendfile. If we
2042 * return ENOSYS then pretend we just got a normal read.
2044 if (errno == ENOSYS)
2045 goto normal_read;
2047 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2048 fsp->fsp_name, strerror(errno) ));
2049 exit_server("send_file_readX sendfile failed");
2052 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2053 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2054 return -1;
2057 normal_read:
2059 #endif
2061 nread = read_file(fsp,data,startpos,smb_maxcnt);
2063 if (nread < 0) {
2064 END_PROFILE(SMBreadX);
2065 return(UNIXERROR(ERRDOS,ERRnoaccess));
2068 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2069 SSVAL(outbuf,smb_vwv5,nread);
2070 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2071 SSVAL(smb_buf(outbuf),-2,nread);
2073 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2074 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2076 return nread;
2079 /****************************************************************************
2080 Reply to a read and X.
2081 ****************************************************************************/
2083 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2085 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2086 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2087 ssize_t nread = -1;
2088 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2089 #if 0
2090 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2091 #endif
2093 START_PROFILE(SMBreadX);
2095 /* If it's an IPC, pass off the pipe handler. */
2096 if (IS_IPC(conn)) {
2097 END_PROFILE(SMBreadX);
2098 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2101 CHECK_FSP(fsp,conn);
2102 CHECK_READ(fsp);
2104 set_message(outbuf,12,0,True);
2106 if(CVAL(inbuf,smb_wct) == 12) {
2107 #ifdef LARGE_SMB_OFF_T
2109 * This is a large offset (64 bit) read.
2111 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2113 #else /* !LARGE_SMB_OFF_T */
2116 * Ensure we haven't been sent a >32 bit offset.
2119 if(IVAL(inbuf,smb_vwv10) != 0) {
2120 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2121 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2122 END_PROFILE(SMBreadX);
2123 return ERROR_DOS(ERRDOS,ERRbadaccess);
2126 #endif /* LARGE_SMB_OFF_T */
2130 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
2131 END_PROFILE(SMBreadX);
2132 return ERROR_DOS(ERRDOS,ERRlock);
2135 nread = send_file_readX(conn, inbuf, outbuf, length, fsp, startpos, smb_maxcnt);
2136 if (nread != -1)
2137 nread = chain_reply(inbuf,outbuf,length,bufsize);
2139 END_PROFILE(SMBreadX);
2140 return nread;
2143 /****************************************************************************
2144 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2145 ****************************************************************************/
2147 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2149 ssize_t nwritten=0;
2150 ssize_t total_written=0;
2151 size_t numtowrite=0;
2152 size_t tcount;
2153 SMB_OFF_T startpos;
2154 char *data=NULL;
2155 BOOL write_through;
2156 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2157 int outsize = 0;
2158 START_PROFILE(SMBwritebraw);
2160 if (srv_is_signing_active()) {
2161 exit_server("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2164 CHECK_FSP(fsp,conn);
2165 CHECK_WRITE(fsp);
2167 tcount = IVAL(inbuf,smb_vwv1);
2168 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2169 write_through = BITSETW(inbuf+smb_vwv7,0);
2171 /* We have to deal with slightly different formats depending
2172 on whether we are using the core+ or lanman1.0 protocol */
2174 if(Protocol <= PROTOCOL_COREPLUS) {
2175 numtowrite = SVAL(smb_buf(inbuf),-2);
2176 data = smb_buf(inbuf);
2177 } else {
2178 numtowrite = SVAL(inbuf,smb_vwv10);
2179 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2182 /* force the error type */
2183 SCVAL(inbuf,smb_com,SMBwritec);
2184 SCVAL(outbuf,smb_com,SMBwritec);
2186 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2187 END_PROFILE(SMBwritebraw);
2188 return(ERROR_DOS(ERRDOS,ERRlock));
2191 if (numtowrite>0)
2192 nwritten = write_file(fsp,data,startpos,numtowrite);
2194 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2195 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2197 if (nwritten < (ssize_t)numtowrite) {
2198 END_PROFILE(SMBwritebraw);
2199 return(UNIXERROR(ERRHRD,ERRdiskfull));
2202 total_written = nwritten;
2204 /* Return a message to the redirector to tell it to send more bytes */
2205 SCVAL(outbuf,smb_com,SMBwritebraw);
2206 SSVALS(outbuf,smb_vwv0,-1);
2207 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2208 if (!send_smb(smbd_server_fd(),outbuf))
2209 exit_server("reply_writebraw: send_smb failed.");
2211 /* Now read the raw data into the buffer and write it */
2212 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2213 exit_server("secondary writebraw failed");
2216 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2217 numtowrite = smb_len(inbuf);
2219 /* Set up outbuf to return the correct return */
2220 outsize = set_message(outbuf,1,0,True);
2221 SCVAL(outbuf,smb_com,SMBwritec);
2222 SSVAL(outbuf,smb_vwv0,total_written);
2224 if (numtowrite != 0) {
2226 if (numtowrite > BUFFER_SIZE) {
2227 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2228 (unsigned int)numtowrite ));
2229 exit_server("secondary writebraw failed");
2232 if (tcount > nwritten+numtowrite) {
2233 DEBUG(3,("Client overestimated the write %d %d %d\n",
2234 (int)tcount,(int)nwritten,(int)numtowrite));
2237 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2238 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2239 strerror(errno) ));
2240 exit_server("secondary writebraw failed");
2243 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2245 if (nwritten < (ssize_t)numtowrite) {
2246 SCVAL(outbuf,smb_rcls,ERRHRD);
2247 SSVAL(outbuf,smb_err,ERRdiskfull);
2250 if (nwritten > 0)
2251 total_written += nwritten;
2254 if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn)))
2255 sync_file(conn,fsp);
2257 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2258 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2260 /* we won't return a status if write through is not selected - this follows what WfWg does */
2261 END_PROFILE(SMBwritebraw);
2262 if (!write_through && total_written==tcount) {
2264 #if RABBIT_PELLET_FIX
2266 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2267 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2269 if (!send_keepalive(smbd_server_fd()))
2270 exit_server("reply_writebraw: send of keepalive failed");
2271 #endif
2272 return(-1);
2275 return(outsize);
2278 /****************************************************************************
2279 Reply to a writeunlock (core+).
2280 ****************************************************************************/
2282 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
2283 int size, int dum_buffsize)
2285 ssize_t nwritten = -1;
2286 size_t numtowrite;
2287 SMB_OFF_T startpos;
2288 char *data;
2289 NTSTATUS status = NT_STATUS_OK;
2290 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2291 int outsize = 0;
2292 START_PROFILE(SMBwriteunlock);
2294 CHECK_FSP(fsp,conn);
2295 CHECK_WRITE(fsp);
2297 numtowrite = SVAL(inbuf,smb_vwv1);
2298 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2299 data = smb_buf(inbuf) + 3;
2301 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos,
2302 WRITE_LOCK,False)) {
2303 END_PROFILE(SMBwriteunlock);
2304 return ERROR_DOS(ERRDOS,ERRlock);
2307 /* The special X/Open SMB protocol handling of
2308 zero length writes is *NOT* done for
2309 this call */
2310 if(numtowrite == 0)
2311 nwritten = 0;
2312 else
2313 nwritten = write_file(fsp,data,startpos,numtowrite);
2315 if (lp_syncalways(SNUM(conn)))
2316 sync_file(conn,fsp);
2318 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2319 END_PROFILE(SMBwriteunlock);
2320 return(UNIXERROR(ERRHRD,ERRdiskfull));
2323 if (numtowrite) {
2324 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite,
2325 (SMB_BIG_UINT)startpos);
2326 if (NT_STATUS_V(status)) {
2327 END_PROFILE(SMBwriteunlock);
2328 return ERROR_NT(status);
2332 outsize = set_message(outbuf,1,0,True);
2334 SSVAL(outbuf,smb_vwv0,nwritten);
2336 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2337 fsp->fnum, (int)numtowrite, (int)nwritten));
2339 END_PROFILE(SMBwriteunlock);
2340 return outsize;
2343 /****************************************************************************
2344 Reply to a write.
2345 ****************************************************************************/
2347 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2349 size_t numtowrite;
2350 ssize_t nwritten = -1;
2351 SMB_OFF_T startpos;
2352 char *data;
2353 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2354 int outsize = 0;
2355 START_PROFILE(SMBwrite);
2357 /* If it's an IPC, pass off the pipe handler. */
2358 if (IS_IPC(conn)) {
2359 END_PROFILE(SMBwrite);
2360 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2363 CHECK_FSP(fsp,conn);
2364 CHECK_WRITE(fsp);
2366 numtowrite = SVAL(inbuf,smb_vwv1);
2367 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2368 data = smb_buf(inbuf) + 3;
2370 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2371 END_PROFILE(SMBwrite);
2372 return ERROR_DOS(ERRDOS,ERRlock);
2376 * X/Open SMB protocol says that if smb_vwv1 is
2377 * zero then the file size should be extended or
2378 * truncated to the size given in smb_vwv[2-3].
2381 if(numtowrite == 0) {
2383 * This is actually an allocate call, and set EOF. JRA.
2385 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2386 if (nwritten < 0) {
2387 END_PROFILE(SMBwrite);
2388 return ERROR_NT(NT_STATUS_DISK_FULL);
2390 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2391 if (nwritten < 0) {
2392 END_PROFILE(SMBwrite);
2393 return ERROR_NT(NT_STATUS_DISK_FULL);
2395 } else
2396 nwritten = write_file(fsp,data,startpos,numtowrite);
2398 if (lp_syncalways(SNUM(conn)))
2399 sync_file(conn,fsp);
2401 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2402 END_PROFILE(SMBwrite);
2403 return(UNIXERROR(ERRHRD,ERRdiskfull));
2406 outsize = set_message(outbuf,1,0,True);
2408 SSVAL(outbuf,smb_vwv0,nwritten);
2410 if (nwritten < (ssize_t)numtowrite) {
2411 SCVAL(outbuf,smb_rcls,ERRHRD);
2412 SSVAL(outbuf,smb_err,ERRdiskfull);
2415 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2417 END_PROFILE(SMBwrite);
2418 return(outsize);
2421 /****************************************************************************
2422 Reply to a write and X.
2423 ****************************************************************************/
2425 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2427 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2428 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2429 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2430 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2431 ssize_t nwritten = -1;
2432 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2433 unsigned int smblen = smb_len(inbuf);
2434 char *data;
2435 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2436 START_PROFILE(SMBwriteX);
2438 /* If it's an IPC, pass off the pipe handler. */
2439 if (IS_IPC(conn)) {
2440 END_PROFILE(SMBwriteX);
2441 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2444 CHECK_FSP(fsp,conn);
2445 CHECK_WRITE(fsp);
2447 /* Deal with possible LARGE_WRITEX */
2448 if (large_writeX)
2449 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2451 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2452 END_PROFILE(SMBwriteX);
2453 return ERROR_DOS(ERRDOS,ERRbadmem);
2456 data = smb_base(inbuf) + smb_doff;
2458 if(CVAL(inbuf,smb_wct) == 14) {
2459 #ifdef LARGE_SMB_OFF_T
2461 * This is a large offset (64 bit) write.
2463 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2465 #else /* !LARGE_SMB_OFF_T */
2468 * Ensure we haven't been sent a >32 bit offset.
2471 if(IVAL(inbuf,smb_vwv12) != 0) {
2472 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2473 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2474 END_PROFILE(SMBwriteX);
2475 return ERROR_DOS(ERRDOS,ERRbadaccess);
2478 #endif /* LARGE_SMB_OFF_T */
2481 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2482 END_PROFILE(SMBwriteX);
2483 return ERROR_DOS(ERRDOS,ERRlock);
2486 /* X/Open SMB protocol says that, unlike SMBwrite
2487 if the length is zero then NO truncation is
2488 done, just a write of zero. To truncate a file,
2489 use SMBwrite. */
2491 if(numtowrite == 0)
2492 nwritten = 0;
2493 else
2494 nwritten = write_file(fsp,data,startpos,numtowrite);
2496 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2497 END_PROFILE(SMBwriteX);
2498 return(UNIXERROR(ERRHRD,ERRdiskfull));
2501 set_message(outbuf,6,0,True);
2503 SSVAL(outbuf,smb_vwv2,nwritten);
2504 if (large_writeX)
2505 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2507 if (nwritten < (ssize_t)numtowrite) {
2508 SCVAL(outbuf,smb_rcls,ERRHRD);
2509 SSVAL(outbuf,smb_err,ERRdiskfull);
2512 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2513 fsp->fnum, (int)numtowrite, (int)nwritten));
2515 if (lp_syncalways(SNUM(conn)) || write_through)
2516 sync_file(conn,fsp);
2518 END_PROFILE(SMBwriteX);
2519 return chain_reply(inbuf,outbuf,length,bufsize);
2522 /****************************************************************************
2523 Reply to a lseek.
2524 ****************************************************************************/
2526 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2528 SMB_OFF_T startpos;
2529 SMB_OFF_T res= -1;
2530 int mode,umode;
2531 int outsize = 0;
2532 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2533 START_PROFILE(SMBlseek);
2535 CHECK_FSP(fsp,conn);
2537 flush_write_cache(fsp, SEEK_FLUSH);
2539 mode = SVAL(inbuf,smb_vwv1) & 3;
2540 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
2541 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
2543 switch (mode) {
2544 case 0:
2545 umode = SEEK_SET;
2546 res = startpos;
2547 break;
2548 case 1:
2549 umode = SEEK_CUR;
2550 res = fsp->pos + startpos;
2551 break;
2552 case 2:
2553 umode = SEEK_END;
2554 break;
2555 default:
2556 umode = SEEK_SET;
2557 res = startpos;
2558 break;
2561 if (umode == SEEK_END) {
2562 if((res = SMB_VFS_LSEEK(fsp,fsp->fd,startpos,umode)) == -1) {
2563 if(errno == EINVAL) {
2564 SMB_OFF_T current_pos = startpos;
2565 SMB_STRUCT_STAT sbuf;
2567 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) {
2568 END_PROFILE(SMBlseek);
2569 return(UNIXERROR(ERRDOS,ERRnoaccess));
2572 current_pos += sbuf.st_size;
2573 if(current_pos < 0)
2574 res = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_SET);
2578 if(res == -1) {
2579 END_PROFILE(SMBlseek);
2580 return(UNIXERROR(ERRDOS,ERRnoaccess));
2584 fsp->pos = res;
2586 outsize = set_message(outbuf,2,0,True);
2587 SIVAL(outbuf,smb_vwv0,res);
2589 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2590 fsp->fnum, (double)startpos, (double)res, mode));
2592 END_PROFILE(SMBlseek);
2593 return(outsize);
2596 /****************************************************************************
2597 Reply to a flush.
2598 ****************************************************************************/
2600 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2602 int outsize = set_message(outbuf,0,0,True);
2603 uint16 fnum = SVAL(inbuf,smb_vwv0);
2604 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2605 START_PROFILE(SMBflush);
2607 if (fnum != 0xFFFF)
2608 CHECK_FSP(fsp,conn);
2610 if (!fsp) {
2611 file_sync_all(conn);
2612 } else {
2613 sync_file(conn,fsp);
2616 DEBUG(3,("flush\n"));
2617 END_PROFILE(SMBflush);
2618 return(outsize);
2621 /****************************************************************************
2622 Reply to a exit.
2623 ****************************************************************************/
2625 int reply_exit(connection_struct *conn,
2626 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2628 int outsize;
2629 START_PROFILE(SMBexit);
2631 file_close_pid(SVAL(inbuf,smb_pid));
2633 outsize = set_message(outbuf,0,0,True);
2635 DEBUG(3,("exit\n"));
2637 END_PROFILE(SMBexit);
2638 return(outsize);
2641 /****************************************************************************
2642 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2643 ****************************************************************************/
2645 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2646 int dum_buffsize)
2648 extern struct current_user current_user;
2649 int outsize = 0;
2650 time_t mtime;
2651 int32 eclass = 0, err = 0;
2652 files_struct *fsp = NULL;
2653 START_PROFILE(SMBclose);
2655 outsize = set_message(outbuf,0,0,True);
2657 /* If it's an IPC, pass off to the pipe handler. */
2658 if (IS_IPC(conn)) {
2659 END_PROFILE(SMBclose);
2660 return reply_pipe_close(conn, inbuf,outbuf);
2663 fsp = file_fsp(inbuf,smb_vwv0);
2666 * We can only use CHECK_FSP if we know it's not a directory.
2669 if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
2670 END_PROFILE(SMBclose);
2671 return ERROR_DOS(ERRDOS,ERRbadfid);
2674 if(fsp->is_directory) {
2676 * Special case - close NT SMB directory handle.
2678 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2679 close_file(fsp,True);
2680 } else {
2682 * Close ordinary file.
2684 int close_err;
2685 pstring file_name;
2687 /* Save the name for time set in close. */
2688 pstrcpy( file_name, fsp->fsp_name);
2690 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2691 fsp->fd, fsp->fnum,
2692 conn->num_files_open));
2695 * close_file() returns the unix errno if an error
2696 * was detected on close - normally this is due to
2697 * a disk full error. If not then it was probably an I/O error.
2700 if((close_err = close_file(fsp,True)) != 0) {
2701 errno = close_err;
2702 END_PROFILE(SMBclose);
2703 return (UNIXERROR(ERRHRD,ERRgeneral));
2707 * Now take care of any time sent in the close.
2710 mtime = make_unix_date3(inbuf+smb_vwv1);
2712 /* try and set the date */
2713 set_filetime(conn, file_name, mtime);
2717 /* We have a cached error */
2718 if(eclass || err) {
2719 END_PROFILE(SMBclose);
2720 return ERROR_DOS(eclass,err);
2723 END_PROFILE(SMBclose);
2724 return(outsize);
2727 /****************************************************************************
2728 Reply to a writeclose (Core+ protocol).
2729 ****************************************************************************/
2731 int reply_writeclose(connection_struct *conn,
2732 char *inbuf,char *outbuf, int size, int dum_buffsize)
2734 size_t numtowrite;
2735 ssize_t nwritten = -1;
2736 int outsize = 0;
2737 int close_err = 0;
2738 SMB_OFF_T startpos;
2739 char *data;
2740 time_t mtime;
2741 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2742 START_PROFILE(SMBwriteclose);
2744 CHECK_FSP(fsp,conn);
2745 CHECK_WRITE(fsp);
2747 numtowrite = SVAL(inbuf,smb_vwv1);
2748 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2749 mtime = make_unix_date3(inbuf+smb_vwv4);
2750 data = smb_buf(inbuf) + 1;
2752 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2753 END_PROFILE(SMBwriteclose);
2754 return ERROR_DOS(ERRDOS,ERRlock);
2757 nwritten = write_file(fsp,data,startpos,numtowrite);
2759 set_filetime(conn, fsp->fsp_name,mtime);
2762 * More insanity. W2K only closes the file if writelen > 0.
2763 * JRA.
2766 if (numtowrite) {
2767 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
2768 fsp->fsp_name ));
2769 close_err = close_file(fsp,True);
2772 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2773 fsp->fnum, (int)numtowrite, (int)nwritten,
2774 conn->num_files_open));
2776 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2777 END_PROFILE(SMBwriteclose);
2778 return(UNIXERROR(ERRHRD,ERRdiskfull));
2781 if(close_err != 0) {
2782 errno = close_err;
2783 END_PROFILE(SMBwriteclose);
2784 return(UNIXERROR(ERRHRD,ERRgeneral));
2787 outsize = set_message(outbuf,1,0,True);
2789 SSVAL(outbuf,smb_vwv0,nwritten);
2790 END_PROFILE(SMBwriteclose);
2791 return(outsize);
2794 /****************************************************************************
2795 Reply to a lock.
2796 ****************************************************************************/
2798 int reply_lock(connection_struct *conn,
2799 char *inbuf,char *outbuf, int length, int dum_buffsize)
2801 int outsize = set_message(outbuf,0,0,True);
2802 SMB_BIG_UINT count,offset;
2803 NTSTATUS status;
2804 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2805 BOOL my_lock_ctx = False;
2807 START_PROFILE(SMBlock);
2809 CHECK_FSP(fsp,conn);
2811 release_level_2_oplocks_on_change(fsp);
2813 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2814 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2816 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2817 fsp->fd, fsp->fnum, (double)offset, (double)count));
2819 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &my_lock_ctx);
2820 if (NT_STATUS_V(status)) {
2821 #if 0
2822 /* Tests using Samba4 against W2K show this call never creates a blocking lock. */
2823 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
2825 * A blocking lock was requested. Package up
2826 * this smb into a queued request and push it
2827 * onto the blocking lock queue.
2829 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), offset, count)) {
2830 END_PROFILE(SMBlock);
2831 return -1;
2834 #endif
2835 END_PROFILE(SMBlock);
2836 return ERROR_NT(status);
2839 END_PROFILE(SMBlock);
2840 return(outsize);
2843 /****************************************************************************
2844 Reply to a unlock.
2845 ****************************************************************************/
2847 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
2848 int dum_buffsize)
2850 int outsize = set_message(outbuf,0,0,True);
2851 SMB_BIG_UINT count,offset;
2852 NTSTATUS status;
2853 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2854 START_PROFILE(SMBunlock);
2856 CHECK_FSP(fsp,conn);
2858 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2859 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2861 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
2862 if (NT_STATUS_V(status)) {
2863 END_PROFILE(SMBunlock);
2864 return ERROR_NT(status);
2867 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2868 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
2870 END_PROFILE(SMBunlock);
2871 return(outsize);
2874 /****************************************************************************
2875 Reply to a tdis.
2876 ****************************************************************************/
2878 int reply_tdis(connection_struct *conn,
2879 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2881 int outsize = set_message(outbuf,0,0,True);
2882 uint16 vuid;
2883 START_PROFILE(SMBtdis);
2885 vuid = SVAL(inbuf,smb_uid);
2887 if (!conn) {
2888 DEBUG(4,("Invalid connection in tdis\n"));
2889 END_PROFILE(SMBtdis);
2890 return ERROR_DOS(ERRSRV,ERRinvnid);
2893 conn->used = False;
2895 close_cnum(conn,vuid);
2897 END_PROFILE(SMBtdis);
2898 return outsize;
2901 /****************************************************************************
2902 Reply to a echo.
2903 ****************************************************************************/
2905 int reply_echo(connection_struct *conn,
2906 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2908 int smb_reverb = SVAL(inbuf,smb_vwv0);
2909 int seq_num;
2910 unsigned int data_len = smb_buflen(inbuf);
2911 int outsize = set_message(outbuf,1,data_len,True);
2912 START_PROFILE(SMBecho);
2914 if (data_len > BUFFER_SIZE) {
2915 DEBUG(0,("reply_echo: data_len too large.\n"));
2916 END_PROFILE(SMBecho);
2917 return -1;
2920 /* copy any incoming data back out */
2921 if (data_len > 0)
2922 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2924 if (smb_reverb > 100) {
2925 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2926 smb_reverb = 100;
2929 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
2930 SSVAL(outbuf,smb_vwv0,seq_num);
2932 smb_setlen(outbuf,outsize - 4);
2934 if (!send_smb(smbd_server_fd(),outbuf))
2935 exit_server("reply_echo: send_smb failed.");
2938 DEBUG(3,("echo %d times\n", smb_reverb));
2940 smb_echo_count++;
2942 END_PROFILE(SMBecho);
2943 return -1;
2946 /****************************************************************************
2947 Reply to a printopen.
2948 ****************************************************************************/
2950 int reply_printopen(connection_struct *conn,
2951 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2953 int outsize = 0;
2954 files_struct *fsp;
2955 START_PROFILE(SMBsplopen);
2957 if (!CAN_PRINT(conn)) {
2958 END_PROFILE(SMBsplopen);
2959 return ERROR_DOS(ERRDOS,ERRnoaccess);
2962 /* Open for exclusive use, write only. */
2963 fsp = print_fsp_open(conn, NULL);
2965 if (!fsp) {
2966 END_PROFILE(SMBsplopen);
2967 return(UNIXERROR(ERRDOS,ERRnoaccess));
2970 outsize = set_message(outbuf,1,0,True);
2971 SSVAL(outbuf,smb_vwv0,fsp->fnum);
2973 DEBUG(3,("openprint fd=%d fnum=%d\n",
2974 fsp->fd, fsp->fnum));
2976 END_PROFILE(SMBsplopen);
2977 return(outsize);
2980 /****************************************************************************
2981 Reply to a printclose.
2982 ****************************************************************************/
2984 int reply_printclose(connection_struct *conn,
2985 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2987 int outsize = set_message(outbuf,0,0,True);
2988 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2989 int close_err = 0;
2990 START_PROFILE(SMBsplclose);
2992 CHECK_FSP(fsp,conn);
2994 if (!CAN_PRINT(conn)) {
2995 END_PROFILE(SMBsplclose);
2996 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
2999 DEBUG(3,("printclose fd=%d fnum=%d\n",
3000 fsp->fd,fsp->fnum));
3002 close_err = close_file(fsp,True);
3004 if(close_err != 0) {
3005 errno = close_err;
3006 END_PROFILE(SMBsplclose);
3007 return(UNIXERROR(ERRHRD,ERRgeneral));
3010 END_PROFILE(SMBsplclose);
3011 return(outsize);
3014 /****************************************************************************
3015 Reply to a printqueue.
3016 ****************************************************************************/
3018 int reply_printqueue(connection_struct *conn,
3019 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3021 int outsize = set_message(outbuf,2,3,True);
3022 int max_count = SVAL(inbuf,smb_vwv0);
3023 int start_index = SVAL(inbuf,smb_vwv1);
3024 START_PROFILE(SMBsplretq);
3026 /* we used to allow the client to get the cnum wrong, but that
3027 is really quite gross and only worked when there was only
3028 one printer - I think we should now only accept it if they
3029 get it right (tridge) */
3030 if (!CAN_PRINT(conn)) {
3031 END_PROFILE(SMBsplretq);
3032 return ERROR_DOS(ERRDOS,ERRnoaccess);
3035 SSVAL(outbuf,smb_vwv0,0);
3036 SSVAL(outbuf,smb_vwv1,0);
3037 SCVAL(smb_buf(outbuf),0,1);
3038 SSVAL(smb_buf(outbuf),1,0);
3040 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3041 start_index, max_count));
3044 print_queue_struct *queue = NULL;
3045 print_status_struct status;
3046 char *p = smb_buf(outbuf) + 3;
3047 int count = print_queue_status(SNUM(conn), &queue, &status);
3048 int num_to_get = ABS(max_count);
3049 int first = (max_count>0?start_index:start_index+max_count+1);
3050 int i;
3052 if (first >= count)
3053 num_to_get = 0;
3054 else
3055 num_to_get = MIN(num_to_get,count-first);
3058 for (i=first;i<first+num_to_get;i++) {
3059 put_dos_date2(p,0,queue[i].time);
3060 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
3061 SSVAL(p,5, queue[i].job);
3062 SIVAL(p,7,queue[i].size);
3063 SCVAL(p,11,0);
3064 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
3065 p += 28;
3068 if (count > 0) {
3069 outsize = set_message(outbuf,2,28*count+3,False);
3070 SSVAL(outbuf,smb_vwv0,count);
3071 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3072 SCVAL(smb_buf(outbuf),0,1);
3073 SSVAL(smb_buf(outbuf),1,28*count);
3076 SAFE_FREE(queue);
3078 DEBUG(3,("%d entries returned in queue\n",count));
3081 END_PROFILE(SMBsplretq);
3082 return(outsize);
3085 /****************************************************************************
3086 Reply to a printwrite.
3087 ****************************************************************************/
3089 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3091 int numtowrite;
3092 int outsize = set_message(outbuf,0,0,True);
3093 char *data;
3094 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3096 START_PROFILE(SMBsplwr);
3098 if (!CAN_PRINT(conn)) {
3099 END_PROFILE(SMBsplwr);
3100 return ERROR_DOS(ERRDOS,ERRnoaccess);
3103 CHECK_FSP(fsp,conn);
3104 CHECK_WRITE(fsp);
3106 numtowrite = SVAL(smb_buf(inbuf),1);
3107 data = smb_buf(inbuf) + 3;
3109 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3110 END_PROFILE(SMBsplwr);
3111 return(UNIXERROR(ERRHRD,ERRdiskfull));
3114 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3116 END_PROFILE(SMBsplwr);
3117 return(outsize);
3120 /****************************************************************************
3121 The guts of the mkdir command, split out so it may be called by the NT SMB
3122 code.
3123 ****************************************************************************/
3125 NTSTATUS mkdir_internal(connection_struct *conn, pstring directory)
3127 BOOL bad_path = False;
3128 SMB_STRUCT_STAT sbuf;
3129 int ret= -1;
3131 unix_convert(directory,conn,0,&bad_path,&sbuf);
3133 if( strchr_m(directory, ':')) {
3134 return NT_STATUS_NOT_A_DIRECTORY;
3137 if (ms_has_wild(directory)) {
3138 return NT_STATUS_OBJECT_NAME_INVALID;
3141 if (check_name(directory, conn))
3142 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory));
3144 if (ret == -1) {
3145 if(errno == ENOENT) {
3146 if (bad_path)
3147 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3148 else
3149 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3151 return map_nt_error_from_unix(errno);
3154 return NT_STATUS_OK;
3157 /****************************************************************************
3158 Reply to a mkdir.
3159 ****************************************************************************/
3161 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3163 pstring directory;
3164 int outsize;
3165 NTSTATUS status;
3166 START_PROFILE(SMBmkdir);
3168 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
3169 if (!NT_STATUS_IS_OK(status)) {
3170 END_PROFILE(SMBmkdir);
3171 return ERROR_NT(status);
3174 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
3176 status = mkdir_internal(conn, directory);
3177 if (!NT_STATUS_IS_OK(status)) {
3178 END_PROFILE(SMBmkdir);
3179 return ERROR_NT(status);
3182 outsize = set_message(outbuf,0,0,True);
3184 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3186 END_PROFILE(SMBmkdir);
3187 return(outsize);
3190 /****************************************************************************
3191 Static function used by reply_rmdir to delete an entire directory
3192 tree recursively. Return False on ok, True on fail.
3193 ****************************************************************************/
3195 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3197 const char *dname = NULL;
3198 BOOL ret = False;
3199 void *dirptr = OpenDir(conn, directory, False);
3201 if(dirptr == NULL)
3202 return True;
3204 while((dname = ReadDirName(dirptr))) {
3205 pstring fullname;
3206 SMB_STRUCT_STAT st;
3208 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3209 continue;
3211 /* Construct the full name. */
3212 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3213 errno = ENOMEM;
3214 ret = True;
3215 break;
3218 pstrcpy(fullname, directory);
3219 pstrcat(fullname, "/");
3220 pstrcat(fullname, dname);
3222 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
3223 ret = True;
3224 break;
3227 if(st.st_mode & S_IFDIR) {
3228 if(recursive_rmdir(conn, fullname)!=0) {
3229 ret = True;
3230 break;
3232 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
3233 ret = True;
3234 break;
3236 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
3237 ret = True;
3238 break;
3241 CloseDir(dirptr);
3242 return ret;
3245 /****************************************************************************
3246 The internals of the rmdir code - called elsewhere.
3247 ****************************************************************************/
3249 BOOL rmdir_internals(connection_struct *conn, char *directory)
3251 BOOL ok;
3253 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3254 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3256 * Check to see if the only thing in this directory are
3257 * vetoed files/directories. If so then delete them and
3258 * retry. If we fail to delete any of them (and we *don't*
3259 * do a recursive delete) then fail the rmdir.
3261 BOOL all_veto_files = True;
3262 const char *dname;
3263 void *dirptr = OpenDir(conn, directory, False);
3265 if(dirptr != NULL) {
3266 int dirpos = TellDir(dirptr);
3267 while ((dname = ReadDirName(dirptr))) {
3268 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3269 continue;
3270 if(!IS_VETO_PATH(conn, dname)) {
3271 all_veto_files = False;
3272 break;
3276 if(all_veto_files) {
3277 SeekDir(dirptr,dirpos);
3278 while ((dname = ReadDirName(dirptr))) {
3279 pstring fullname;
3280 SMB_STRUCT_STAT st;
3282 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3283 continue;
3285 /* Construct the full name. */
3286 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3287 errno = ENOMEM;
3288 break;
3291 pstrcpy(fullname, directory);
3292 pstrcat(fullname, "/");
3293 pstrcat(fullname, dname);
3295 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
3296 break;
3297 if(st.st_mode & S_IFDIR) {
3298 if(lp_recursive_veto_delete(SNUM(conn))) {
3299 if(recursive_rmdir(conn, fullname) != 0)
3300 break;
3302 if(SMB_VFS_RMDIR(conn,fullname) != 0)
3303 break;
3304 } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
3305 break;
3307 CloseDir(dirptr);
3308 /* Retry the rmdir */
3309 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3310 } else {
3311 CloseDir(dirptr);
3313 } else {
3314 errno = ENOTEMPTY;
3318 if (!ok)
3319 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
3321 return ok;
3324 /****************************************************************************
3325 Reply to a rmdir.
3326 ****************************************************************************/
3328 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3330 pstring directory;
3331 int outsize = 0;
3332 BOOL ok = False;
3333 BOOL bad_path = False;
3334 SMB_STRUCT_STAT sbuf;
3335 NTSTATUS status;
3336 START_PROFILE(SMBrmdir);
3338 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
3339 if (!NT_STATUS_IS_OK(status)) {
3340 END_PROFILE(SMBrmdir);
3341 return ERROR_NT(status);
3344 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3346 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3348 if (check_name(directory,conn)) {
3349 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3350 ok = rmdir_internals(conn, directory);
3353 if (!ok) {
3354 END_PROFILE(SMBrmdir);
3355 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRbadpath);
3358 outsize = set_message(outbuf,0,0,True);
3360 DEBUG( 3, ( "rmdir %s\n", directory ) );
3362 END_PROFILE(SMBrmdir);
3363 return(outsize);
3366 /*******************************************************************
3367 Resolve wildcards in a filename rename.
3368 Note that name is in UNIX charset and thus potentially can be more
3369 than fstring buffer (255 bytes) especially in default UTF-8 case.
3370 Therefore, we use pstring inside and all calls should ensure that
3371 name2 is at least pstring-long (they do already)
3372 ********************************************************************/
3374 static BOOL resolve_wildcards(const char *name1, char *name2)
3376 pstring root1,root2;
3377 pstring ext1,ext2;
3378 char *p,*p2, *pname1, *pname2;
3379 int available_space, actual_space;
3382 pname1 = strrchr_m(name1,'/');
3383 pname2 = strrchr_m(name2,'/');
3385 if (!pname1 || !pname2)
3386 return(False);
3388 pstrcpy(root1,pname1);
3389 pstrcpy(root2,pname2);
3390 p = strrchr_m(root1,'.');
3391 if (p) {
3392 *p = 0;
3393 pstrcpy(ext1,p+1);
3394 } else {
3395 pstrcpy(ext1,"");
3397 p = strrchr_m(root2,'.');
3398 if (p) {
3399 *p = 0;
3400 pstrcpy(ext2,p+1);
3401 } else {
3402 pstrcpy(ext2,"");
3405 p = root1;
3406 p2 = root2;
3407 while (*p2) {
3408 if (*p2 == '?') {
3409 *p2 = *p;
3410 p2++;
3411 } else {
3412 p2++;
3414 if (*p)
3415 p++;
3418 p = ext1;
3419 p2 = ext2;
3420 while (*p2) {
3421 if (*p2 == '?') {
3422 *p2 = *p;
3423 p2++;
3424 } else {
3425 p2++;
3427 if (*p)
3428 p++;
3431 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
3433 if (ext2[0]) {
3434 actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
3435 if (actual_space >= available_space - 1) {
3436 DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
3437 actual_space - available_space));
3439 } else {
3440 pstrcpy_base(pname2, root2, name2);
3443 return(True);
3446 /****************************************************************************
3447 Ensure open files have their names updates.
3448 ****************************************************************************/
3450 static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode, char *newname)
3452 files_struct *fsp;
3453 BOOL did_rename = False;
3455 for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
3456 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
3457 fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
3458 fsp->fsp_name, newname ));
3459 string_set(&fsp->fsp_name, newname);
3460 did_rename = True;
3463 if (!did_rename)
3464 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
3465 (unsigned int)dev, (double)inode, newname ));
3468 /****************************************************************************
3469 Rename an open file - given an fsp.
3470 ****************************************************************************/
3472 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, BOOL replace_if_exists)
3474 SMB_STRUCT_STAT sbuf;
3475 BOOL bad_path = False;
3476 pstring newname_last_component;
3477 NTSTATUS error = NT_STATUS_OK;
3478 BOOL dest_exists;
3479 BOOL rcdest = True;
3481 ZERO_STRUCT(sbuf);
3482 rcdest = unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf);
3484 /* Quick check for "." and ".." */
3485 if (!bad_path && newname_last_component[0] == '.') {
3486 if (!newname_last_component[1] || (newname_last_component[1] == '.' && !newname_last_component[2])) {
3487 return NT_STATUS_ACCESS_DENIED;
3490 if (!rcdest && bad_path) {
3491 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3494 /* Ensure newname contains a '/' */
3495 if(strrchr_m(newname,'/') == 0) {
3496 pstring tmpstr;
3498 pstrcpy(tmpstr, "./");
3499 pstrcat(tmpstr, newname);
3500 pstrcpy(newname, tmpstr);
3504 * Check for special case with case preserving and not
3505 * case sensitive. If the old last component differs from the original
3506 * last component only by case, then we should allow
3507 * the rename (user is trying to change the case of the
3508 * filename).
3511 if((case_sensitive == False) && (case_preserve == True) &&
3512 strequal(newname, fsp->fsp_name)) {
3513 char *p;
3514 pstring newname_modified_last_component;
3517 * Get the last component of the modified name.
3518 * Note that we guarantee that newname contains a '/'
3519 * character above.
3521 p = strrchr_m(newname,'/');
3522 pstrcpy(newname_modified_last_component,p+1);
3524 if(strcsequal(newname_modified_last_component,
3525 newname_last_component) == False) {
3527 * Replace the modified last component with
3528 * the original.
3530 pstrcpy(p+1, newname_last_component);
3535 * If the src and dest names are identical - including case,
3536 * don't do the rename, just return success.
3539 if (strcsequal(fsp->fsp_name, newname)) {
3540 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
3541 newname));
3542 return NT_STATUS_OK;
3545 dest_exists = vfs_object_exist(conn,newname,NULL);
3547 if(!replace_if_exists && dest_exists) {
3548 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
3549 fsp->fsp_name,newname));
3550 return NT_STATUS_OBJECT_NAME_COLLISION;
3553 error = can_rename(newname,conn,&sbuf);
3555 if (dest_exists && !NT_STATUS_IS_OK(error)) {
3556 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3557 nt_errstr(error), fsp->fsp_name,newname));
3558 if (NT_STATUS_EQUAL(error,NT_STATUS_SHARING_VIOLATION))
3559 error = NT_STATUS_ACCESS_DENIED;
3560 return error;
3563 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
3564 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
3565 fsp->fsp_name,newname));
3566 rename_open_files(conn, fsp->dev, fsp->inode, newname);
3567 return NT_STATUS_OK;
3570 if (errno == ENOTDIR || errno == EISDIR)
3571 error = NT_STATUS_OBJECT_NAME_COLLISION;
3572 else
3573 error = map_nt_error_from_unix(errno);
3575 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
3576 nt_errstr(error), fsp->fsp_name,newname));
3578 return error;
3581 /****************************************************************************
3582 The guts of the rename command, split out so it may be called by the NT SMB
3583 code.
3584 ****************************************************************************/
3586 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, uint16 attrs, BOOL replace_if_exists)
3588 pstring directory;
3589 pstring mask;
3590 pstring last_component_src;
3591 pstring last_component_dest;
3592 char *p;
3593 BOOL has_wild;
3594 BOOL bad_path_src = False;
3595 BOOL bad_path_dest = False;
3596 int count=0;
3597 NTSTATUS error = NT_STATUS_OK;
3598 BOOL rc = True;
3599 BOOL rcdest = True;
3600 SMB_STRUCT_STAT sbuf1, sbuf2;
3602 *directory = *mask = 0;
3604 ZERO_STRUCT(sbuf1);
3605 ZERO_STRUCT(sbuf2);
3607 rc = unix_convert(name,conn,last_component_src,&bad_path_src,&sbuf1);
3608 if (!rc && bad_path_src) {
3609 if (ms_has_wild(last_component_src))
3610 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3611 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3614 /* Quick check for "." and ".." */
3615 if (last_component_src[0] == '.') {
3616 if (!last_component_src[1] || (last_component_src[1] == '.' && !last_component_src[2])) {
3617 return NT_STATUS_OBJECT_NAME_INVALID;
3621 rcdest = unix_convert(newname,conn,last_component_dest,&bad_path_dest,&sbuf2);
3623 /* Quick check for "." and ".." */
3624 if (last_component_dest[0] == '.') {
3625 if (!last_component_dest[1] || (last_component_dest[1] == '.' && !last_component_dest[2])) {
3626 return NT_STATUS_OBJECT_NAME_INVALID;
3631 * Split the old name into directory and last component
3632 * strings. Note that unix_convert may have stripped off a
3633 * leading ./ from both name and newname if the rename is
3634 * at the root of the share. We need to make sure either both
3635 * name and newname contain a / character or neither of them do
3636 * as this is checked in resolve_wildcards().
3639 p = strrchr_m(name,'/');
3640 if (!p) {
3641 pstrcpy(directory,".");
3642 pstrcpy(mask,name);
3643 } else {
3644 *p = 0;
3645 pstrcpy(directory,name);
3646 pstrcpy(mask,p+1);
3647 *p = '/'; /* Replace needed for exceptional test below. */
3651 * We should only check the mangled cache
3652 * here if unix_convert failed. This means
3653 * that the path in 'mask' doesn't exist
3654 * on the file system and so we need to look
3655 * for a possible mangle. This patch from
3656 * Tine Smukavec <valentin.smukavec@hermes.si>.
3659 if (!rc && mangle_is_mangled(mask))
3660 mangle_check_cache( mask );
3662 has_wild = ms_has_wild(mask);
3664 if (!has_wild) {
3666 * No wildcards - just process the one file.
3668 BOOL is_short_name = mangle_is_8_3(name, True);
3670 /* Add a terminating '/' to the directory name. */
3671 pstrcat(directory,"/");
3672 pstrcat(directory,mask);
3674 /* Ensure newname contains a '/' also */
3675 if(strrchr_m(newname,'/') == 0) {
3676 pstring tmpstr;
3678 pstrcpy(tmpstr, "./");
3679 pstrcat(tmpstr, newname);
3680 pstrcpy(newname, tmpstr);
3683 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
3684 directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
3685 case_sensitive, case_preserve, short_case_preserve, directory,
3686 newname, last_component_dest, is_short_name));
3689 * Check for special case with case preserving and not
3690 * case sensitive, if directory and newname are identical,
3691 * and the old last component differs from the original
3692 * last component only by case, then we should allow
3693 * the rename (user is trying to change the case of the
3694 * filename).
3696 if((case_sensitive == False) &&
3697 (((case_preserve == True) &&
3698 (is_short_name == False)) ||
3699 ((short_case_preserve == True) &&
3700 (is_short_name == True))) &&
3701 strcsequal(directory, newname)) {
3702 pstring modified_last_component;
3705 * Get the last component of the modified name.
3706 * Note that we guarantee that newname contains a '/'
3707 * character above.
3709 p = strrchr_m(newname,'/');
3710 pstrcpy(modified_last_component,p+1);
3712 if(strcsequal(modified_last_component,
3713 last_component_dest) == False) {
3715 * Replace the modified last component with
3716 * the original.
3718 pstrcpy(p+1, last_component_dest);
3722 resolve_wildcards(directory,newname);
3725 * The source object must exist.
3728 if (!vfs_object_exist(conn, directory, &sbuf1)) {
3729 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
3730 directory,newname));
3732 if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
3734 * Must return different errors depending on whether the parent
3735 * directory existed or not.
3738 p = strrchr_m(directory, '/');
3739 if (!p)
3740 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3741 *p = '\0';
3742 if (vfs_object_exist(conn, directory, NULL))
3743 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3744 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3746 error = map_nt_error_from_unix(errno);
3747 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3748 nt_errstr(error), directory,newname));
3750 return error;
3753 if (!rcdest && bad_path_dest) {
3754 if (ms_has_wild(last_component_dest))
3755 return NT_STATUS_OBJECT_NAME_INVALID;
3756 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3759 error = can_rename(directory,conn,&sbuf1);
3761 if (!NT_STATUS_IS_OK(error)) {
3762 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3763 nt_errstr(error), directory,newname));
3764 return error;
3768 * If the src and dest names are identical - including case,
3769 * don't do the rename, just return success.
3772 if (strcsequal(directory, newname)) {
3773 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3774 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
3775 return NT_STATUS_OK;
3778 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
3779 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
3780 directory,newname));
3781 return NT_STATUS_OBJECT_NAME_COLLISION;
3784 if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
3785 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
3786 directory,newname));
3787 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3788 return NT_STATUS_OK;
3791 if (errno == ENOTDIR || errno == EISDIR)
3792 error = NT_STATUS_OBJECT_NAME_COLLISION;
3793 else
3794 error = map_nt_error_from_unix(errno);
3796 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3797 nt_errstr(error), directory,newname));
3799 return error;
3800 } else {
3802 * Wildcards - process each file that matches.
3804 void *dirptr = NULL;
3805 const char *dname;
3806 pstring destname;
3808 if (check_name(directory,conn))
3809 dirptr = OpenDir(conn, directory, True);
3811 if (dirptr) {
3812 error = NT_STATUS_NO_SUCH_FILE;
3813 /* Was error = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */
3815 if (strequal(mask,"????????.???"))
3816 pstrcpy(mask,"*");
3818 while ((dname = ReadDirName(dirptr))) {
3819 pstring fname;
3820 BOOL sysdir_entry = False;
3822 pstrcpy(fname,dname);
3824 /* Quick check for "." and ".." */
3825 if (fname[0] == '.') {
3826 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
3827 if (attrs & aDIR) {
3828 sysdir_entry = True;
3829 } else {
3830 continue;
3835 if(!mask_match(fname, mask, case_sensitive))
3836 continue;
3838 if (sysdir_entry) {
3839 error = NT_STATUS_OBJECT_NAME_INVALID;
3840 continue;
3843 error = NT_STATUS_ACCESS_DENIED;
3844 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3845 if (!vfs_object_exist(conn, fname, &sbuf1)) {
3846 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3847 DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
3848 continue;
3850 error = can_rename(fname,conn,&sbuf1);
3851 if (!NT_STATUS_IS_OK(error)) {
3852 DEBUG(6,("rename %s refused\n", fname));
3853 continue;
3855 pstrcpy(destname,newname);
3857 if (!resolve_wildcards(fname,destname)) {
3858 DEBUG(6,("resolve_wildcards %s %s failed\n",
3859 fname, destname));
3860 continue;
3863 if (strcsequal(fname,destname)) {
3864 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3865 DEBUG(3,("rename_internals: identical names in wildcard rename %s - success\n", fname));
3866 count++;
3867 error = NT_STATUS_OK;
3868 continue;
3871 if (!replace_if_exists &&
3872 vfs_file_exist(conn,destname, NULL)) {
3873 DEBUG(6,("file_exist %s\n", destname));
3874 error = NT_STATUS_OBJECT_NAME_COLLISION;
3875 continue;
3878 if (!SMB_VFS_RENAME(conn,fname,destname)) {
3879 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3880 count++;
3881 error = NT_STATUS_OK;
3883 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3885 CloseDir(dirptr);
3888 if (!NT_STATUS_EQUAL(error,NT_STATUS_NO_SUCH_FILE)) {
3889 if (!rcdest && bad_path_dest) {
3890 if (ms_has_wild(last_component_dest))
3891 return NT_STATUS_OBJECT_NAME_INVALID;
3892 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3897 if (count == 0 && NT_STATUS_IS_OK(error)) {
3898 error = map_nt_error_from_unix(errno);
3901 return error;
3904 /****************************************************************************
3905 Reply to a mv.
3906 ****************************************************************************/
3908 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
3909 int dum_buffsize)
3911 int outsize = 0;
3912 pstring name;
3913 pstring newname;
3914 char *p;
3915 uint16 attrs = SVAL(inbuf,smb_vwv0);
3916 NTSTATUS status;
3918 START_PROFILE(SMBmv);
3920 p = smb_buf(inbuf) + 1;
3921 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status);
3922 if (!NT_STATUS_IS_OK(status)) {
3923 END_PROFILE(SMBmv);
3924 return ERROR_NT(status);
3926 p++;
3927 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status);
3928 if (!NT_STATUS_IS_OK(status)) {
3929 END_PROFILE(SMBmv);
3930 return ERROR_NT(status);
3933 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3934 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3936 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3938 status = rename_internals(conn, name, newname, attrs, False);
3939 if (!NT_STATUS_IS_OK(status)) {
3940 END_PROFILE(SMBmv);
3941 return ERROR_NT(status);
3945 * Win2k needs a changenotify request response before it will
3946 * update after a rename..
3948 process_pending_change_notify_queue((time_t)0);
3949 outsize = set_message(outbuf,0,0,True);
3951 END_PROFILE(SMBmv);
3952 return(outsize);
3955 /*******************************************************************
3956 Copy a file as part of a reply_copy.
3957 ******************************************************************/
3959 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3960 int count,BOOL target_is_directory, int *err_ret)
3962 int Access,action;
3963 SMB_STRUCT_STAT src_sbuf, sbuf2;
3964 SMB_OFF_T ret=-1;
3965 files_struct *fsp1,*fsp2;
3966 pstring dest;
3967 uint32 dosattrs;
3969 *err_ret = 0;
3971 pstrcpy(dest,dest1);
3972 if (target_is_directory) {
3973 char *p = strrchr_m(src,'/');
3974 if (p)
3975 p++;
3976 else
3977 p = src;
3978 pstrcat(dest,"/");
3979 pstrcat(dest,p);
3982 if (!vfs_file_exist(conn,src,&src_sbuf))
3983 return(False);
3985 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
3986 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),FILE_ATTRIBUTE_NORMAL,0,&Access,&action);
3988 if (!fsp1)
3989 return(False);
3991 if (!target_is_directory && count)
3992 ofun = FILE_EXISTS_OPEN;
3994 dosattrs = dos_mode(conn, src, &src_sbuf);
3995 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1)
3996 ZERO_STRUCTP(&sbuf2);
3998 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
3999 ofun,dosattrs,0,&Access,&action);
4001 if (!fsp2) {
4002 close_file(fsp1,False);
4003 return(False);
4006 if ((ofun&3) == 1) {
4007 if(SMB_VFS_LSEEK(fsp2,fsp2->fd,0,SEEK_END) == -1) {
4008 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
4010 * Stop the copy from occurring.
4012 ret = -1;
4013 src_sbuf.st_size = 0;
4017 if (src_sbuf.st_size)
4018 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
4020 close_file(fsp1,False);
4022 /* Ensure the modtime is set correctly on the destination file. */
4023 fsp2->pending_modtime = src_sbuf.st_mtime;
4026 * As we are opening fsp1 read-only we only expect
4027 * an error on close on fsp2 if we are out of space.
4028 * Thus we don't look at the error return from the
4029 * close of fsp1.
4031 *err_ret = close_file(fsp2,False);
4033 return(ret == (SMB_OFF_T)src_sbuf.st_size);
4036 /****************************************************************************
4037 Reply to a file copy.
4038 ****************************************************************************/
4040 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4042 int outsize = 0;
4043 pstring name;
4044 pstring directory;
4045 pstring mask,newname;
4046 char *p;
4047 int count=0;
4048 int error = ERRnoaccess;
4049 int err = 0;
4050 BOOL has_wild;
4051 BOOL exists=False;
4052 int tid2 = SVAL(inbuf,smb_vwv0);
4053 int ofun = SVAL(inbuf,smb_vwv1);
4054 int flags = SVAL(inbuf,smb_vwv2);
4055 BOOL target_is_directory=False;
4056 BOOL bad_path1 = False;
4057 BOOL bad_path2 = False;
4058 BOOL rc = True;
4059 SMB_STRUCT_STAT sbuf1, sbuf2;
4060 NTSTATUS status;
4062 START_PROFILE(SMBcopy);
4064 *directory = *mask = 0;
4066 p = smb_buf(inbuf);
4067 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status);
4068 if (!NT_STATUS_IS_OK(status)) {
4069 END_PROFILE(SMBcopy);
4070 return ERROR_NT(status);
4072 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status);
4073 if (!NT_STATUS_IS_OK(status)) {
4074 END_PROFILE(SMBcopy);
4075 return ERROR_NT(status);
4078 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
4080 if (tid2 != conn->cnum) {
4081 /* can't currently handle inter share copies XXXX */
4082 DEBUG(3,("Rejecting inter-share copy\n"));
4083 END_PROFILE(SMBcopy);
4084 return ERROR_DOS(ERRSRV,ERRinvdevice);
4087 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
4088 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4090 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
4091 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
4093 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
4095 if ((flags&1) && target_is_directory) {
4096 END_PROFILE(SMBcopy);
4097 return ERROR_DOS(ERRDOS,ERRbadfile);
4100 if ((flags&2) && !target_is_directory) {
4101 END_PROFILE(SMBcopy);
4102 return ERROR_DOS(ERRDOS,ERRbadpath);
4105 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
4106 /* wants a tree copy! XXXX */
4107 DEBUG(3,("Rejecting tree copy\n"));
4108 END_PROFILE(SMBcopy);
4109 return ERROR_DOS(ERRSRV,ERRerror);
4112 p = strrchr_m(name,'/');
4113 if (!p) {
4114 pstrcpy(directory,"./");
4115 pstrcpy(mask,name);
4116 } else {
4117 *p = 0;
4118 pstrcpy(directory,name);
4119 pstrcpy(mask,p+1);
4123 * We should only check the mangled cache
4124 * here if unix_convert failed. This means
4125 * that the path in 'mask' doesn't exist
4126 * on the file system and so we need to look
4127 * for a possible mangle. This patch from
4128 * Tine Smukavec <valentin.smukavec@hermes.si>.
4131 if (!rc && mangle_is_mangled(mask))
4132 mangle_check_cache( mask );
4134 has_wild = ms_has_wild(mask);
4136 if (!has_wild) {
4137 pstrcat(directory,"/");
4138 pstrcat(directory,mask);
4139 if (resolve_wildcards(directory,newname) &&
4140 copy_file(directory,newname,conn,ofun, count,target_is_directory,&err))
4141 count++;
4142 if(!count && err) {
4143 errno = err;
4144 END_PROFILE(SMBcopy);
4145 return(UNIXERROR(ERRHRD,ERRgeneral));
4147 if (!count) {
4148 exists = vfs_file_exist(conn,directory,NULL);
4150 } else {
4151 void *dirptr = NULL;
4152 const char *dname;
4153 pstring destname;
4155 if (check_name(directory,conn))
4156 dirptr = OpenDir(conn, directory, True);
4158 if (dirptr) {
4159 error = ERRbadfile;
4161 if (strequal(mask,"????????.???"))
4162 pstrcpy(mask,"*");
4164 while ((dname = ReadDirName(dirptr))) {
4165 pstring fname;
4166 pstrcpy(fname,dname);
4168 if(!mask_match(fname, mask, case_sensitive))
4169 continue;
4171 error = ERRnoaccess;
4172 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
4173 pstrcpy(destname,newname);
4174 if (resolve_wildcards(fname,destname) &&
4175 copy_file(fname,destname,conn,ofun,
4176 count,target_is_directory,&err))
4177 count++;
4178 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
4180 CloseDir(dirptr);
4184 if (count == 0) {
4185 if(err) {
4186 /* Error on close... */
4187 errno = err;
4188 END_PROFILE(SMBcopy);
4189 return(UNIXERROR(ERRHRD,ERRgeneral));
4192 if (exists) {
4193 END_PROFILE(SMBcopy);
4194 return ERROR_DOS(ERRDOS,error);
4195 } else {
4196 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
4197 unix_ERR_class = ERRDOS;
4198 unix_ERR_code = ERRbadpath;
4200 END_PROFILE(SMBcopy);
4201 return(UNIXERROR(ERRDOS,error));
4205 outsize = set_message(outbuf,1,0,True);
4206 SSVAL(outbuf,smb_vwv0,count);
4208 END_PROFILE(SMBcopy);
4209 return(outsize);
4212 /****************************************************************************
4213 Reply to a setdir.
4214 ****************************************************************************/
4216 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4218 int snum;
4219 int outsize = 0;
4220 BOOL ok = False;
4221 pstring newdir;
4222 NTSTATUS status;
4224 START_PROFILE(pathworks_setdir);
4226 snum = SNUM(conn);
4227 if (!CAN_SETDIR(snum)) {
4228 END_PROFILE(pathworks_setdir);
4229 return ERROR_DOS(ERRDOS,ERRnoaccess);
4232 srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status);
4233 if (!NT_STATUS_IS_OK(status)) {
4234 END_PROFILE(pathworks_setdir);
4235 return ERROR_NT(status);
4238 if (strlen(newdir) == 0) {
4239 ok = True;
4240 } else {
4241 ok = vfs_directory_exist(conn,newdir,NULL);
4242 if (ok)
4243 string_set(&conn->connectpath,newdir);
4246 if (!ok) {
4247 END_PROFILE(pathworks_setdir);
4248 return ERROR_DOS(ERRDOS,ERRbadpath);
4251 outsize = set_message(outbuf,0,0,True);
4252 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
4254 DEBUG(3,("setdir %s\n", newdir));
4256 END_PROFILE(pathworks_setdir);
4257 return(outsize);
4260 /****************************************************************************
4261 Get a lock pid, dealing with large count requests.
4262 ****************************************************************************/
4264 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
4266 if(!large_file_format)
4267 return SVAL(data,SMB_LPID_OFFSET(data_offset));
4268 else
4269 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
4272 /****************************************************************************
4273 Get a lock count, dealing with large count requests.
4274 ****************************************************************************/
4276 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4278 SMB_BIG_UINT count = 0;
4280 if(!large_file_format) {
4281 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4282 } else {
4284 #if defined(HAVE_LONGLONG)
4285 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4286 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4287 #else /* HAVE_LONGLONG */
4290 * NT4.x seems to be broken in that it sends large file (64 bit)
4291 * lockingX calls even if the CAP_LARGE_FILES was *not*
4292 * negotiated. For boxes without large unsigned ints truncate the
4293 * lock count by dropping the top 32 bits.
4296 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4297 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4298 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4299 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4300 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4303 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4304 #endif /* HAVE_LONGLONG */
4307 return count;
4310 #if !defined(HAVE_LONGLONG)
4311 /****************************************************************************
4312 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
4313 ****************************************************************************/
4315 static uint32 map_lock_offset(uint32 high, uint32 low)
4317 unsigned int i;
4318 uint32 mask = 0;
4319 uint32 highcopy = high;
4322 * Try and find out how many significant bits there are in high.
4325 for(i = 0; highcopy; i++)
4326 highcopy >>= 1;
4329 * We use 31 bits not 32 here as POSIX
4330 * lock offsets may not be negative.
4333 mask = (~0) << (31 - i);
4335 if(low & mask)
4336 return 0; /* Fail. */
4338 high <<= (31 - i);
4340 return (high|low);
4342 #endif /* !defined(HAVE_LONGLONG) */
4344 /****************************************************************************
4345 Get a lock offset, dealing with large offset requests.
4346 ****************************************************************************/
4348 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4350 SMB_BIG_UINT offset = 0;
4352 *err = False;
4354 if(!large_file_format) {
4355 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4356 } else {
4358 #if defined(HAVE_LONGLONG)
4359 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4360 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4361 #else /* HAVE_LONGLONG */
4364 * NT4.x seems to be broken in that it sends large file (64 bit)
4365 * lockingX calls even if the CAP_LARGE_FILES was *not*
4366 * negotiated. For boxes without large unsigned ints mangle the
4367 * lock offset by mapping the top 32 bits onto the lower 32.
4370 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4371 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4372 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4373 uint32 new_low = 0;
4375 if((new_low = map_lock_offset(high, low)) == 0) {
4376 *err = True;
4377 return (SMB_BIG_UINT)-1;
4380 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4381 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4382 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4383 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4386 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4387 #endif /* HAVE_LONGLONG */
4390 return offset;
4393 /****************************************************************************
4394 Reply to a lockingX request.
4395 ****************************************************************************/
4397 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4399 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4400 unsigned char locktype = CVAL(inbuf,smb_vwv3);
4401 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4402 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4403 uint16 num_locks = SVAL(inbuf,smb_vwv7);
4404 SMB_BIG_UINT count = 0, offset = 0;
4405 uint16 lock_pid;
4406 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4407 int i;
4408 char *data;
4409 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4410 BOOL err;
4411 BOOL my_lock_ctx = False;
4412 NTSTATUS status;
4414 START_PROFILE(SMBlockingX);
4416 CHECK_FSP(fsp,conn);
4418 data = smb_buf(inbuf);
4420 if (locktype & (LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_CHANGE_LOCKTYPE)) {
4421 /* we don't support these - and CANCEL_LOCK makes w2k
4422 and XP reboot so I don't really want to be
4423 compatible! (tridge) */
4424 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
4427 /* Check if this is an oplock break on a file
4428 we have granted an oplock on.
4430 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
4431 /* Client can insist on breaking to none. */
4432 BOOL break_to_none = (oplocklevel == 0);
4434 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4435 (unsigned int)oplocklevel, fsp->fnum ));
4438 * Make sure we have granted an exclusive or batch oplock on this file.
4441 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
4442 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4443 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4445 /* if this is a pure oplock break request then don't send a reply */
4446 if (num_locks == 0 && num_ulocks == 0) {
4447 END_PROFILE(SMBlockingX);
4448 return -1;
4449 } else {
4450 END_PROFILE(SMBlockingX);
4451 return ERROR_DOS(ERRDOS,ERRlock);
4455 if (remove_oplock(fsp, break_to_none) == False) {
4456 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4457 fsp->fsp_name ));
4460 /* if this is a pure oplock break request then don't send a reply */
4461 if (num_locks == 0 && num_ulocks == 0) {
4462 /* Sanity check - ensure a pure oplock break is not a
4463 chained request. */
4464 if(CVAL(inbuf,smb_vwv0) != 0xff)
4465 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4466 (unsigned int)CVAL(inbuf,smb_vwv0) ));
4467 END_PROFILE(SMBlockingX);
4468 return -1;
4473 * We do this check *after* we have checked this is not a oplock break
4474 * response message. JRA.
4477 release_level_2_oplocks_on_change(fsp);
4479 /* Data now points at the beginning of the list
4480 of smb_unlkrng structs */
4481 for(i = 0; i < (int)num_ulocks; i++) {
4482 lock_pid = get_lock_pid( data, i, large_file_format);
4483 count = get_lock_count( data, i, large_file_format);
4484 offset = get_lock_offset( data, i, large_file_format, &err);
4487 * There is no error code marked "stupid client bug".... :-).
4489 if(err) {
4490 END_PROFILE(SMBlockingX);
4491 return ERROR_DOS(ERRDOS,ERRnoaccess);
4494 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4495 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4497 status = do_unlock(fsp,conn,lock_pid,count,offset);
4498 if (NT_STATUS_V(status)) {
4499 END_PROFILE(SMBlockingX);
4500 return ERROR_NT(status);
4504 /* Setup the timeout in seconds. */
4506 lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000);
4508 /* Now do any requested locks */
4509 data += ((large_file_format ? 20 : 10)*num_ulocks);
4511 /* Data now points at the beginning of the list
4512 of smb_lkrng structs */
4514 for(i = 0; i < (int)num_locks; i++) {
4515 lock_pid = get_lock_pid( data, i, large_file_format);
4516 count = get_lock_count( data, i, large_file_format);
4517 offset = get_lock_offset( data, i, large_file_format, &err);
4520 * There is no error code marked "stupid client bug".... :-).
4522 if(err) {
4523 END_PROFILE(SMBlockingX);
4524 return ERROR_DOS(ERRDOS,ERRnoaccess);
4527 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
4528 (double)offset, (double)count, (unsigned int)lock_pid,
4529 fsp->fsp_name, (int)lock_timeout ));
4531 status = do_lock_spin(fsp,conn,lock_pid, count,offset,
4532 ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &my_lock_ctx);
4533 if (NT_STATUS_V(status)) {
4535 * Interesting fact found by IFSTEST /t LockOverlappedTest...
4536 * Even if it's our own lock context, we need to wait here as
4537 * there may be an unlock on the way.
4538 * So I removed a "&& !my_lock_ctx" from the following
4539 * if statement. JRA.
4541 if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
4543 * A blocking lock was requested. Package up
4544 * this smb into a queued request and push it
4545 * onto the blocking lock queue.
4547 if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) {
4548 END_PROFILE(SMBlockingX);
4549 return -1;
4552 break;
4556 /* If any of the above locks failed, then we must unlock
4557 all of the previous locks (X/Open spec). */
4558 if (i != num_locks && num_locks != 0) {
4560 * Ensure we don't do a remove on the lock that just failed,
4561 * as under POSIX rules, if we have a lock already there, we
4562 * will delete it (and we shouldn't) .....
4564 for(i--; i >= 0; i--) {
4565 lock_pid = get_lock_pid( data, i, large_file_format);
4566 count = get_lock_count( data, i, large_file_format);
4567 offset = get_lock_offset( data, i, large_file_format, &err);
4570 * There is no error code marked "stupid client bug".... :-).
4572 if(err) {
4573 END_PROFILE(SMBlockingX);
4574 return ERROR_DOS(ERRDOS,ERRnoaccess);
4577 do_unlock(fsp,conn,lock_pid,count,offset);
4579 END_PROFILE(SMBlockingX);
4580 return ERROR_NT(status);
4583 set_message(outbuf,2,0,True);
4585 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4586 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4588 END_PROFILE(SMBlockingX);
4589 return chain_reply(inbuf,outbuf,length,bufsize);
4592 /****************************************************************************
4593 Reply to a SMBreadbmpx (read block multiplex) request.
4594 ****************************************************************************/
4596 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4598 ssize_t nread = -1;
4599 ssize_t total_read;
4600 char *data;
4601 SMB_OFF_T startpos;
4602 int outsize;
4603 size_t maxcount;
4604 int max_per_packet;
4605 size_t tcount;
4606 int pad;
4607 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4608 START_PROFILE(SMBreadBmpx);
4610 /* this function doesn't seem to work - disable by default */
4611 if (!lp_readbmpx()) {
4612 END_PROFILE(SMBreadBmpx);
4613 return ERROR_DOS(ERRSRV,ERRuseSTD);
4616 outsize = set_message(outbuf,8,0,True);
4618 CHECK_FSP(fsp,conn);
4619 CHECK_READ(fsp);
4621 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
4622 maxcount = SVAL(inbuf,smb_vwv3);
4624 data = smb_buf(outbuf);
4625 pad = ((long)data)%4;
4626 if (pad)
4627 pad = 4 - pad;
4628 data += pad;
4630 max_per_packet = bufsize-(outsize+pad);
4631 tcount = maxcount;
4632 total_read = 0;
4634 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
4635 END_PROFILE(SMBreadBmpx);
4636 return ERROR_DOS(ERRDOS,ERRlock);
4639 do {
4640 size_t N = MIN(max_per_packet,tcount-total_read);
4642 nread = read_file(fsp,data,startpos,N);
4644 if (nread <= 0)
4645 nread = 0;
4647 if (nread < (ssize_t)N)
4648 tcount = total_read + nread;
4650 set_message(outbuf,8,nread,False);
4651 SIVAL(outbuf,smb_vwv0,startpos);
4652 SSVAL(outbuf,smb_vwv2,tcount);
4653 SSVAL(outbuf,smb_vwv6,nread);
4654 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4656 if (!send_smb(smbd_server_fd(),outbuf))
4657 exit_server("reply_readbmpx: send_smb failed.");
4659 total_read += nread;
4660 startpos += nread;
4661 } while (total_read < (ssize_t)tcount);
4663 END_PROFILE(SMBreadBmpx);
4664 return(-1);
4667 /****************************************************************************
4668 Reply to a SMBsetattrE.
4669 ****************************************************************************/
4671 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4673 struct utimbuf unix_times;
4674 int outsize = 0;
4675 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4676 START_PROFILE(SMBsetattrE);
4678 outsize = set_message(outbuf,0,0,True);
4680 if(!fsp || (fsp->conn != conn)) {
4681 END_PROFILE(SMBgetattrE);
4682 return ERROR_DOS(ERRDOS,ERRbadfid);
4686 * Convert the DOS times into unix times. Ignore create
4687 * time as UNIX can't set this.
4690 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4691 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4694 * Patch from Ray Frush <frush@engr.colostate.edu>
4695 * Sometimes times are sent as zero - ignore them.
4698 if ((unix_times.actime == 0) && (unix_times.modtime == 0)) {
4699 /* Ignore request */
4700 if( DEBUGLVL( 3 ) ) {
4701 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4702 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4704 END_PROFILE(SMBsetattrE);
4705 return(outsize);
4706 } else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) {
4707 /* set modify time = to access time if modify time was 0 */
4708 unix_times.modtime = unix_times.actime;
4711 /* Set the date on this file */
4712 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4713 END_PROFILE(SMBsetattrE);
4714 return ERROR_DOS(ERRDOS,ERRnoaccess);
4717 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4718 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4720 END_PROFILE(SMBsetattrE);
4721 return(outsize);
4725 /* Back from the dead for OS/2..... JRA. */
4727 /****************************************************************************
4728 Reply to a SMBwritebmpx (write block multiplex primary) request.
4729 ****************************************************************************/
4731 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4733 size_t numtowrite;
4734 ssize_t nwritten = -1;
4735 int outsize = 0;
4736 SMB_OFF_T startpos;
4737 size_t tcount;
4738 BOOL write_through;
4739 int smb_doff;
4740 char *data;
4741 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4742 START_PROFILE(SMBwriteBmpx);
4744 CHECK_FSP(fsp,conn);
4745 CHECK_WRITE(fsp);
4746 CHECK_ERROR(fsp);
4748 tcount = SVAL(inbuf,smb_vwv1);
4749 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
4750 write_through = BITSETW(inbuf+smb_vwv7,0);
4751 numtowrite = SVAL(inbuf,smb_vwv10);
4752 smb_doff = SVAL(inbuf,smb_vwv11);
4754 data = smb_base(inbuf) + smb_doff;
4756 /* If this fails we need to send an SMBwriteC response,
4757 not an SMBwritebmpx - set this up now so we don't forget */
4758 SCVAL(outbuf,smb_com,SMBwritec);
4760 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK,False)) {
4761 END_PROFILE(SMBwriteBmpx);
4762 return(ERROR_DOS(ERRDOS,ERRlock));
4765 nwritten = write_file(fsp,data,startpos,numtowrite);
4767 if(lp_syncalways(SNUM(conn)) || write_through)
4768 sync_file(conn,fsp);
4770 if(nwritten < (ssize_t)numtowrite) {
4771 END_PROFILE(SMBwriteBmpx);
4772 return(UNIXERROR(ERRHRD,ERRdiskfull));
4775 /* If the maximum to be written to this file
4776 is greater than what we just wrote then set
4777 up a secondary struct to be attached to this
4778 fd, we will use this to cache error messages etc. */
4780 if((ssize_t)tcount > nwritten) {
4781 write_bmpx_struct *wbms;
4782 if(fsp->wbmpx_ptr != NULL)
4783 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4784 else
4785 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
4786 if(!wbms) {
4787 DEBUG(0,("Out of memory in reply_readmpx\n"));
4788 END_PROFILE(SMBwriteBmpx);
4789 return(ERROR_DOS(ERRSRV,ERRnoresource));
4791 wbms->wr_mode = write_through;
4792 wbms->wr_discard = False; /* No errors yet */
4793 wbms->wr_total_written = nwritten;
4794 wbms->wr_errclass = 0;
4795 wbms->wr_error = 0;
4796 fsp->wbmpx_ptr = wbms;
4799 /* We are returning successfully, set the message type back to
4800 SMBwritebmpx */
4801 SCVAL(outbuf,smb_com,SMBwriteBmpx);
4803 outsize = set_message(outbuf,1,0,True);
4805 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
4807 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4808 fsp->fnum, (int)numtowrite, (int)nwritten ) );
4810 if (write_through && tcount==nwritten) {
4811 /* We need to send both a primary and a secondary response */
4812 smb_setlen(outbuf,outsize - 4);
4813 if (!send_smb(smbd_server_fd(),outbuf))
4814 exit_server("reply_writebmpx: send_smb failed.");
4816 /* Now the secondary */
4817 outsize = set_message(outbuf,1,0,True);
4818 SCVAL(outbuf,smb_com,SMBwritec);
4819 SSVAL(outbuf,smb_vwv0,nwritten);
4822 END_PROFILE(SMBwriteBmpx);
4823 return(outsize);
4826 /****************************************************************************
4827 Reply to a SMBwritebs (write block multiplex secondary) request.
4828 ****************************************************************************/
4830 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4832 size_t numtowrite;
4833 ssize_t nwritten = -1;
4834 int outsize = 0;
4835 SMB_OFF_T startpos;
4836 size_t tcount;
4837 BOOL write_through;
4838 int smb_doff;
4839 char *data;
4840 write_bmpx_struct *wbms;
4841 BOOL send_response = False;
4842 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4843 START_PROFILE(SMBwriteBs);
4845 CHECK_FSP(fsp,conn);
4846 CHECK_WRITE(fsp);
4848 tcount = SVAL(inbuf,smb_vwv1);
4849 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
4850 numtowrite = SVAL(inbuf,smb_vwv6);
4851 smb_doff = SVAL(inbuf,smb_vwv7);
4853 data = smb_base(inbuf) + smb_doff;
4855 /* We need to send an SMBwriteC response, not an SMBwritebs */
4856 SCVAL(outbuf,smb_com,SMBwritec);
4858 /* This fd should have an auxiliary struct attached,
4859 check that it does */
4860 wbms = fsp->wbmpx_ptr;
4861 if(!wbms) {
4862 END_PROFILE(SMBwriteBs);
4863 return(-1);
4866 /* If write through is set we can return errors, else we must cache them */
4867 write_through = wbms->wr_mode;
4869 /* Check for an earlier error */
4870 if(wbms->wr_discard) {
4871 END_PROFILE(SMBwriteBs);
4872 return -1; /* Just discard the packet */
4875 nwritten = write_file(fsp,data,startpos,numtowrite);
4877 if(lp_syncalways(SNUM(conn)) || write_through)
4878 sync_file(conn,fsp);
4880 if (nwritten < (ssize_t)numtowrite) {
4881 if(write_through) {
4882 /* We are returning an error - we can delete the aux struct */
4883 if (wbms)
4884 free((char *)wbms);
4885 fsp->wbmpx_ptr = NULL;
4886 END_PROFILE(SMBwriteBs);
4887 return(ERROR_DOS(ERRHRD,ERRdiskfull));
4889 END_PROFILE(SMBwriteBs);
4890 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4893 /* Increment the total written, if this matches tcount
4894 we can discard the auxiliary struct (hurrah !) and return a writeC */
4895 wbms->wr_total_written += nwritten;
4896 if(wbms->wr_total_written >= tcount) {
4897 if (write_through) {
4898 outsize = set_message(outbuf,1,0,True);
4899 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
4900 send_response = True;
4903 free((char *)wbms);
4904 fsp->wbmpx_ptr = NULL;
4907 if(send_response) {
4908 END_PROFILE(SMBwriteBs);
4909 return(outsize);
4912 END_PROFILE(SMBwriteBs);
4913 return(-1);
4916 /****************************************************************************
4917 Reply to a SMBgetattrE.
4918 ****************************************************************************/
4920 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4922 SMB_STRUCT_STAT sbuf;
4923 int outsize = 0;
4924 int mode;
4925 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4926 START_PROFILE(SMBgetattrE);
4928 outsize = set_message(outbuf,11,0,True);
4930 if(!fsp || (fsp->conn != conn)) {
4931 END_PROFILE(SMBgetattrE);
4932 return ERROR_DOS(ERRDOS,ERRbadfid);
4935 /* Do an fstat on this file */
4936 if(fsp_stat(fsp, &sbuf)) {
4937 END_PROFILE(SMBgetattrE);
4938 return(UNIXERROR(ERRDOS,ERRnoaccess));
4941 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4944 * Convert the times into dos times. Set create
4945 * date to be last modify date as UNIX doesn't save
4946 * this.
4949 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4950 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4951 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4953 if (mode & aDIR) {
4954 SIVAL(outbuf,smb_vwv6,0);
4955 SIVAL(outbuf,smb_vwv8,0);
4956 } else {
4957 uint32 allocation_size = get_allocation_size(fsp, &sbuf);
4958 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4959 SIVAL(outbuf,smb_vwv8,allocation_size);
4961 SSVAL(outbuf,smb_vwv10, mode);
4963 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
4965 END_PROFILE(SMBgetattrE);
4966 return(outsize);