r2150: Fix parsing of names ending in dot and a few other error returns
[Samba/wip.git] / source3 / smbd / reply.c
blob30616a66fbfc98bda835e7a3c071a416929d9002
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 int global_oplock_break;
35 unsigned int smb_echo_count = 0;
37 extern BOOL global_encrypted_passwords_negotiated;
39 /****************************************************************************
40 Ensure we check the path in *exactly* the same way as W2K.
41 We're assuming here that '/' is not the second byte in any multibyte char
42 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
43 set.
44 ****************************************************************************/
46 NTSTATUS check_path_syntax(pstring destname, const pstring srcname, BOOL allow_wcard_names)
48 char *d = destname;
49 const char *s = srcname;
50 NTSTATUS ret = NT_STATUS_OK;
52 while (*s) {
53 if (IS_DIRECTORY_SEP(*s)) {
55 * Safe to assume is not the second part of a mb char as this is handled below.
57 /* Eat multiple '/' or '\\' */
58 while (IS_DIRECTORY_SEP(*s)) {
59 s++;
61 if ((s[0] == '.') && (s[1] == '\0')) {
62 ret = NT_STATUS_OBJECT_NAME_INVALID;
63 break;
65 if ((d != destname) && (*s != '\0')) {
66 /* We only care about non-leading or trailing '/' or '\\' */
67 *d++ = '/';
69 } else if ((s[0] == '.') && (s[1] == '.') && (IS_DIRECTORY_SEP(s[2]) || s[2] == '\0')) {
70 /* Uh oh - "../" or "..\\" or "..\0" ! */
73 * No mb char starts with '.' so we're safe checking the directory separator here.
76 /* If we just added a '/', delete it. */
78 if ((d > destname) && (*(d-1) == '/')) {
79 *(d-1) = '\0';
80 if (d == (destname + 1)) {
81 d--;
82 } else {
83 d -= 2;
86 /* Are we at the start ? Can't go back further if so. */
87 if (d == destname) {
88 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
89 break;
91 /* Go back one level... */
92 /* We know this is safe as '/' cannot be part of a mb sequence. */
93 /* NOTE - if this assumption is invalid we are not in good shape... */
94 while (d > destname) {
95 if (*d == '/')
96 break;
97 d--;
99 s += 3;
100 } else if ((s[0] == '.') && (s[1] == '\0')) {
101 if (s == srcname) {
102 ret = NT_STATUS_OBJECT_NAME_INVALID;
103 break;
105 *d++ = *s++;
106 } else if ((s[0] == '.') && IS_DIRECTORY_SEP(s[1])) {
108 * No mb char starts with '.' so we're safe checking the directory separator here.
111 /* "./" or ".\\" fails with a different error depending on what is after it... */
113 if (s[2] == '\0') {
114 ret = NT_STATUS_OBJECT_NAME_INVALID;
115 } else {
116 ret = NT_STATUS_OBJECT_PATH_NOT_FOUND;
118 break;
119 } else {
120 if (!(*s & 0x80)) {
121 if (allow_wcard_names) {
122 *d++ = *s++;
123 } else {
124 switch (*s) {
125 case '*':
126 case '?':
127 case '<':
128 case '>':
129 case '"':
130 return NT_STATUS_OBJECT_NAME_INVALID;
131 default:
132 *d++ = *s++;
133 break;
136 } else {
137 switch(next_mb_char_size(s)) {
138 case 4:
139 *d++ = *s++;
140 case 3:
141 *d++ = *s++;
142 case 2:
143 *d++ = *s++;
144 case 1:
145 *d++ = *s++;
146 break;
147 default:
148 DEBUG(0,("check_path_syntax: character length assumptions invalid !\n"));
149 *d = '\0';
150 return NT_STATUS_INVALID_PARAMETER;
155 *d = '\0';
156 return ret;
159 /****************************************************************************
160 Pull a string and check the path - provide for error return.
161 ****************************************************************************/
163 size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags, NTSTATUS *err, BOOL allow_wcard_names)
165 pstring tmppath;
166 char *tmppath_ptr = tmppath;
167 size_t ret;
168 #ifdef DEVELOPER
169 SMB_ASSERT(dest_len == sizeof(pstring));
170 #endif
172 if (src_len == 0) {
173 ret = srvstr_pull_buf( inbuf, tmppath_ptr, src, dest_len, flags);
174 } else {
175 ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags);
177 *err = check_path_syntax(dest, tmppath, allow_wcard_names);
178 return ret;
181 /****************************************************************************
182 Reply to a special message.
183 ****************************************************************************/
185 int reply_special(char *inbuf,char *outbuf)
187 int outsize = 4;
188 int msg_type = CVAL(inbuf,0);
189 int msg_flags = CVAL(inbuf,1);
190 fstring name1,name2;
191 char name_type = 0;
193 static BOOL already_got_session = False;
195 *name1 = *name2 = 0;
197 memset(outbuf,'\0',smb_size);
199 smb_setlen(outbuf,0);
201 switch (msg_type) {
202 case 0x81: /* session request */
204 if (already_got_session) {
205 exit_server("multiple session request not permitted");
208 SCVAL(outbuf,0,0x82);
209 SCVAL(outbuf,3,0);
210 if (name_len(inbuf+4) > 50 ||
211 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
212 DEBUG(0,("Invalid name length in session request\n"));
213 return(0);
215 name_extract(inbuf,4,name1);
216 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
217 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
218 name1,name2));
220 set_local_machine_name(name1, True);
221 set_remote_machine_name(name2, True);
223 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
224 get_local_machine_name(), get_remote_machine_name(),
225 name_type));
227 if (name_type == 'R') {
228 /* We are being asked for a pathworks session ---
229 no thanks! */
230 SCVAL(outbuf, 0,0x83);
231 break;
234 /* only add the client's machine name to the list
235 of possibly valid usernames if we are operating
236 in share mode security */
237 if (lp_security() == SEC_SHARE) {
238 add_session_user(get_remote_machine_name());
241 reload_services(True);
242 reopen_logs();
244 claim_connection(NULL,"",0,True,FLAG_MSG_GENERAL|FLAG_MSG_SMBD|FLAG_MSG_PRINT_GENERAL);
246 already_got_session = True;
247 break;
249 case 0x89: /* session keepalive request
250 (some old clients produce this?) */
251 SCVAL(outbuf,0,SMBkeepalive);
252 SCVAL(outbuf,3,0);
253 break;
255 case 0x82: /* positive session response */
256 case 0x83: /* negative session response */
257 case 0x84: /* retarget session response */
258 DEBUG(0,("Unexpected session response\n"));
259 break;
261 case SMBkeepalive: /* session keepalive */
262 default:
263 return(0);
266 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
267 msg_type, msg_flags));
269 return(outsize);
272 /****************************************************************************
273 Reply to a tcon.
274 ****************************************************************************/
276 int reply_tcon(connection_struct *conn,
277 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
279 const char *service;
280 pstring service_buf;
281 pstring password;
282 pstring dev;
283 int outsize = 0;
284 uint16 vuid = SVAL(inbuf,smb_uid);
285 int pwlen=0;
286 NTSTATUS nt_status;
287 char *p;
288 DATA_BLOB password_blob;
290 START_PROFILE(SMBtcon);
292 *service_buf = *password = *dev = 0;
294 p = smb_buf(inbuf)+1;
295 p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service_buf), STR_TERMINATE) + 1;
296 pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1;
297 p += pwlen;
298 p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1;
300 p = strrchr_m(service_buf,'\\');
301 if (p) {
302 service = p+1;
303 } else {
304 service = service_buf;
307 password_blob = data_blob(password, pwlen+1);
309 conn = make_connection(service,password_blob,dev,vuid,&nt_status);
311 data_blob_clear_free(&password_blob);
313 if (!conn) {
314 END_PROFILE(SMBtcon);
315 return ERROR_NT(nt_status);
318 outsize = set_message(outbuf,2,0,True);
319 SSVAL(outbuf,smb_vwv0,max_recv);
320 SSVAL(outbuf,smb_vwv1,conn->cnum);
321 SSVAL(outbuf,smb_tid,conn->cnum);
323 DEBUG(3,("tcon service=%s cnum=%d\n",
324 service, conn->cnum));
326 END_PROFILE(SMBtcon);
327 return(outsize);
330 /****************************************************************************
331 Reply to a tcon and X.
332 ****************************************************************************/
334 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
336 fstring service;
337 DATA_BLOB password;
339 /* what the cleint thinks the device is */
340 fstring client_devicetype;
341 /* what the server tells the client the share represents */
342 const char *server_devicetype;
343 NTSTATUS nt_status;
344 uint16 vuid = SVAL(inbuf,smb_uid);
345 int passlen = SVAL(inbuf,smb_vwv3);
346 pstring path;
347 char *p, *q;
348 extern BOOL global_encrypted_passwords_negotiated;
350 START_PROFILE(SMBtconX);
352 *service = *client_devicetype = 0;
354 /* we might have to close an old one */
355 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
356 close_cnum(conn,vuid);
359 if (passlen > MAX_PASS_LEN) {
360 return ERROR_DOS(ERRDOS,ERRbuftoosmall);
363 if (global_encrypted_passwords_negotiated) {
364 password = data_blob(smb_buf(inbuf),passlen);
365 } else {
366 password = data_blob(smb_buf(inbuf),passlen+1);
367 /* Ensure correct termination */
368 password.data[passlen]=0;
371 p = smb_buf(inbuf) + passlen;
372 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
375 * the service name can be either: \\server\share
376 * or share directly like on the DELL PowerVault 705
378 if (*path=='\\') {
379 q = strchr_m(path+2,'\\');
380 if (!q) {
381 END_PROFILE(SMBtconX);
382 return(ERROR_DOS(ERRDOS,ERRnosuchshare));
384 fstrcpy(service,q+1);
386 else
387 fstrcpy(service,path);
389 p += srvstr_pull(inbuf, client_devicetype, p, sizeof(client_devicetype), 6, STR_ASCII);
391 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
393 conn = make_connection(service,password,client_devicetype,vuid,&nt_status);
395 data_blob_clear_free(&password);
397 if (!conn) {
398 END_PROFILE(SMBtconX);
399 return ERROR_NT(nt_status);
402 if ( IS_IPC(conn) )
403 server_devicetype = "IPC";
404 else if ( IS_PRINT(conn) )
405 server_devicetype = "LPT1:";
406 else
407 server_devicetype = "A:";
409 if (Protocol < PROTOCOL_NT1) {
410 set_message(outbuf,2,0,True);
411 p = smb_buf(outbuf);
412 p += srvstr_push(outbuf, p, server_devicetype, -1,
413 STR_TERMINATE|STR_ASCII);
414 set_message_end(outbuf,p);
415 } else {
416 /* NT sets the fstype of IPC$ to the null string */
417 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
419 set_message(outbuf,3,0,True);
421 p = smb_buf(outbuf);
422 p += srvstr_push(outbuf, p, server_devicetype, -1,
423 STR_TERMINATE|STR_ASCII);
424 p += srvstr_push(outbuf, p, fstype, -1,
425 STR_TERMINATE);
427 set_message_end(outbuf,p);
429 /* what does setting this bit do? It is set by NT4 and
430 may affect the ability to autorun mounted cdroms */
431 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
432 (lp_csc_policy(SNUM(conn)) << 2));
434 init_dfsroot(conn, inbuf, outbuf);
438 DEBUG(3,("tconX service=%s \n",
439 service));
441 /* set the incoming and outgoing tid to the just created one */
442 SSVAL(inbuf,smb_tid,conn->cnum);
443 SSVAL(outbuf,smb_tid,conn->cnum);
445 END_PROFILE(SMBtconX);
446 return chain_reply(inbuf,outbuf,length,bufsize);
449 /****************************************************************************
450 Reply to an unknown type.
451 ****************************************************************************/
453 int reply_unknown(char *inbuf,char *outbuf)
455 int type;
456 type = CVAL(inbuf,smb_com);
458 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
459 smb_fn_name(type), type, type));
461 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
464 /****************************************************************************
465 Reply to an ioctl.
466 ****************************************************************************/
468 int reply_ioctl(connection_struct *conn,
469 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
471 uint16 device = SVAL(inbuf,smb_vwv1);
472 uint16 function = SVAL(inbuf,smb_vwv2);
473 uint32 ioctl_code = (device << 16) + function;
474 int replysize, outsize;
475 char *p;
476 START_PROFILE(SMBioctl);
478 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
480 switch (ioctl_code) {
481 case IOCTL_QUERY_JOB_INFO:
482 replysize = 32;
483 break;
484 default:
485 END_PROFILE(SMBioctl);
486 return(ERROR_DOS(ERRSRV,ERRnosupport));
489 outsize = set_message(outbuf,8,replysize+1,True);
490 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
491 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
492 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
493 p = smb_buf(outbuf) + 1; /* Allow for alignment */
495 switch (ioctl_code) {
496 case IOCTL_QUERY_JOB_INFO:
498 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
499 if (!fsp) {
500 END_PROFILE(SMBioctl);
501 return(UNIXERROR(ERRDOS,ERRbadfid));
503 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
504 srvstr_push(outbuf, p+2, global_myname(), 15, STR_TERMINATE|STR_ASCII);
505 if (conn) {
506 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
508 break;
512 END_PROFILE(SMBioctl);
513 return outsize;
516 /****************************************************************************
517 Reply to a chkpth.
518 ****************************************************************************/
520 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
522 int outsize = 0;
523 pstring name;
524 BOOL ok = False;
525 BOOL bad_path = False;
526 SMB_STRUCT_STAT sbuf;
527 NTSTATUS status;
529 START_PROFILE(SMBchkpth);
531 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, False);
532 if (!NT_STATUS_IS_OK(status)) {
533 END_PROFILE(SMBchkpth);
534 return ERROR_NT(status);
537 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
539 unix_convert(name,conn,0,&bad_path,&sbuf);
540 if (bad_path) {
541 END_PROFILE(SMBchkpth);
542 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
545 if (check_name(name,conn)) {
546 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,name,&sbuf) == 0)
547 if (!(ok = S_ISDIR(sbuf.st_mode))) {
548 END_PROFILE(SMBchkpth);
549 return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath);
553 if (!ok) {
554 /* We special case this - as when a Windows machine
555 is parsing a path is steps through the components
556 one at a time - if a component fails it expects
557 ERRbadpath, not ERRbadfile.
559 if(errno == ENOENT) {
561 * Windows returns different error codes if
562 * the parent directory is valid but not the
563 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
564 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
565 * if the path is invalid. This is different from set_bad_path_error()
566 * in the non-NT error case.
568 END_PROFILE(SMBchkpth);
569 return ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpath);
572 END_PROFILE(SMBchkpth);
573 return(UNIXERROR(ERRDOS,ERRbadpath));
576 outsize = set_message(outbuf,0,0,True);
577 DEBUG(3,("chkpth %s mode=%d\n", name, (int)SVAL(inbuf,smb_vwv0)));
579 END_PROFILE(SMBchkpth);
580 return(outsize);
583 /****************************************************************************
584 Reply to a getatr.
585 ****************************************************************************/
587 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
589 pstring fname;
590 int outsize = 0;
591 SMB_STRUCT_STAT sbuf;
592 BOOL ok = False;
593 int mode=0;
594 SMB_OFF_T size=0;
595 time_t mtime=0;
596 BOOL bad_path = False;
597 char *p;
598 NTSTATUS status;
600 START_PROFILE(SMBgetatr);
602 p = smb_buf(inbuf) + 1;
603 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status, False);
604 if (!NT_STATUS_IS_OK(status)) {
605 END_PROFILE(SMBgetatr);
606 return ERROR_NT(status);
609 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
611 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
612 under WfWg - weird! */
613 if (! (*fname)) {
614 mode = aHIDDEN | aDIR;
615 if (!CAN_WRITE(conn))
616 mode |= aRONLY;
617 size = 0;
618 mtime = 0;
619 ok = True;
620 } else {
621 unix_convert(fname,conn,0,&bad_path,&sbuf);
622 if (bad_path) {
623 END_PROFILE(SMBgetatr);
624 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
626 if (check_name(fname,conn)) {
627 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,fname,&sbuf) == 0) {
628 mode = dos_mode(conn,fname,&sbuf);
629 size = sbuf.st_size;
630 mtime = sbuf.st_mtime;
631 if (mode & aDIR)
632 size = 0;
633 ok = True;
634 } else {
635 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
640 if (!ok) {
641 END_PROFILE(SMBgetatr);
642 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadfile);
645 outsize = set_message(outbuf,10,0,True);
647 SSVAL(outbuf,smb_vwv0,mode);
648 if(lp_dos_filetime_resolution(SNUM(conn)) )
649 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
650 else
651 put_dos_date3(outbuf,smb_vwv1,mtime);
652 SIVAL(outbuf,smb_vwv3,(uint32)size);
654 if (Protocol >= PROTOCOL_NT1)
655 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
657 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
659 END_PROFILE(SMBgetatr);
660 return(outsize);
663 /****************************************************************************
664 Reply to a setatr.
665 ****************************************************************************/
667 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
669 pstring fname;
670 int outsize = 0;
671 BOOL ok=False;
672 int mode;
673 time_t mtime;
674 SMB_STRUCT_STAT sbuf;
675 BOOL bad_path = False;
676 char *p;
677 NTSTATUS status;
679 START_PROFILE(SMBsetatr);
681 p = smb_buf(inbuf) + 1;
682 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status, False);
683 if (!NT_STATUS_IS_OK(status)) {
684 END_PROFILE(SMBsetatr);
685 return ERROR_NT(status);
688 unix_convert(fname,conn,0,&bad_path,&sbuf);
689 if (bad_path) {
690 END_PROFILE(SMBsetatr);
691 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
694 mode = SVAL(inbuf,smb_vwv0);
695 mtime = make_unix_date3(inbuf+smb_vwv1);
697 if (mode != FILE_ATTRIBUTE_NORMAL) {
698 if (VALID_STAT_OF_DIR(sbuf))
699 mode |= aDIR;
700 else
701 mode &= ~aDIR;
703 if (check_name(fname,conn)) {
704 ok = (file_set_dosmode(conn,fname,mode,NULL) == 0);
706 } else {
707 ok = True;
710 if (ok)
711 ok = set_filetime(conn,fname,mtime);
713 if (!ok) {
714 END_PROFILE(SMBsetatr);
715 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
718 outsize = set_message(outbuf,0,0,True);
720 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
722 END_PROFILE(SMBsetatr);
723 return(outsize);
726 /****************************************************************************
727 Reply to a dskattr.
728 ****************************************************************************/
730 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
732 int outsize = 0;
733 SMB_BIG_UINT dfree,dsize,bsize;
734 START_PROFILE(SMBdskattr);
736 SMB_VFS_DISK_FREE(conn,".",True,&bsize,&dfree,&dsize);
738 outsize = set_message(outbuf,5,0,True);
740 if (Protocol <= PROTOCOL_LANMAN2) {
741 double total_space, free_space;
742 /* we need to scale this to a number that DOS6 can handle. We
743 use floating point so we can handle large drives on systems
744 that don't have 64 bit integers
746 we end up displaying a maximum of 2G to DOS systems
748 total_space = dsize * (double)bsize;
749 free_space = dfree * (double)bsize;
751 dsize = (total_space+63*512) / (64*512);
752 dfree = (free_space+63*512) / (64*512);
754 if (dsize > 0xFFFF) dsize = 0xFFFF;
755 if (dfree > 0xFFFF) dfree = 0xFFFF;
757 SSVAL(outbuf,smb_vwv0,dsize);
758 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
759 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
760 SSVAL(outbuf,smb_vwv3,dfree);
761 } else {
762 SSVAL(outbuf,smb_vwv0,dsize);
763 SSVAL(outbuf,smb_vwv1,bsize/512);
764 SSVAL(outbuf,smb_vwv2,512);
765 SSVAL(outbuf,smb_vwv3,dfree);
768 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
770 END_PROFILE(SMBdskattr);
771 return(outsize);
774 /****************************************************************************
775 Reply to a search.
776 Can be called from SMBsearch, SMBffirst or SMBfunique.
777 ****************************************************************************/
779 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
781 pstring mask;
782 pstring directory;
783 pstring fname;
784 SMB_OFF_T size;
785 int mode;
786 time_t date;
787 int dirtype;
788 int outsize = 0;
789 unsigned int numentries = 0;
790 unsigned int maxentries = 0;
791 BOOL finished = False;
792 char *p;
793 BOOL ok = False;
794 int status_len;
795 pstring path;
796 char status[21];
797 int dptr_num= -1;
798 BOOL check_descend = False;
799 BOOL expect_close = False;
800 BOOL can_open = True;
801 BOOL bad_path = False;
802 NTSTATUS nt_status;
803 START_PROFILE(SMBsearch);
805 *mask = *directory = *fname = 0;
807 /* If we were called as SMBffirst then we must expect close. */
808 if(CVAL(inbuf,smb_com) == SMBffirst)
809 expect_close = True;
811 outsize = set_message(outbuf,1,3,True);
812 maxentries = SVAL(inbuf,smb_vwv0);
813 dirtype = SVAL(inbuf,smb_vwv1);
814 p = smb_buf(inbuf) + 1;
815 p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &nt_status, True);
816 if (!NT_STATUS_IS_OK(nt_status)) {
817 END_PROFILE(SMBsearch);
818 return ERROR_NT(nt_status);
820 p++;
821 status_len = SVAL(p, 0);
822 p += 2;
824 /* dirtype &= ~aDIR; */
826 if (status_len == 0) {
827 SMB_STRUCT_STAT sbuf;
828 pstring dir2;
830 pstrcpy(directory,path);
831 pstrcpy(dir2,path);
832 unix_convert(directory,conn,0,&bad_path,&sbuf);
833 unix_format(dir2);
835 if (!check_name(directory,conn))
836 can_open = False;
838 p = strrchr_m(dir2,'/');
839 if (p == NULL) {
840 pstrcpy(mask,dir2);
841 *dir2 = 0;
842 } else {
843 *p = 0;
844 pstrcpy(mask,p+1);
847 p = strrchr_m(directory,'/');
848 if (!p)
849 *directory = 0;
850 else
851 *p = 0;
853 if (strlen(directory) == 0)
854 pstrcpy(directory,".");
855 memset((char *)status,'\0',21);
856 SCVAL(status,0,(dirtype & 0x1F));
857 } else {
858 int status_dirtype;
860 memcpy(status,p,21);
861 status_dirtype = CVAL(status,0) & 0x1F;
862 if (status_dirtype != (dirtype & 0x1F))
863 dirtype = status_dirtype;
865 conn->dirptr = dptr_fetch(status+12,&dptr_num);
866 if (!conn->dirptr)
867 goto SearchEmpty;
868 string_set(&conn->dirpath,dptr_path(dptr_num));
869 pstrcpy(mask, dptr_wcard(dptr_num));
872 if (can_open) {
873 p = smb_buf(outbuf) + 3;
874 ok = True;
876 if (status_len == 0) {
877 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
878 if (dptr_num < 0) {
879 if(dptr_num == -2) {
880 END_PROFILE(SMBsearch);
881 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnofids);
883 END_PROFILE(SMBsearch);
884 return ERROR_DOS(ERRDOS,ERRnofids);
886 dptr_set_wcard(dptr_num, strdup(mask));
887 dptr_set_attr(dptr_num, dirtype);
888 } else {
889 dirtype = dptr_attr(dptr_num);
892 DEBUG(4,("dptr_num is %d\n",dptr_num));
894 if (ok) {
895 if ((dirtype&0x1F) == aVOLID) {
896 memcpy(p,status,21);
897 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0,conn->case_sensitive);
898 dptr_fill(p+12,dptr_num);
899 if (dptr_zero(p+12) && (status_len==0))
900 numentries = 1;
901 else
902 numentries = 0;
903 p += DIR_STRUCT_SIZE;
904 } else {
905 unsigned int i;
906 maxentries = MIN(maxentries, ((BUFFER_SIZE - (p - outbuf))/DIR_STRUCT_SIZE));
908 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
909 conn->dirpath,lp_dontdescend(SNUM(conn))));
910 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
911 check_descend = True;
913 for (i=numentries;(i<maxentries) && !finished;i++) {
914 finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
915 if (!finished) {
916 memcpy(p,status,21);
917 make_dir_struct(p,mask,fname,size,mode,date,conn->case_sensitive);
918 dptr_fill(p+12,dptr_num);
919 numentries++;
921 p += DIR_STRUCT_SIZE;
924 } /* if (ok ) */
928 SearchEmpty:
930 /* If we were called as SMBffirst with smb_search_id == NULL
931 and no entries were found then return error and close dirptr
932 (X/Open spec) */
934 if(ok && expect_close && numentries == 0 && status_len == 0) {
935 if (Protocol < PROTOCOL_NT1) {
936 SCVAL(outbuf,smb_rcls,ERRDOS);
937 SSVAL(outbuf,smb_err,ERRnofiles);
939 /* Also close the dptr - we know it's gone */
940 dptr_close(&dptr_num);
941 } else if (numentries == 0 || !ok) {
942 if (Protocol < PROTOCOL_NT1) {
943 SCVAL(outbuf,smb_rcls,ERRDOS);
944 SSVAL(outbuf,smb_err,ERRnofiles);
946 dptr_close(&dptr_num);
949 /* If we were called as SMBfunique, then we can close the dirptr now ! */
950 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
951 dptr_close(&dptr_num);
953 SSVAL(outbuf,smb_vwv0,numentries);
954 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
955 SCVAL(smb_buf(outbuf),0,5);
956 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
958 if (Protocol >= PROTOCOL_NT1)
959 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
961 outsize += DIR_STRUCT_SIZE*numentries;
962 smb_setlen(outbuf,outsize - 4);
964 if ((! *directory) && dptr_path(dptr_num))
965 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
967 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
968 smb_fn_name(CVAL(inbuf,smb_com)),
969 mask, directory, dirtype, numentries, maxentries ) );
971 END_PROFILE(SMBsearch);
972 return(outsize);
975 /****************************************************************************
976 Reply to a fclose (stop directory search).
977 ****************************************************************************/
979 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
981 int outsize = 0;
982 int status_len;
983 pstring path;
984 char status[21];
985 int dptr_num= -2;
986 char *p;
987 NTSTATUS err;
989 START_PROFILE(SMBfclose);
991 outsize = set_message(outbuf,1,0,True);
992 p = smb_buf(inbuf) + 1;
993 p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err, True);
994 if (!NT_STATUS_IS_OK(err)) {
995 END_PROFILE(SMBfclose);
996 return ERROR_NT(err);
998 p++;
999 status_len = SVAL(p,0);
1000 p += 2;
1002 if (status_len == 0) {
1003 END_PROFILE(SMBfclose);
1004 return ERROR_DOS(ERRSRV,ERRsrverror);
1007 memcpy(status,p,21);
1009 if(dptr_fetch(status+12,&dptr_num)) {
1010 /* Close the dptr - we know it's gone */
1011 dptr_close(&dptr_num);
1014 SSVAL(outbuf,smb_vwv0,0);
1016 DEBUG(3,("search close\n"));
1018 END_PROFILE(SMBfclose);
1019 return(outsize);
1022 /****************************************************************************
1023 Reply to an open.
1024 ****************************************************************************/
1026 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1028 pstring fname;
1029 int outsize = 0;
1030 int fmode=0;
1031 int share_mode;
1032 SMB_OFF_T size = 0;
1033 time_t mtime=0;
1034 int rmode=0;
1035 SMB_STRUCT_STAT sbuf;
1036 BOOL bad_path = False;
1037 files_struct *fsp;
1038 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1039 uint16 dos_attr = SVAL(inbuf,smb_vwv1);
1040 NTSTATUS status;
1041 START_PROFILE(SMBopen);
1043 share_mode = SVAL(inbuf,smb_vwv0);
1045 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status, False);
1046 if (!NT_STATUS_IS_OK(status)) {
1047 END_PROFILE(SMBopen);
1048 return ERROR_NT(status);
1051 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1053 unix_convert(fname,conn,0,&bad_path,&sbuf);
1054 if (bad_path) {
1055 END_PROFILE(SMBopen);
1056 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1059 fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1060 (uint32)dos_attr, oplock_request,&rmode,NULL);
1062 if (!fsp) {
1063 END_PROFILE(SMBopen);
1064 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1065 /* We have re-scheduled this call. */
1066 clear_cached_errors();
1067 return -1;
1069 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1072 size = sbuf.st_size;
1073 fmode = dos_mode(conn,fname,&sbuf);
1074 mtime = sbuf.st_mtime;
1076 if (fmode & aDIR) {
1077 DEBUG(3,("attempt to open a directory %s\n",fname));
1078 close_file(fsp,False);
1079 END_PROFILE(SMBopen);
1080 return ERROR_DOS(ERRDOS,ERRnoaccess);
1083 outsize = set_message(outbuf,7,0,True);
1084 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1085 SSVAL(outbuf,smb_vwv1,fmode);
1086 if(lp_dos_filetime_resolution(SNUM(conn)) )
1087 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1088 else
1089 put_dos_date3(outbuf,smb_vwv2,mtime);
1090 SIVAL(outbuf,smb_vwv4,(uint32)size);
1091 SSVAL(outbuf,smb_vwv6,rmode);
1093 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1094 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1096 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1097 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1098 END_PROFILE(SMBopen);
1099 return(outsize);
1102 /****************************************************************************
1103 Reply to an open and X.
1104 ****************************************************************************/
1106 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1108 pstring fname;
1109 int smb_mode = SVAL(inbuf,smb_vwv3);
1110 int smb_attr = SVAL(inbuf,smb_vwv5);
1111 /* Breakout the oplock request bits so we can set the
1112 reply bits separately. */
1113 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1114 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1115 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1116 #if 0
1117 int open_flags = SVAL(inbuf,smb_vwv2);
1118 int smb_sattr = SVAL(inbuf,smb_vwv4);
1119 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1120 #endif
1121 int smb_ofun = SVAL(inbuf,smb_vwv8);
1122 SMB_OFF_T size=0;
1123 int fmode=0,mtime=0,rmode=0;
1124 SMB_STRUCT_STAT sbuf;
1125 int smb_action = 0;
1126 BOOL bad_path = False;
1127 files_struct *fsp;
1128 NTSTATUS status;
1129 START_PROFILE(SMBopenX);
1131 /* If it's an IPC, pass off the pipe handler. */
1132 if (IS_IPC(conn)) {
1133 if (lp_nt_pipe_support()) {
1134 END_PROFILE(SMBopenX);
1135 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1136 } else {
1137 END_PROFILE(SMBopenX);
1138 return ERROR_DOS(ERRSRV,ERRaccess);
1142 /* XXXX we need to handle passed times, sattr and flags */
1143 srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status, False);
1144 if (!NT_STATUS_IS_OK(status)) {
1145 END_PROFILE(SMBopenX);
1146 return ERROR_NT(status);
1149 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1151 unix_convert(fname,conn,0,&bad_path,&sbuf);
1152 if (bad_path) {
1153 END_PROFILE(SMBopenX);
1154 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1157 fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,(uint32)smb_attr,
1158 oplock_request, &rmode,&smb_action);
1160 if (!fsp) {
1161 END_PROFILE(SMBopenX);
1162 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1163 /* We have re-scheduled this call. */
1164 clear_cached_errors();
1165 return -1;
1167 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1170 size = sbuf.st_size;
1171 fmode = dos_mode(conn,fname,&sbuf);
1172 mtime = sbuf.st_mtime;
1173 if (fmode & aDIR) {
1174 close_file(fsp,False);
1175 END_PROFILE(SMBopenX);
1176 return ERROR_DOS(ERRDOS,ERRnoaccess);
1179 /* If the caller set the extended oplock request bit
1180 and we granted one (by whatever means) - set the
1181 correct bit for extended oplock reply.
1184 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn)))
1185 smb_action |= EXTENDED_OPLOCK_GRANTED;
1187 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1188 smb_action |= EXTENDED_OPLOCK_GRANTED;
1190 /* If the caller set the core oplock request bit
1191 and we granted one (by whatever means) - set the
1192 correct bit for core oplock reply.
1195 if (core_oplock_request && lp_fake_oplocks(SNUM(conn)))
1196 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1198 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1199 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1201 set_message(outbuf,15,0,True);
1202 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1203 SSVAL(outbuf,smb_vwv3,fmode);
1204 if(lp_dos_filetime_resolution(SNUM(conn)) )
1205 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1206 else
1207 put_dos_date3(outbuf,smb_vwv4,mtime);
1208 SIVAL(outbuf,smb_vwv6,(uint32)size);
1209 SSVAL(outbuf,smb_vwv8,rmode);
1210 SSVAL(outbuf,smb_vwv11,smb_action);
1212 END_PROFILE(SMBopenX);
1213 return chain_reply(inbuf,outbuf,length,bufsize);
1216 /****************************************************************************
1217 Reply to a SMBulogoffX.
1218 ****************************************************************************/
1220 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1222 uint16 vuid = SVAL(inbuf,smb_uid);
1223 user_struct *vuser = get_valid_user_struct(vuid);
1224 START_PROFILE(SMBulogoffX);
1226 if(vuser == 0)
1227 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1229 /* in user level security we are supposed to close any files
1230 open by this user */
1231 if ((vuser != 0) && (lp_security() != SEC_SHARE))
1232 file_close_user(vuid);
1234 invalidate_vuid(vuid);
1236 set_message(outbuf,2,0,True);
1238 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1240 END_PROFILE(SMBulogoffX);
1241 return chain_reply(inbuf,outbuf,length,bufsize);
1244 /****************************************************************************
1245 Reply to a mknew or a create.
1246 ****************************************************************************/
1248 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1250 pstring fname;
1251 int com;
1252 int outsize = 0;
1253 int createmode;
1254 int ofun = 0;
1255 BOOL bad_path = False;
1256 files_struct *fsp;
1257 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1258 SMB_STRUCT_STAT sbuf;
1259 NTSTATUS status;
1260 START_PROFILE(SMBcreate);
1262 com = SVAL(inbuf,smb_com);
1264 createmode = SVAL(inbuf,smb_vwv0);
1265 srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status, False);
1266 if (!NT_STATUS_IS_OK(status)) {
1267 END_PROFILE(SMBcreate);
1268 return ERROR_NT(status);
1271 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1273 unix_convert(fname,conn,0,&bad_path,&sbuf);
1274 if (bad_path) {
1275 END_PROFILE(SMBcreate);
1276 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1279 if (createmode & aVOLID)
1280 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1282 if(com == SMBmknew) {
1283 /* We should fail if file exists. */
1284 ofun = FILE_CREATE_IF_NOT_EXIST;
1285 } else {
1286 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1287 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1290 /* Open file in dos compatibility share mode. */
1291 fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1292 ofun, (uint32)createmode, oplock_request, NULL, NULL);
1294 if (!fsp) {
1295 END_PROFILE(SMBcreate);
1296 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1297 /* We have re-scheduled this call. */
1298 clear_cached_errors();
1299 return -1;
1301 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1304 outsize = set_message(outbuf,1,0,True);
1305 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1307 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1308 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1310 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1311 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1313 DEBUG( 2, ( "new file %s\n", fname ) );
1314 DEBUG( 3, ( "mknew %s fd=%d dmode=%d\n", fname, fsp->fd, createmode ) );
1316 END_PROFILE(SMBcreate);
1317 return(outsize);
1320 /****************************************************************************
1321 Reply to a create temporary file.
1322 ****************************************************************************/
1324 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1326 pstring fname;
1327 int outsize = 0;
1328 int createattr;
1329 BOOL bad_path = False;
1330 files_struct *fsp;
1331 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1332 int tmpfd;
1333 SMB_STRUCT_STAT sbuf;
1334 char *p, *s;
1335 NTSTATUS status;
1336 unsigned int namelen;
1338 START_PROFILE(SMBctemp);
1340 createattr = SVAL(inbuf,smb_vwv0);
1341 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status, False);
1342 if (!NT_STATUS_IS_OK(status)) {
1343 END_PROFILE(SMBctemp);
1344 return ERROR_NT(status);
1346 if (*fname) {
1347 pstrcat(fname,"/TMXXXXXX");
1348 } else {
1349 pstrcat(fname,"TMXXXXXX");
1352 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1354 unix_convert(fname,conn,0,&bad_path,&sbuf);
1355 if (bad_path) {
1356 END_PROFILE(SMBctemp);
1357 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1360 tmpfd = smb_mkstemp(fname);
1361 if (tmpfd == -1) {
1362 END_PROFILE(SMBctemp);
1363 return(UNIXERROR(ERRDOS,ERRnoaccess));
1366 SMB_VFS_STAT(conn,fname,&sbuf);
1368 /* Open file in dos compatibility share mode. */
1369 /* We should fail if file does not exist. */
1370 fsp = open_file_shared(conn,fname,&sbuf,
1371 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1372 FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
1373 (uint32)createattr, oplock_request, NULL, NULL);
1375 /* close fd from smb_mkstemp() */
1376 close(tmpfd);
1378 if (!fsp) {
1379 END_PROFILE(SMBctemp);
1380 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1381 /* We have re-scheduled this call. */
1382 clear_cached_errors();
1383 return -1;
1385 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1388 outsize = set_message(outbuf,1,0,True);
1389 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1391 /* the returned filename is relative to the directory */
1392 s = strrchr_m(fname, '/');
1393 if (!s)
1394 s = fname;
1395 else
1396 s++;
1398 p = smb_buf(outbuf);
1399 #if 0
1400 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
1401 thing in the byte section. JRA */
1402 SSVALS(p, 0, -1); /* what is this? not in spec */
1403 #endif
1404 namelen = srvstr_push(outbuf, p, s, -1, STR_ASCII|STR_TERMINATE);
1405 p += namelen;
1406 outsize = set_message_end(outbuf, p);
1408 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1409 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1411 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1412 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1414 DEBUG( 2, ( "created temp file %s\n", fname ) );
1415 DEBUG( 3, ( "ctemp %s fd=%d umode=%o\n",
1416 fname, fsp->fd, sbuf.st_mode ) );
1418 END_PROFILE(SMBctemp);
1419 return(outsize);
1422 /*******************************************************************
1423 Check if a user is allowed to rename a file.
1424 ********************************************************************/
1426 static NTSTATUS can_rename(char *fname,connection_struct *conn, uint16 dirtype, SMB_STRUCT_STAT *pst)
1428 int smb_action;
1429 int access_mode;
1430 files_struct *fsp;
1431 uint16 fmode;
1433 if (!CAN_WRITE(conn))
1434 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1436 fmode = dos_mode(conn,fname,pst);
1437 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1438 return NT_STATUS_NO_SUCH_FILE;
1440 if (S_ISDIR(pst->st_mode))
1441 return NT_STATUS_OK;
1443 /* We need a better way to return NT status codes from open... */
1444 unix_ERR_class = 0;
1445 unix_ERR_code = 0;
1447 fsp = open_file_shared1(conn, fname, pst, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1448 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action);
1450 if (!fsp) {
1451 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1452 if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1453 ret = NT_STATUS_SHARING_VIOLATION;
1454 unix_ERR_class = 0;
1455 unix_ERR_code = 0;
1456 unix_ERR_ntstatus = NT_STATUS_OK;
1457 return ret;
1459 close_file(fsp,False);
1460 return NT_STATUS_OK;
1463 /*******************************************************************
1464 Check if a user is allowed to delete a file.
1465 ********************************************************************/
1467 static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype, BOOL bad_path)
1469 SMB_STRUCT_STAT sbuf;
1470 int fmode;
1471 int smb_action;
1472 int access_mode;
1473 files_struct *fsp;
1475 DEBUG(10,("can_delete: %s, dirtype = %d\n",
1476 fname, dirtype ));
1478 if (!CAN_WRITE(conn))
1479 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1481 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
1482 if(errno == ENOENT) {
1483 if (bad_path)
1484 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1485 else
1486 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1488 return map_nt_error_from_unix(errno);
1491 fmode = dos_mode(conn,fname,&sbuf);
1493 /* Can't delete a directory. */
1494 if (fmode & aDIR)
1495 return NT_STATUS_FILE_IS_A_DIRECTORY;
1496 #if 0 /* JRATEST */
1497 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
1498 return NT_STATUS_OBJECT_NAME_INVALID;
1499 #endif /* JRATEST */
1501 if (!lp_delete_readonly(SNUM(conn))) {
1502 if (fmode & aRONLY)
1503 return NT_STATUS_CANNOT_DELETE;
1505 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1506 return NT_STATUS_NO_SUCH_FILE;
1508 /* We need a better way to return NT status codes from open... */
1509 unix_ERR_class = 0;
1510 unix_ERR_code = 0;
1512 fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1513 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action);
1515 if (!fsp) {
1516 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1517 if (!NT_STATUS_IS_OK(unix_ERR_ntstatus))
1518 ret = unix_ERR_ntstatus;
1519 else if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1520 ret = NT_STATUS_SHARING_VIOLATION;
1521 unix_ERR_class = 0;
1522 unix_ERR_code = 0;
1523 unix_ERR_ntstatus = NT_STATUS_OK;
1524 return ret;
1526 close_file(fsp,False);
1527 return NT_STATUS_OK;
1530 /****************************************************************************
1531 The guts of the unlink command, split out so it may be called by the NT SMB
1532 code.
1533 ****************************************************************************/
1535 NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
1537 pstring directory;
1538 pstring mask;
1539 char *p;
1540 int count=0;
1541 NTSTATUS error = NT_STATUS_OK;
1542 BOOL has_wild;
1543 BOOL bad_path = False;
1544 BOOL rc = True;
1545 SMB_STRUCT_STAT sbuf;
1547 *directory = *mask = 0;
1549 /* We must check for wildcards in the name given
1550 * directly by the client - before any unmangling.
1551 * This prevents an unmangling of a UNIX name containing
1552 * a DOS wildcard like '*' or '?' from unmangling into
1553 * a wildcard delete which was not intended.
1554 * FIX for #226. JRA.
1557 has_wild = ms_has_wild(name);
1559 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1561 p = strrchr_m(name,'/');
1562 if (!p) {
1563 pstrcpy(directory,".");
1564 pstrcpy(mask,name);
1565 } else {
1566 *p = 0;
1567 pstrcpy(directory,name);
1568 pstrcpy(mask,p+1);
1572 * We should only check the mangled cache
1573 * here if unix_convert failed. This means
1574 * that the path in 'mask' doesn't exist
1575 * on the file system and so we need to look
1576 * for a possible mangle. This patch from
1577 * Tine Smukavec <valentin.smukavec@hermes.si>.
1580 if (!rc && mangle_is_mangled(mask))
1581 mangle_check_cache( mask, sizeof(pstring)-1 );
1583 if (!has_wild) {
1584 pstrcat(directory,"/");
1585 pstrcat(directory,mask);
1586 error = can_delete(directory,conn,dirtype,bad_path);
1587 if (!NT_STATUS_IS_OK(error))
1588 return error;
1590 if (SMB_VFS_UNLINK(conn,directory) == 0) {
1591 count++;
1593 } else {
1594 void *dirptr = NULL;
1595 const char *dname;
1597 if (check_name(directory,conn))
1598 dirptr = OpenDir(conn, directory, True);
1600 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1601 the pattern matches against the long name, otherwise the short name
1602 We don't implement this yet XXXX
1605 if (dirptr) {
1606 error = NT_STATUS_NO_SUCH_FILE;
1608 if (strequal(mask,"????????.???"))
1609 pstrcpy(mask,"*");
1611 while ((dname = ReadDirName(dirptr))) {
1612 pstring fname;
1613 BOOL sys_direntry = False;
1614 pstrcpy(fname,dname);
1616 /* Quick check for "." and ".." */
1617 if (fname[0] == '.') {
1618 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
1619 if ((dirtype & FILE_ATTRIBUTE_DIRECTORY) && (dirtype & FILE_ATTRIBUTE_SYSTEM)) {
1620 sys_direntry = True;
1621 } else {
1622 continue;
1627 if(!mask_match(fname, mask, conn->case_sensitive))
1628 continue;
1630 if (sys_direntry) {
1631 error = NT_STATUS_OBJECT_NAME_INVALID;
1632 DEBUG(3,("unlink_internals: system directory delete denied [%s] mask [%s]\n",
1633 fname, mask));
1634 break;
1637 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1638 error = can_delete(fname,conn,dirtype,bad_path);
1639 if (!NT_STATUS_IS_OK(error)) {
1640 continue;
1642 if (SMB_VFS_UNLINK(conn,fname) == 0)
1643 count++;
1644 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
1646 CloseDir(dirptr);
1650 if (count == 0 && NT_STATUS_IS_OK(error)) {
1651 error = map_nt_error_from_unix(errno);
1654 return error;
1657 /****************************************************************************
1658 Reply to a unlink
1659 ****************************************************************************/
1661 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
1662 int dum_buffsize)
1664 int outsize = 0;
1665 pstring name;
1666 int dirtype;
1667 NTSTATUS status;
1668 START_PROFILE(SMBunlink);
1670 dirtype = SVAL(inbuf,smb_vwv0);
1672 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, True);
1673 if (!NT_STATUS_IS_OK(status)) {
1674 END_PROFILE(SMBunlink);
1675 return ERROR_NT(status);
1678 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1680 DEBUG(3,("reply_unlink : %s\n",name));
1682 status = unlink_internals(conn, dirtype, name);
1683 if (!NT_STATUS_IS_OK(status)) {
1684 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1685 /* We have re-scheduled this call. */
1686 clear_cached_errors();
1687 return -1;
1689 return ERROR_NT(status);
1693 * Win2k needs a changenotify request response before it will
1694 * update after a rename..
1696 process_pending_change_notify_queue((time_t)0);
1698 outsize = set_message(outbuf,0,0,True);
1700 END_PROFILE(SMBunlink);
1701 return outsize;
1704 /****************************************************************************
1705 Fail for readbraw.
1706 ****************************************************************************/
1708 void fail_readraw(void)
1710 pstring errstr;
1711 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
1712 strerror(errno) );
1713 exit_server(errstr);
1716 /****************************************************************************
1717 Use sendfile in readbraw.
1718 ****************************************************************************/
1720 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
1721 ssize_t mincount, char *outbuf)
1723 ssize_t ret=0;
1725 #if defined(WITH_SENDFILE)
1727 * We can only use sendfile on a non-chained packet
1728 * but we can use on a non-oplocked file. tridge proved this
1729 * on a train in Germany :-). JRA.
1730 * reply_readbraw has already checked the length.
1733 if (chain_size ==0 && (nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) && lp_use_sendfile(SNUM(conn)) ) {
1734 DATA_BLOB header;
1736 _smb_setlen(outbuf,nread);
1737 header.data = outbuf;
1738 header.length = 4;
1739 header.free = NULL;
1741 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) {
1743 * Special hack for broken Linux with no 64 bit clean sendfile. If we
1744 * return ENOSYS then pretend we just got a normal read.
1746 if (errno == ENOSYS) {
1747 set_use_sendfile(SNUM(conn), False);
1748 goto normal_read;
1751 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
1752 fsp->fsp_name, strerror(errno) ));
1753 exit_server("send_file_readbraw sendfile failed");
1758 normal_read:
1759 #endif
1761 if (nread > 0) {
1762 ret = read_file(fsp,outbuf+4,startpos,nread);
1763 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1764 if (ret < mincount)
1765 ret = 0;
1766 #else
1767 if (ret < nread)
1768 ret = 0;
1769 #endif
1772 _smb_setlen(outbuf,ret);
1773 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
1774 fail_readraw();
1777 /****************************************************************************
1778 Reply to a readbraw (core+ protocol).
1779 ****************************************************************************/
1781 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
1783 extern struct current_user current_user;
1784 ssize_t maxcount,mincount;
1785 size_t nread = 0;
1786 SMB_OFF_T startpos;
1787 char *header = outbuf;
1788 files_struct *fsp;
1789 START_PROFILE(SMBreadbraw);
1791 if (srv_is_signing_active()) {
1792 exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
1796 * Special check if an oplock break has been issued
1797 * and the readraw request croses on the wire, we must
1798 * return a zero length response here.
1801 if(global_oplock_break) {
1802 _smb_setlen(header,0);
1803 if (write_data(smbd_server_fd(),header,4) != 4)
1804 fail_readraw();
1805 DEBUG(5,("readbraw - oplock break finished\n"));
1806 END_PROFILE(SMBreadbraw);
1807 return -1;
1810 fsp = file_fsp(inbuf,smb_vwv0);
1812 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1814 * fsp could be NULL here so use the value from the packet. JRA.
1816 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
1817 _smb_setlen(header,0);
1818 if (write_data(smbd_server_fd(),header,4) != 4)
1819 fail_readraw();
1820 END_PROFILE(SMBreadbraw);
1821 return(-1);
1824 CHECK_FSP(fsp,conn);
1826 flush_write_cache(fsp, READRAW_FLUSH);
1828 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
1829 if(CVAL(inbuf,smb_wct) == 10) {
1831 * This is a large offset (64 bit) read.
1833 #ifdef LARGE_SMB_OFF_T
1835 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
1837 #else /* !LARGE_SMB_OFF_T */
1840 * Ensure we haven't been sent a >32 bit offset.
1843 if(IVAL(inbuf,smb_vwv8) != 0) {
1844 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
1845 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
1846 _smb_setlen(header,0);
1847 if (write_data(smbd_server_fd(),header,4) != 4)
1848 fail_readraw();
1849 END_PROFILE(SMBreadbraw);
1850 return(-1);
1853 #endif /* LARGE_SMB_OFF_T */
1855 if(startpos < 0) {
1856 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
1857 _smb_setlen(header,0);
1858 if (write_data(smbd_server_fd(),header,4) != 4)
1859 fail_readraw();
1860 END_PROFILE(SMBreadbraw);
1861 return(-1);
1864 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
1865 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
1867 /* ensure we don't overrun the packet size */
1868 maxcount = MIN(65535,maxcount);
1870 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1871 SMB_OFF_T size = fsp->size;
1872 SMB_OFF_T sizeneeded = startpos + maxcount;
1874 if (size < sizeneeded) {
1875 SMB_STRUCT_STAT st;
1876 if (SMB_VFS_FSTAT(fsp,fsp->fd,&st) == 0)
1877 size = st.st_size;
1878 if (!fsp->can_write)
1879 fsp->size = size;
1882 if (startpos >= size)
1883 nread = 0;
1884 else
1885 nread = MIN(maxcount,(size - startpos));
1888 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1889 if (nread < mincount)
1890 nread = 0;
1891 #endif
1893 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
1894 (int)maxcount, (int)mincount, (int)nread ) );
1896 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf);
1898 DEBUG(5,("readbraw finished\n"));
1899 END_PROFILE(SMBreadbraw);
1900 return -1;
1903 /****************************************************************************
1904 Reply to a lockread (core+ protocol).
1905 ****************************************************************************/
1907 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
1909 ssize_t nread = -1;
1910 char *data;
1911 int outsize = 0;
1912 SMB_OFF_T startpos;
1913 size_t numtoread;
1914 NTSTATUS status;
1915 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1916 BOOL my_lock_ctx = False;
1917 START_PROFILE(SMBlockread);
1919 CHECK_FSP(fsp,conn);
1920 CHECK_READ(fsp);
1922 release_level_2_oplocks_on_change(fsp);
1924 numtoread = SVAL(inbuf,smb_vwv1);
1925 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
1927 outsize = set_message(outbuf,5,3,True);
1928 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1929 data = smb_buf(outbuf) + 3;
1932 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
1933 * protocol request that predates the read/write lock concept.
1934 * Thus instead of asking for a read lock here we need to ask
1935 * for a write lock. JRA.
1936 * Note that the requested lock size is unaffected by max_recv.
1939 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid),
1940 (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, &my_lock_ctx);
1942 if (NT_STATUS_V(status)) {
1943 #if 0
1945 * We used to make lockread a blocking lock. It turns out
1946 * that this isn't on W2k. Found by the Samba 4 RAW-READ torture
1947 * tester. JRA.
1950 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
1952 * A blocking lock was requested. Package up
1953 * this smb into a queued request and push it
1954 * onto the blocking lock queue.
1956 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)startpos,
1957 (SMB_BIG_UINT)numtoread)) {
1958 END_PROFILE(SMBlockread);
1959 return -1;
1962 #endif
1963 END_PROFILE(SMBlockread);
1964 return ERROR_NT(status);
1968 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
1971 if (numtoread > max_recv) {
1972 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
1973 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
1974 (unsigned int)numtoread, (unsigned int)max_recv ));
1975 numtoread = MIN(numtoread,max_recv);
1977 nread = read_file(fsp,data,startpos,numtoread);
1979 if (nread < 0) {
1980 END_PROFILE(SMBlockread);
1981 return(UNIXERROR(ERRDOS,ERRnoaccess));
1984 outsize += nread;
1985 SSVAL(outbuf,smb_vwv0,nread);
1986 SSVAL(outbuf,smb_vwv5,nread+3);
1987 SSVAL(smb_buf(outbuf),1,nread);
1989 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
1990 fsp->fnum, (int)numtoread, (int)nread));
1992 END_PROFILE(SMBlockread);
1993 return(outsize);
1996 /****************************************************************************
1997 Reply to a read.
1998 ****************************************************************************/
2000 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2002 size_t numtoread;
2003 ssize_t nread = 0;
2004 char *data;
2005 SMB_OFF_T startpos;
2006 int outsize = 0;
2007 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2008 START_PROFILE(SMBread);
2010 CHECK_FSP(fsp,conn);
2011 CHECK_READ(fsp);
2013 numtoread = SVAL(inbuf,smb_vwv1);
2014 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2016 outsize = set_message(outbuf,5,3,True);
2017 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2019 * The requested read size cannot be greater than max_recv. JRA.
2021 if (numtoread > max_recv) {
2022 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
2023 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2024 (unsigned int)numtoread, (unsigned int)max_recv ));
2025 numtoread = MIN(numtoread,max_recv);
2028 data = smb_buf(outbuf) + 3;
2030 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
2031 END_PROFILE(SMBread);
2032 return ERROR_DOS(ERRDOS,ERRlock);
2035 if (numtoread > 0)
2036 nread = read_file(fsp,data,startpos,numtoread);
2038 if (nread < 0) {
2039 END_PROFILE(SMBread);
2040 return(UNIXERROR(ERRDOS,ERRnoaccess));
2043 outsize += nread;
2044 SSVAL(outbuf,smb_vwv0,nread);
2045 SSVAL(outbuf,smb_vwv5,nread+3);
2046 SCVAL(smb_buf(outbuf),0,1);
2047 SSVAL(smb_buf(outbuf),1,nread);
2049 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2050 fsp->fnum, (int)numtoread, (int)nread ) );
2052 END_PROFILE(SMBread);
2053 return(outsize);
2056 /****************************************************************************
2057 Reply to a read and X - possibly using sendfile.
2058 ****************************************************************************/
2060 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length,
2061 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
2063 ssize_t nread = -1;
2064 char *data = smb_buf(outbuf);
2066 #if defined(WITH_SENDFILE)
2068 * We can only use sendfile on a non-chained packet
2069 * but we can use on a non-oplocked file. tridge proved this
2070 * on a train in Germany :-). JRA.
2073 if (chain_size ==0 && (CVAL(inbuf,smb_vwv0) == 0xFF) && lp_use_sendfile(SNUM(conn)) &&
2074 (lp_write_cache_size(SNUM(conn)) == 0) ) {
2075 SMB_STRUCT_STAT sbuf;
2076 DATA_BLOB header;
2078 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1)
2079 return(UNIXERROR(ERRDOS,ERRnoaccess));
2081 if (startpos > sbuf.st_size)
2082 goto normal_read;
2084 if (smb_maxcnt > (sbuf.st_size - startpos))
2085 smb_maxcnt = (sbuf.st_size - startpos);
2087 if (smb_maxcnt == 0)
2088 goto normal_read;
2091 * Set up the packet header before send. We
2092 * assume here the sendfile will work (get the
2093 * correct amount of data).
2096 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2097 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
2098 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2099 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
2100 SCVAL(outbuf,smb_vwv0,0xFF);
2101 set_message(outbuf,12,smb_maxcnt,False);
2102 header.data = outbuf;
2103 header.length = data - outbuf;
2104 header.free = NULL;
2106 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt) == -1) {
2108 * Special hack for broken Linux with no 64 bit clean sendfile. If we
2109 * return ENOSYS then pretend we just got a normal read.
2111 if (errno == ENOSYS) {
2112 set_use_sendfile(SNUM(conn), False);
2113 goto normal_read;
2116 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2117 fsp->fsp_name, strerror(errno) ));
2118 exit_server("send_file_readX sendfile failed");
2121 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2122 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2123 return -1;
2126 normal_read:
2128 #endif
2130 nread = read_file(fsp,data,startpos,smb_maxcnt);
2132 if (nread < 0) {
2133 END_PROFILE(SMBreadX);
2134 return(UNIXERROR(ERRDOS,ERRnoaccess));
2137 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2138 SSVAL(outbuf,smb_vwv5,nread);
2139 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2140 SSVAL(smb_buf(outbuf),-2,nread);
2142 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2143 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2145 return nread;
2148 /****************************************************************************
2149 Reply to a read and X.
2150 ****************************************************************************/
2152 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2154 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2155 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2156 ssize_t nread = -1;
2157 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2158 #if 0
2159 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2160 #endif
2162 START_PROFILE(SMBreadX);
2164 /* If it's an IPC, pass off the pipe handler. */
2165 if (IS_IPC(conn)) {
2166 END_PROFILE(SMBreadX);
2167 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2170 CHECK_FSP(fsp,conn);
2171 CHECK_READ(fsp);
2173 set_message(outbuf,12,0,True);
2175 if(CVAL(inbuf,smb_wct) == 12) {
2176 #ifdef LARGE_SMB_OFF_T
2178 * This is a large offset (64 bit) read.
2180 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2182 #else /* !LARGE_SMB_OFF_T */
2185 * Ensure we haven't been sent a >32 bit offset.
2188 if(IVAL(inbuf,smb_vwv10) != 0) {
2189 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2190 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2191 END_PROFILE(SMBreadX);
2192 return ERROR_DOS(ERRDOS,ERRbadaccess);
2195 #endif /* LARGE_SMB_OFF_T */
2199 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
2200 END_PROFILE(SMBreadX);
2201 return ERROR_DOS(ERRDOS,ERRlock);
2204 nread = send_file_readX(conn, inbuf, outbuf, length, fsp, startpos, smb_maxcnt);
2205 if (nread != -1)
2206 nread = chain_reply(inbuf,outbuf,length,bufsize);
2208 END_PROFILE(SMBreadX);
2209 return nread;
2212 /****************************************************************************
2213 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2214 ****************************************************************************/
2216 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2218 ssize_t nwritten=0;
2219 ssize_t total_written=0;
2220 size_t numtowrite=0;
2221 size_t tcount;
2222 SMB_OFF_T startpos;
2223 char *data=NULL;
2224 BOOL write_through;
2225 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2226 int outsize = 0;
2227 START_PROFILE(SMBwritebraw);
2229 if (srv_is_signing_active()) {
2230 exit_server("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2233 CHECK_FSP(fsp,conn);
2234 CHECK_WRITE(fsp);
2236 tcount = IVAL(inbuf,smb_vwv1);
2237 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2238 write_through = BITSETW(inbuf+smb_vwv7,0);
2240 /* We have to deal with slightly different formats depending
2241 on whether we are using the core+ or lanman1.0 protocol */
2243 if(Protocol <= PROTOCOL_COREPLUS) {
2244 numtowrite = SVAL(smb_buf(inbuf),-2);
2245 data = smb_buf(inbuf);
2246 } else {
2247 numtowrite = SVAL(inbuf,smb_vwv10);
2248 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2251 /* force the error type */
2252 SCVAL(inbuf,smb_com,SMBwritec);
2253 SCVAL(outbuf,smb_com,SMBwritec);
2255 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2256 END_PROFILE(SMBwritebraw);
2257 return(ERROR_DOS(ERRDOS,ERRlock));
2260 if (numtowrite>0)
2261 nwritten = write_file(fsp,data,startpos,numtowrite);
2263 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2264 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2266 if (nwritten < (ssize_t)numtowrite) {
2267 END_PROFILE(SMBwritebraw);
2268 return(UNIXERROR(ERRHRD,ERRdiskfull));
2271 total_written = nwritten;
2273 /* Return a message to the redirector to tell it to send more bytes */
2274 SCVAL(outbuf,smb_com,SMBwritebraw);
2275 SSVALS(outbuf,smb_vwv0,-1);
2276 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2277 if (!send_smb(smbd_server_fd(),outbuf))
2278 exit_server("reply_writebraw: send_smb failed.");
2280 /* Now read the raw data into the buffer and write it */
2281 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2282 exit_server("secondary writebraw failed");
2285 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2286 numtowrite = smb_len(inbuf);
2288 /* Set up outbuf to return the correct return */
2289 outsize = set_message(outbuf,1,0,True);
2290 SCVAL(outbuf,smb_com,SMBwritec);
2291 SSVAL(outbuf,smb_vwv0,total_written);
2293 if (numtowrite != 0) {
2295 if (numtowrite > BUFFER_SIZE) {
2296 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2297 (unsigned int)numtowrite ));
2298 exit_server("secondary writebraw failed");
2301 if (tcount > nwritten+numtowrite) {
2302 DEBUG(3,("Client overestimated the write %d %d %d\n",
2303 (int)tcount,(int)nwritten,(int)numtowrite));
2306 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2307 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2308 strerror(errno) ));
2309 exit_server("secondary writebraw failed");
2312 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2314 if (nwritten < (ssize_t)numtowrite) {
2315 SCVAL(outbuf,smb_rcls,ERRHRD);
2316 SSVAL(outbuf,smb_err,ERRdiskfull);
2319 if (nwritten > 0)
2320 total_written += nwritten;
2323 if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn)))
2324 sync_file(conn,fsp);
2326 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2327 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2329 /* we won't return a status if write through is not selected - this follows what WfWg does */
2330 END_PROFILE(SMBwritebraw);
2331 if (!write_through && total_written==tcount) {
2333 #if RABBIT_PELLET_FIX
2335 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2336 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2338 if (!send_keepalive(smbd_server_fd()))
2339 exit_server("reply_writebraw: send of keepalive failed");
2340 #endif
2341 return(-1);
2344 return(outsize);
2347 /****************************************************************************
2348 Reply to a writeunlock (core+).
2349 ****************************************************************************/
2351 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
2352 int size, int dum_buffsize)
2354 ssize_t nwritten = -1;
2355 size_t numtowrite;
2356 SMB_OFF_T startpos;
2357 char *data;
2358 NTSTATUS status = NT_STATUS_OK;
2359 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2360 int outsize = 0;
2361 START_PROFILE(SMBwriteunlock);
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 (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos,
2371 WRITE_LOCK,False)) {
2372 END_PROFILE(SMBwriteunlock);
2373 return ERROR_DOS(ERRDOS,ERRlock);
2376 /* The special X/Open SMB protocol handling of
2377 zero length writes is *NOT* done for
2378 this call */
2379 if(numtowrite == 0)
2380 nwritten = 0;
2381 else
2382 nwritten = write_file(fsp,data,startpos,numtowrite);
2384 if (lp_syncalways(SNUM(conn)))
2385 sync_file(conn,fsp);
2387 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2388 END_PROFILE(SMBwriteunlock);
2389 return(UNIXERROR(ERRHRD,ERRdiskfull));
2392 if (numtowrite) {
2393 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite,
2394 (SMB_BIG_UINT)startpos);
2395 if (NT_STATUS_V(status)) {
2396 END_PROFILE(SMBwriteunlock);
2397 return ERROR_NT(status);
2401 outsize = set_message(outbuf,1,0,True);
2403 SSVAL(outbuf,smb_vwv0,nwritten);
2405 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2406 fsp->fnum, (int)numtowrite, (int)nwritten));
2408 END_PROFILE(SMBwriteunlock);
2409 return outsize;
2412 /****************************************************************************
2413 Reply to a write.
2414 ****************************************************************************/
2416 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2418 size_t numtowrite;
2419 ssize_t nwritten = -1;
2420 SMB_OFF_T startpos;
2421 char *data;
2422 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2423 int outsize = 0;
2424 START_PROFILE(SMBwrite);
2426 /* If it's an IPC, pass off the pipe handler. */
2427 if (IS_IPC(conn)) {
2428 END_PROFILE(SMBwrite);
2429 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2432 CHECK_FSP(fsp,conn);
2433 CHECK_WRITE(fsp);
2435 numtowrite = SVAL(inbuf,smb_vwv1);
2436 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2437 data = smb_buf(inbuf) + 3;
2439 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2440 END_PROFILE(SMBwrite);
2441 return ERROR_DOS(ERRDOS,ERRlock);
2445 * X/Open SMB protocol says that if smb_vwv1 is
2446 * zero then the file size should be extended or
2447 * truncated to the size given in smb_vwv[2-3].
2450 if(numtowrite == 0) {
2452 * This is actually an allocate call, and set EOF. JRA.
2454 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2455 if (nwritten < 0) {
2456 END_PROFILE(SMBwrite);
2457 return ERROR_NT(NT_STATUS_DISK_FULL);
2459 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2460 if (nwritten < 0) {
2461 END_PROFILE(SMBwrite);
2462 return ERROR_NT(NT_STATUS_DISK_FULL);
2464 } else
2465 nwritten = write_file(fsp,data,startpos,numtowrite);
2467 if (lp_syncalways(SNUM(conn)))
2468 sync_file(conn,fsp);
2470 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2471 END_PROFILE(SMBwrite);
2472 return(UNIXERROR(ERRHRD,ERRdiskfull));
2475 outsize = set_message(outbuf,1,0,True);
2477 SSVAL(outbuf,smb_vwv0,nwritten);
2479 if (nwritten < (ssize_t)numtowrite) {
2480 SCVAL(outbuf,smb_rcls,ERRHRD);
2481 SSVAL(outbuf,smb_err,ERRdiskfull);
2484 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2486 END_PROFILE(SMBwrite);
2487 return(outsize);
2490 /****************************************************************************
2491 Reply to a write and X.
2492 ****************************************************************************/
2494 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2496 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2497 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2498 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2499 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2500 ssize_t nwritten = -1;
2501 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2502 unsigned int smblen = smb_len(inbuf);
2503 char *data;
2504 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2505 START_PROFILE(SMBwriteX);
2507 /* If it's an IPC, pass off the pipe handler. */
2508 if (IS_IPC(conn)) {
2509 END_PROFILE(SMBwriteX);
2510 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2513 CHECK_FSP(fsp,conn);
2514 CHECK_WRITE(fsp);
2516 /* Deal with possible LARGE_WRITEX */
2517 if (large_writeX)
2518 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2520 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2521 END_PROFILE(SMBwriteX);
2522 return ERROR_DOS(ERRDOS,ERRbadmem);
2525 data = smb_base(inbuf) + smb_doff;
2527 if(CVAL(inbuf,smb_wct) == 14) {
2528 #ifdef LARGE_SMB_OFF_T
2530 * This is a large offset (64 bit) write.
2532 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2534 #else /* !LARGE_SMB_OFF_T */
2537 * Ensure we haven't been sent a >32 bit offset.
2540 if(IVAL(inbuf,smb_vwv12) != 0) {
2541 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2542 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2543 END_PROFILE(SMBwriteX);
2544 return ERROR_DOS(ERRDOS,ERRbadaccess);
2547 #endif /* LARGE_SMB_OFF_T */
2550 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2551 END_PROFILE(SMBwriteX);
2552 return ERROR_DOS(ERRDOS,ERRlock);
2555 /* X/Open SMB protocol says that, unlike SMBwrite
2556 if the length is zero then NO truncation is
2557 done, just a write of zero. To truncate a file,
2558 use SMBwrite. */
2560 if(numtowrite == 0)
2561 nwritten = 0;
2562 else
2563 nwritten = write_file(fsp,data,startpos,numtowrite);
2565 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2566 END_PROFILE(SMBwriteX);
2567 return(UNIXERROR(ERRHRD,ERRdiskfull));
2570 set_message(outbuf,6,0,True);
2572 SSVAL(outbuf,smb_vwv2,nwritten);
2573 if (large_writeX)
2574 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2576 if (nwritten < (ssize_t)numtowrite) {
2577 SCVAL(outbuf,smb_rcls,ERRHRD);
2578 SSVAL(outbuf,smb_err,ERRdiskfull);
2581 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2582 fsp->fnum, (int)numtowrite, (int)nwritten));
2584 if (lp_syncalways(SNUM(conn)) || write_through)
2585 sync_file(conn,fsp);
2587 END_PROFILE(SMBwriteX);
2588 return chain_reply(inbuf,outbuf,length,bufsize);
2591 /****************************************************************************
2592 Reply to a lseek.
2593 ****************************************************************************/
2595 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2597 SMB_OFF_T startpos;
2598 SMB_OFF_T res= -1;
2599 int mode,umode;
2600 int outsize = 0;
2601 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2602 START_PROFILE(SMBlseek);
2604 CHECK_FSP(fsp,conn);
2606 flush_write_cache(fsp, SEEK_FLUSH);
2608 mode = SVAL(inbuf,smb_vwv1) & 3;
2609 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
2610 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
2612 switch (mode) {
2613 case 0:
2614 umode = SEEK_SET;
2615 res = startpos;
2616 break;
2617 case 1:
2618 umode = SEEK_CUR;
2619 res = fsp->pos + startpos;
2620 break;
2621 case 2:
2622 umode = SEEK_END;
2623 break;
2624 default:
2625 umode = SEEK_SET;
2626 res = startpos;
2627 break;
2630 if (umode == SEEK_END) {
2631 if((res = SMB_VFS_LSEEK(fsp,fsp->fd,startpos,umode)) == -1) {
2632 if(errno == EINVAL) {
2633 SMB_OFF_T current_pos = startpos;
2634 SMB_STRUCT_STAT sbuf;
2636 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) {
2637 END_PROFILE(SMBlseek);
2638 return(UNIXERROR(ERRDOS,ERRnoaccess));
2641 current_pos += sbuf.st_size;
2642 if(current_pos < 0)
2643 res = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_SET);
2647 if(res == -1) {
2648 END_PROFILE(SMBlseek);
2649 return(UNIXERROR(ERRDOS,ERRnoaccess));
2653 fsp->pos = res;
2655 outsize = set_message(outbuf,2,0,True);
2656 SIVAL(outbuf,smb_vwv0,res);
2658 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2659 fsp->fnum, (double)startpos, (double)res, mode));
2661 END_PROFILE(SMBlseek);
2662 return(outsize);
2665 /****************************************************************************
2666 Reply to a flush.
2667 ****************************************************************************/
2669 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2671 int outsize = set_message(outbuf,0,0,True);
2672 uint16 fnum = SVAL(inbuf,smb_vwv0);
2673 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2674 START_PROFILE(SMBflush);
2676 if (fnum != 0xFFFF)
2677 CHECK_FSP(fsp,conn);
2679 if (!fsp) {
2680 file_sync_all(conn);
2681 } else {
2682 sync_file(conn,fsp);
2685 DEBUG(3,("flush\n"));
2686 END_PROFILE(SMBflush);
2687 return(outsize);
2690 /****************************************************************************
2691 Reply to a exit.
2692 ****************************************************************************/
2694 int reply_exit(connection_struct *conn,
2695 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2697 int outsize;
2698 START_PROFILE(SMBexit);
2700 file_close_pid(SVAL(inbuf,smb_pid));
2702 outsize = set_message(outbuf,0,0,True);
2704 DEBUG(3,("exit\n"));
2706 END_PROFILE(SMBexit);
2707 return(outsize);
2710 /****************************************************************************
2711 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2712 ****************************************************************************/
2714 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2715 int dum_buffsize)
2717 extern struct current_user current_user;
2718 int outsize = 0;
2719 time_t mtime;
2720 int32 eclass = 0, err = 0;
2721 files_struct *fsp = NULL;
2722 START_PROFILE(SMBclose);
2724 outsize = set_message(outbuf,0,0,True);
2726 /* If it's an IPC, pass off to the pipe handler. */
2727 if (IS_IPC(conn)) {
2728 END_PROFILE(SMBclose);
2729 return reply_pipe_close(conn, inbuf,outbuf);
2732 fsp = file_fsp(inbuf,smb_vwv0);
2735 * We can only use CHECK_FSP if we know it's not a directory.
2738 if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
2739 END_PROFILE(SMBclose);
2740 return ERROR_DOS(ERRDOS,ERRbadfid);
2743 if(fsp->is_directory) {
2745 * Special case - close NT SMB directory handle.
2747 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2748 close_file(fsp,True);
2749 } else {
2751 * Close ordinary file.
2753 int close_err;
2754 pstring file_name;
2756 /* Save the name for time set in close. */
2757 pstrcpy( file_name, fsp->fsp_name);
2759 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2760 fsp->fd, fsp->fnum,
2761 conn->num_files_open));
2764 * close_file() returns the unix errno if an error
2765 * was detected on close - normally this is due to
2766 * a disk full error. If not then it was probably an I/O error.
2769 if((close_err = close_file(fsp,True)) != 0) {
2770 errno = close_err;
2771 END_PROFILE(SMBclose);
2772 return (UNIXERROR(ERRHRD,ERRgeneral));
2776 * Now take care of any time sent in the close.
2779 mtime = make_unix_date3(inbuf+smb_vwv1);
2781 /* try and set the date */
2782 set_filetime(conn, file_name, mtime);
2786 /* We have a cached error */
2787 if(eclass || err) {
2788 END_PROFILE(SMBclose);
2789 return ERROR_DOS(eclass,err);
2792 END_PROFILE(SMBclose);
2793 return(outsize);
2796 /****************************************************************************
2797 Reply to a writeclose (Core+ protocol).
2798 ****************************************************************************/
2800 int reply_writeclose(connection_struct *conn,
2801 char *inbuf,char *outbuf, int size, int dum_buffsize)
2803 size_t numtowrite;
2804 ssize_t nwritten = -1;
2805 int outsize = 0;
2806 int close_err = 0;
2807 SMB_OFF_T startpos;
2808 char *data;
2809 time_t mtime;
2810 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2811 START_PROFILE(SMBwriteclose);
2813 CHECK_FSP(fsp,conn);
2814 CHECK_WRITE(fsp);
2816 numtowrite = SVAL(inbuf,smb_vwv1);
2817 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2818 mtime = make_unix_date3(inbuf+smb_vwv4);
2819 data = smb_buf(inbuf) + 1;
2821 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2822 END_PROFILE(SMBwriteclose);
2823 return ERROR_DOS(ERRDOS,ERRlock);
2826 nwritten = write_file(fsp,data,startpos,numtowrite);
2828 set_filetime(conn, fsp->fsp_name,mtime);
2831 * More insanity. W2K only closes the file if writelen > 0.
2832 * JRA.
2835 if (numtowrite) {
2836 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
2837 fsp->fsp_name ));
2838 close_err = close_file(fsp,True);
2841 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2842 fsp->fnum, (int)numtowrite, (int)nwritten,
2843 conn->num_files_open));
2845 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2846 END_PROFILE(SMBwriteclose);
2847 return(UNIXERROR(ERRHRD,ERRdiskfull));
2850 if(close_err != 0) {
2851 errno = close_err;
2852 END_PROFILE(SMBwriteclose);
2853 return(UNIXERROR(ERRHRD,ERRgeneral));
2856 outsize = set_message(outbuf,1,0,True);
2858 SSVAL(outbuf,smb_vwv0,nwritten);
2859 END_PROFILE(SMBwriteclose);
2860 return(outsize);
2863 /****************************************************************************
2864 Reply to a lock.
2865 ****************************************************************************/
2867 int reply_lock(connection_struct *conn,
2868 char *inbuf,char *outbuf, int length, int dum_buffsize)
2870 int outsize = set_message(outbuf,0,0,True);
2871 SMB_BIG_UINT count,offset;
2872 NTSTATUS status;
2873 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2874 BOOL my_lock_ctx = False;
2876 START_PROFILE(SMBlock);
2878 CHECK_FSP(fsp,conn);
2880 release_level_2_oplocks_on_change(fsp);
2882 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2883 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2885 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2886 fsp->fd, fsp->fnum, (double)offset, (double)count));
2888 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &my_lock_ctx);
2889 if (NT_STATUS_V(status)) {
2890 #if 0
2891 /* Tests using Samba4 against W2K show this call never creates a blocking lock. */
2892 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
2894 * A blocking lock was requested. Package up
2895 * this smb into a queued request and push it
2896 * onto the blocking lock queue.
2898 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), offset, count)) {
2899 END_PROFILE(SMBlock);
2900 return -1;
2903 #endif
2904 END_PROFILE(SMBlock);
2905 return ERROR_NT(status);
2908 END_PROFILE(SMBlock);
2909 return(outsize);
2912 /****************************************************************************
2913 Reply to a unlock.
2914 ****************************************************************************/
2916 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
2917 int dum_buffsize)
2919 int outsize = set_message(outbuf,0,0,True);
2920 SMB_BIG_UINT count,offset;
2921 NTSTATUS status;
2922 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2923 START_PROFILE(SMBunlock);
2925 CHECK_FSP(fsp,conn);
2927 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2928 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2930 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
2931 if (NT_STATUS_V(status)) {
2932 END_PROFILE(SMBunlock);
2933 return ERROR_NT(status);
2936 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2937 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
2939 END_PROFILE(SMBunlock);
2940 return(outsize);
2943 /****************************************************************************
2944 Reply to a tdis.
2945 ****************************************************************************/
2947 int reply_tdis(connection_struct *conn,
2948 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2950 int outsize = set_message(outbuf,0,0,True);
2951 uint16 vuid;
2952 START_PROFILE(SMBtdis);
2954 vuid = SVAL(inbuf,smb_uid);
2956 if (!conn) {
2957 DEBUG(4,("Invalid connection in tdis\n"));
2958 END_PROFILE(SMBtdis);
2959 return ERROR_DOS(ERRSRV,ERRinvnid);
2962 conn->used = False;
2964 close_cnum(conn,vuid);
2966 END_PROFILE(SMBtdis);
2967 return outsize;
2970 /****************************************************************************
2971 Reply to a echo.
2972 ****************************************************************************/
2974 int reply_echo(connection_struct *conn,
2975 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2977 int smb_reverb = SVAL(inbuf,smb_vwv0);
2978 int seq_num;
2979 unsigned int data_len = smb_buflen(inbuf);
2980 int outsize = set_message(outbuf,1,data_len,True);
2981 START_PROFILE(SMBecho);
2983 if (data_len > BUFFER_SIZE) {
2984 DEBUG(0,("reply_echo: data_len too large.\n"));
2985 END_PROFILE(SMBecho);
2986 return -1;
2989 /* copy any incoming data back out */
2990 if (data_len > 0)
2991 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2993 if (smb_reverb > 100) {
2994 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2995 smb_reverb = 100;
2998 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
2999 SSVAL(outbuf,smb_vwv0,seq_num);
3001 smb_setlen(outbuf,outsize - 4);
3003 if (!send_smb(smbd_server_fd(),outbuf))
3004 exit_server("reply_echo: send_smb failed.");
3007 DEBUG(3,("echo %d times\n", smb_reverb));
3009 smb_echo_count++;
3011 END_PROFILE(SMBecho);
3012 return -1;
3015 /****************************************************************************
3016 Reply to a printopen.
3017 ****************************************************************************/
3019 int reply_printopen(connection_struct *conn,
3020 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3022 int outsize = 0;
3023 files_struct *fsp;
3024 START_PROFILE(SMBsplopen);
3026 if (!CAN_PRINT(conn)) {
3027 END_PROFILE(SMBsplopen);
3028 return ERROR_DOS(ERRDOS,ERRnoaccess);
3031 /* Open for exclusive use, write only. */
3032 fsp = print_fsp_open(conn, NULL);
3034 if (!fsp) {
3035 END_PROFILE(SMBsplopen);
3036 return(UNIXERROR(ERRDOS,ERRnoaccess));
3039 outsize = set_message(outbuf,1,0,True);
3040 SSVAL(outbuf,smb_vwv0,fsp->fnum);
3042 DEBUG(3,("openprint fd=%d fnum=%d\n",
3043 fsp->fd, fsp->fnum));
3045 END_PROFILE(SMBsplopen);
3046 return(outsize);
3049 /****************************************************************************
3050 Reply to a printclose.
3051 ****************************************************************************/
3053 int reply_printclose(connection_struct *conn,
3054 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3056 int outsize = set_message(outbuf,0,0,True);
3057 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3058 int close_err = 0;
3059 START_PROFILE(SMBsplclose);
3061 CHECK_FSP(fsp,conn);
3063 if (!CAN_PRINT(conn)) {
3064 END_PROFILE(SMBsplclose);
3065 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
3068 DEBUG(3,("printclose fd=%d fnum=%d\n",
3069 fsp->fd,fsp->fnum));
3071 close_err = close_file(fsp,True);
3073 if(close_err != 0) {
3074 errno = close_err;
3075 END_PROFILE(SMBsplclose);
3076 return(UNIXERROR(ERRHRD,ERRgeneral));
3079 END_PROFILE(SMBsplclose);
3080 return(outsize);
3083 /****************************************************************************
3084 Reply to a printqueue.
3085 ****************************************************************************/
3087 int reply_printqueue(connection_struct *conn,
3088 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3090 int outsize = set_message(outbuf,2,3,True);
3091 int max_count = SVAL(inbuf,smb_vwv0);
3092 int start_index = SVAL(inbuf,smb_vwv1);
3093 START_PROFILE(SMBsplretq);
3095 /* we used to allow the client to get the cnum wrong, but that
3096 is really quite gross and only worked when there was only
3097 one printer - I think we should now only accept it if they
3098 get it right (tridge) */
3099 if (!CAN_PRINT(conn)) {
3100 END_PROFILE(SMBsplretq);
3101 return ERROR_DOS(ERRDOS,ERRnoaccess);
3104 SSVAL(outbuf,smb_vwv0,0);
3105 SSVAL(outbuf,smb_vwv1,0);
3106 SCVAL(smb_buf(outbuf),0,1);
3107 SSVAL(smb_buf(outbuf),1,0);
3109 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3110 start_index, max_count));
3113 print_queue_struct *queue = NULL;
3114 print_status_struct status;
3115 char *p = smb_buf(outbuf) + 3;
3116 int count = print_queue_status(SNUM(conn), &queue, &status);
3117 int num_to_get = ABS(max_count);
3118 int first = (max_count>0?start_index:start_index+max_count+1);
3119 int i;
3121 if (first >= count)
3122 num_to_get = 0;
3123 else
3124 num_to_get = MIN(num_to_get,count-first);
3127 for (i=first;i<first+num_to_get;i++) {
3128 put_dos_date2(p,0,queue[i].time);
3129 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
3130 SSVAL(p,5, queue[i].job);
3131 SIVAL(p,7,queue[i].size);
3132 SCVAL(p,11,0);
3133 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
3134 p += 28;
3137 if (count > 0) {
3138 outsize = set_message(outbuf,2,28*count+3,False);
3139 SSVAL(outbuf,smb_vwv0,count);
3140 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3141 SCVAL(smb_buf(outbuf),0,1);
3142 SSVAL(smb_buf(outbuf),1,28*count);
3145 SAFE_FREE(queue);
3147 DEBUG(3,("%d entries returned in queue\n",count));
3150 END_PROFILE(SMBsplretq);
3151 return(outsize);
3154 /****************************************************************************
3155 Reply to a printwrite.
3156 ****************************************************************************/
3158 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3160 int numtowrite;
3161 int outsize = set_message(outbuf,0,0,True);
3162 char *data;
3163 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3165 START_PROFILE(SMBsplwr);
3167 if (!CAN_PRINT(conn)) {
3168 END_PROFILE(SMBsplwr);
3169 return ERROR_DOS(ERRDOS,ERRnoaccess);
3172 CHECK_FSP(fsp,conn);
3173 CHECK_WRITE(fsp);
3175 numtowrite = SVAL(smb_buf(inbuf),1);
3176 data = smb_buf(inbuf) + 3;
3178 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3179 END_PROFILE(SMBsplwr);
3180 return(UNIXERROR(ERRHRD,ERRdiskfull));
3183 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3185 END_PROFILE(SMBsplwr);
3186 return(outsize);
3189 /****************************************************************************
3190 The guts of the mkdir command, split out so it may be called by the NT SMB
3191 code.
3192 ****************************************************************************/
3194 NTSTATUS mkdir_internal(connection_struct *conn, pstring directory)
3196 BOOL bad_path = False;
3197 SMB_STRUCT_STAT sbuf;
3198 int ret= -1;
3200 unix_convert(directory,conn,0,&bad_path,&sbuf);
3202 if( strchr_m(directory, ':')) {
3203 return NT_STATUS_NOT_A_DIRECTORY;
3206 if (ms_has_wild(directory)) {
3207 return NT_STATUS_OBJECT_NAME_INVALID;
3210 if (bad_path) {
3211 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3214 if (check_name(directory, conn))
3215 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory));
3217 if (ret == -1) {
3218 if(errno == ENOENT) {
3219 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3221 return map_nt_error_from_unix(errno);
3224 return NT_STATUS_OK;
3227 /****************************************************************************
3228 Reply to a mkdir.
3229 ****************************************************************************/
3231 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3233 pstring directory;
3234 int outsize;
3235 NTSTATUS status;
3236 START_PROFILE(SMBmkdir);
3238 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False);
3239 if (!NT_STATUS_IS_OK(status)) {
3240 END_PROFILE(SMBmkdir);
3241 return ERROR_NT(status);
3244 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
3246 status = mkdir_internal(conn, directory);
3247 if (!NT_STATUS_IS_OK(status)) {
3248 END_PROFILE(SMBmkdir);
3249 return ERROR_NT(status);
3252 outsize = set_message(outbuf,0,0,True);
3254 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3256 END_PROFILE(SMBmkdir);
3257 return(outsize);
3260 /****************************************************************************
3261 Static function used by reply_rmdir to delete an entire directory
3262 tree recursively. Return False on ok, True on fail.
3263 ****************************************************************************/
3265 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3267 const char *dname = NULL;
3268 BOOL ret = False;
3269 void *dirptr = OpenDir(conn, directory, False);
3271 if(dirptr == NULL)
3272 return True;
3274 while((dname = ReadDirName(dirptr))) {
3275 pstring fullname;
3276 SMB_STRUCT_STAT st;
3278 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3279 continue;
3281 /* Construct the full name. */
3282 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3283 errno = ENOMEM;
3284 ret = True;
3285 break;
3288 pstrcpy(fullname, directory);
3289 pstrcat(fullname, "/");
3290 pstrcat(fullname, dname);
3292 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
3293 ret = True;
3294 break;
3297 if(st.st_mode & S_IFDIR) {
3298 if(recursive_rmdir(conn, fullname)!=0) {
3299 ret = True;
3300 break;
3302 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
3303 ret = True;
3304 break;
3306 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
3307 ret = True;
3308 break;
3311 CloseDir(dirptr);
3312 return ret;
3315 /****************************************************************************
3316 The internals of the rmdir code - called elsewhere.
3317 ****************************************************************************/
3319 BOOL rmdir_internals(connection_struct *conn, char *directory)
3321 BOOL ok;
3323 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3324 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3326 * Check to see if the only thing in this directory are
3327 * vetoed files/directories. If so then delete them and
3328 * retry. If we fail to delete any of them (and we *don't*
3329 * do a recursive delete) then fail the rmdir.
3331 BOOL all_veto_files = True;
3332 const char *dname;
3333 void *dirptr = OpenDir(conn, directory, False);
3335 if(dirptr != NULL) {
3336 int dirpos = TellDir(dirptr);
3337 while ((dname = ReadDirName(dirptr))) {
3338 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3339 continue;
3340 if(!IS_VETO_PATH(conn, dname)) {
3341 all_veto_files = False;
3342 break;
3346 if(all_veto_files) {
3347 SeekDir(dirptr,dirpos);
3348 while ((dname = ReadDirName(dirptr))) {
3349 pstring fullname;
3350 SMB_STRUCT_STAT st;
3352 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3353 continue;
3355 /* Construct the full name. */
3356 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3357 errno = ENOMEM;
3358 break;
3361 pstrcpy(fullname, directory);
3362 pstrcat(fullname, "/");
3363 pstrcat(fullname, dname);
3365 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
3366 break;
3367 if(st.st_mode & S_IFDIR) {
3368 if(lp_recursive_veto_delete(SNUM(conn))) {
3369 if(recursive_rmdir(conn, fullname) != 0)
3370 break;
3372 if(SMB_VFS_RMDIR(conn,fullname) != 0)
3373 break;
3374 } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
3375 break;
3377 CloseDir(dirptr);
3378 /* Retry the rmdir */
3379 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3380 } else {
3381 CloseDir(dirptr);
3383 } else {
3384 errno = ENOTEMPTY;
3388 if (!ok)
3389 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
3391 return ok;
3394 /****************************************************************************
3395 Reply to a rmdir.
3396 ****************************************************************************/
3398 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3400 pstring directory;
3401 int outsize = 0;
3402 BOOL ok = False;
3403 BOOL bad_path = False;
3404 SMB_STRUCT_STAT sbuf;
3405 NTSTATUS status;
3406 START_PROFILE(SMBrmdir);
3408 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False);
3409 if (!NT_STATUS_IS_OK(status)) {
3410 END_PROFILE(SMBrmdir);
3411 return ERROR_NT(status);
3414 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3416 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3417 if (bad_path) {
3418 END_PROFILE(SMBrmdir);
3419 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3422 if (check_name(directory,conn)) {
3423 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3424 ok = rmdir_internals(conn, directory);
3427 if (!ok) {
3428 END_PROFILE(SMBrmdir);
3429 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRbadpath);
3432 outsize = set_message(outbuf,0,0,True);
3434 DEBUG( 3, ( "rmdir %s\n", directory ) );
3436 END_PROFILE(SMBrmdir);
3437 return(outsize);
3440 /*******************************************************************
3441 Resolve wildcards in a filename rename.
3442 Note that name is in UNIX charset and thus potentially can be more
3443 than fstring buffer (255 bytes) especially in default UTF-8 case.
3444 Therefore, we use pstring inside and all calls should ensure that
3445 name2 is at least pstring-long (they do already)
3446 ********************************************************************/
3448 static BOOL resolve_wildcards(const char *name1, char *name2)
3450 pstring root1,root2;
3451 pstring ext1,ext2;
3452 char *p,*p2, *pname1, *pname2;
3453 int available_space, actual_space;
3456 pname1 = strrchr_m(name1,'/');
3457 pname2 = strrchr_m(name2,'/');
3459 if (!pname1 || !pname2)
3460 return(False);
3462 pstrcpy(root1,pname1);
3463 pstrcpy(root2,pname2);
3464 p = strrchr_m(root1,'.');
3465 if (p) {
3466 *p = 0;
3467 pstrcpy(ext1,p+1);
3468 } else {
3469 pstrcpy(ext1,"");
3471 p = strrchr_m(root2,'.');
3472 if (p) {
3473 *p = 0;
3474 pstrcpy(ext2,p+1);
3475 } else {
3476 pstrcpy(ext2,"");
3479 p = root1;
3480 p2 = root2;
3481 while (*p2) {
3482 if (*p2 == '?') {
3483 *p2 = *p;
3484 p2++;
3485 } else if (*p2 == '*') {
3486 pstrcpy(p2, p);
3487 break;
3488 } else {
3489 p2++;
3491 if (*p)
3492 p++;
3495 p = ext1;
3496 p2 = ext2;
3497 while (*p2) {
3498 if (*p2 == '?') {
3499 *p2 = *p;
3500 p2++;
3501 } else if (*p2 == '*') {
3502 pstrcpy(p2, p);
3503 break;
3504 } else {
3505 p2++;
3507 if (*p)
3508 p++;
3511 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
3513 if (ext2[0]) {
3514 actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
3515 if (actual_space >= available_space - 1) {
3516 DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
3517 actual_space - available_space));
3519 } else {
3520 pstrcpy_base(pname2, root2, name2);
3523 return(True);
3526 /****************************************************************************
3527 Ensure open files have their names updates.
3528 ****************************************************************************/
3530 static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode, char *newname)
3532 files_struct *fsp;
3533 BOOL did_rename = False;
3535 for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
3536 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
3537 fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
3538 fsp->fsp_name, newname ));
3539 string_set(&fsp->fsp_name, newname);
3540 did_rename = True;
3543 if (!did_rename)
3544 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
3545 (unsigned int)dev, (double)inode, newname ));
3548 /****************************************************************************
3549 Rename an open file - given an fsp.
3550 ****************************************************************************/
3552 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, uint16 attrs, BOOL replace_if_exists)
3554 SMB_STRUCT_STAT sbuf;
3555 BOOL bad_path = False;
3556 pstring newname_last_component;
3557 NTSTATUS error = NT_STATUS_OK;
3558 BOOL dest_exists;
3559 BOOL rcdest = True;
3561 ZERO_STRUCT(sbuf);
3562 rcdest = unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf);
3564 /* Quick check for "." and ".." */
3565 if (!bad_path && newname_last_component[0] == '.') {
3566 if (!newname_last_component[1] || (newname_last_component[1] == '.' && !newname_last_component[2])) {
3567 return NT_STATUS_ACCESS_DENIED;
3570 if (!rcdest && bad_path) {
3571 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3574 /* Ensure newname contains a '/' */
3575 if(strrchr_m(newname,'/') == 0) {
3576 pstring tmpstr;
3578 pstrcpy(tmpstr, "./");
3579 pstrcat(tmpstr, newname);
3580 pstrcpy(newname, tmpstr);
3584 * Check for special case with case preserving and not
3585 * case sensitive. If the old last component differs from the original
3586 * last component only by case, then we should allow
3587 * the rename (user is trying to change the case of the
3588 * filename).
3591 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
3592 strequal(newname, fsp->fsp_name)) {
3593 char *p;
3594 pstring newname_modified_last_component;
3597 * Get the last component of the modified name.
3598 * Note that we guarantee that newname contains a '/'
3599 * character above.
3601 p = strrchr_m(newname,'/');
3602 pstrcpy(newname_modified_last_component,p+1);
3604 if(strcsequal(newname_modified_last_component,
3605 newname_last_component) == False) {
3607 * Replace the modified last component with
3608 * the original.
3610 pstrcpy(p+1, newname_last_component);
3615 * If the src and dest names are identical - including case,
3616 * don't do the rename, just return success.
3619 if (strcsequal(fsp->fsp_name, newname)) {
3620 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
3621 newname));
3622 return NT_STATUS_OK;
3625 dest_exists = vfs_object_exist(conn,newname,NULL);
3627 if(!replace_if_exists && dest_exists) {
3628 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
3629 fsp->fsp_name,newname));
3630 return NT_STATUS_OBJECT_NAME_COLLISION;
3633 error = can_rename(newname,conn,attrs,&sbuf);
3635 if (dest_exists && !NT_STATUS_IS_OK(error)) {
3636 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3637 nt_errstr(error), fsp->fsp_name,newname));
3638 if (NT_STATUS_EQUAL(error,NT_STATUS_SHARING_VIOLATION))
3639 error = NT_STATUS_ACCESS_DENIED;
3640 return error;
3643 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
3644 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
3645 fsp->fsp_name,newname));
3646 rename_open_files(conn, fsp->dev, fsp->inode, newname);
3647 return NT_STATUS_OK;
3650 if (errno == ENOTDIR || errno == EISDIR)
3651 error = NT_STATUS_OBJECT_NAME_COLLISION;
3652 else
3653 error = map_nt_error_from_unix(errno);
3655 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
3656 nt_errstr(error), fsp->fsp_name,newname));
3658 return error;
3661 /****************************************************************************
3662 The guts of the rename command, split out so it may be called by the NT SMB
3663 code.
3664 ****************************************************************************/
3666 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, uint16 attrs, BOOL replace_if_exists)
3668 pstring directory;
3669 pstring mask;
3670 pstring last_component_src;
3671 pstring last_component_dest;
3672 char *p;
3673 BOOL has_wild;
3674 BOOL bad_path_src = False;
3675 BOOL bad_path_dest = False;
3676 int count=0;
3677 NTSTATUS error = NT_STATUS_OK;
3678 BOOL rc = True;
3679 BOOL rcdest = True;
3680 SMB_STRUCT_STAT sbuf1, sbuf2;
3682 *directory = *mask = 0;
3684 ZERO_STRUCT(sbuf1);
3685 ZERO_STRUCT(sbuf2);
3687 rc = unix_convert(name,conn,last_component_src,&bad_path_src,&sbuf1);
3688 if (!rc && bad_path_src) {
3689 if (ms_has_wild(last_component_src))
3690 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3691 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3694 /* Quick check for "." and ".." */
3695 if (last_component_src[0] == '.') {
3696 if (!last_component_src[1] || (last_component_src[1] == '.' && !last_component_src[2])) {
3697 return NT_STATUS_OBJECT_NAME_INVALID;
3701 rcdest = unix_convert(newname,conn,last_component_dest,&bad_path_dest,&sbuf2);
3703 /* Quick check for "." and ".." */
3704 if (last_component_dest[0] == '.') {
3705 if (!last_component_dest[1] || (last_component_dest[1] == '.' && !last_component_dest[2])) {
3706 return NT_STATUS_OBJECT_NAME_INVALID;
3711 * Split the old name into directory and last component
3712 * strings. Note that unix_convert may have stripped off a
3713 * leading ./ from both name and newname if the rename is
3714 * at the root of the share. We need to make sure either both
3715 * name and newname contain a / character or neither of them do
3716 * as this is checked in resolve_wildcards().
3719 p = strrchr_m(name,'/');
3720 if (!p) {
3721 pstrcpy(directory,".");
3722 pstrcpy(mask,name);
3723 } else {
3724 *p = 0;
3725 pstrcpy(directory,name);
3726 pstrcpy(mask,p+1);
3727 *p = '/'; /* Replace needed for exceptional test below. */
3731 * We should only check the mangled cache
3732 * here if unix_convert failed. This means
3733 * that the path in 'mask' doesn't exist
3734 * on the file system and so we need to look
3735 * for a possible mangle. This patch from
3736 * Tine Smukavec <valentin.smukavec@hermes.si>.
3739 if (!rc && mangle_is_mangled(mask))
3740 mangle_check_cache( mask, sizeof(pstring)-1 );
3742 has_wild = ms_has_wild(mask);
3744 if (!has_wild) {
3746 * No wildcards - just process the one file.
3748 BOOL is_short_name = mangle_is_8_3(name, True);
3750 /* Add a terminating '/' to the directory name. */
3751 pstrcat(directory,"/");
3752 pstrcat(directory,mask);
3754 /* Ensure newname contains a '/' also */
3755 if(strrchr_m(newname,'/') == 0) {
3756 pstring tmpstr;
3758 pstrcpy(tmpstr, "./");
3759 pstrcat(tmpstr, newname);
3760 pstrcpy(newname, tmpstr);
3763 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
3764 directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
3765 conn->case_sensitive, conn->case_preserve, conn->short_case_preserve, directory,
3766 newname, last_component_dest, is_short_name));
3769 * Check for special case with case preserving and not
3770 * case sensitive, if directory and newname are identical,
3771 * and the old last component differs from the original
3772 * last component only by case, then we should allow
3773 * the rename (user is trying to change the case of the
3774 * filename).
3776 if((conn->case_sensitive == False) &&
3777 (((conn->case_preserve == True) &&
3778 (is_short_name == False)) ||
3779 ((conn->short_case_preserve == True) &&
3780 (is_short_name == True))) &&
3781 strcsequal(directory, newname)) {
3782 pstring modified_last_component;
3785 * Get the last component of the modified name.
3786 * Note that we guarantee that newname contains a '/'
3787 * character above.
3789 p = strrchr_m(newname,'/');
3790 pstrcpy(modified_last_component,p+1);
3792 if(strcsequal(modified_last_component,
3793 last_component_dest) == False) {
3795 * Replace the modified last component with
3796 * the original.
3798 pstrcpy(p+1, last_component_dest);
3802 resolve_wildcards(directory,newname);
3805 * The source object must exist.
3808 if (!vfs_object_exist(conn, directory, &sbuf1)) {
3809 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
3810 directory,newname));
3812 if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
3814 * Must return different errors depending on whether the parent
3815 * directory existed or not.
3818 p = strrchr_m(directory, '/');
3819 if (!p)
3820 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3821 *p = '\0';
3822 if (vfs_object_exist(conn, directory, NULL))
3823 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3824 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3826 error = map_nt_error_from_unix(errno);
3827 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3828 nt_errstr(error), directory,newname));
3830 return error;
3833 if (!rcdest && bad_path_dest) {
3834 if (ms_has_wild(last_component_dest))
3835 return NT_STATUS_OBJECT_NAME_INVALID;
3836 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3839 error = can_rename(directory,conn,attrs,&sbuf1);
3841 if (!NT_STATUS_IS_OK(error)) {
3842 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3843 nt_errstr(error), directory,newname));
3844 return error;
3848 * If the src and dest names are identical - including case,
3849 * don't do the rename, just return success.
3852 if (strcsequal(directory, newname)) {
3853 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3854 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
3855 return NT_STATUS_OK;
3858 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
3859 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
3860 directory,newname));
3861 return NT_STATUS_OBJECT_NAME_COLLISION;
3864 if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
3865 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
3866 directory,newname));
3867 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3868 return NT_STATUS_OK;
3871 if (errno == ENOTDIR || errno == EISDIR)
3872 error = NT_STATUS_OBJECT_NAME_COLLISION;
3873 else
3874 error = map_nt_error_from_unix(errno);
3876 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3877 nt_errstr(error), directory,newname));
3879 return error;
3880 } else {
3882 * Wildcards - process each file that matches.
3884 void *dirptr = NULL;
3885 const char *dname;
3886 pstring destname;
3888 if (check_name(directory,conn))
3889 dirptr = OpenDir(conn, directory, True);
3891 if (dirptr) {
3892 error = NT_STATUS_NO_SUCH_FILE;
3893 /* Was error = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */
3895 if (strequal(mask,"????????.???"))
3896 pstrcpy(mask,"*");
3898 while ((dname = ReadDirName(dirptr))) {
3899 pstring fname;
3900 BOOL sysdir_entry = False;
3902 pstrcpy(fname,dname);
3904 /* Quick check for "." and ".." */
3905 if (fname[0] == '.') {
3906 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
3907 if (attrs & aDIR) {
3908 sysdir_entry = True;
3909 } else {
3910 continue;
3915 if(!mask_match(fname, mask, conn->case_sensitive))
3916 continue;
3918 if (sysdir_entry) {
3919 error = NT_STATUS_OBJECT_NAME_INVALID;
3920 break;
3923 error = NT_STATUS_ACCESS_DENIED;
3924 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3925 if (!vfs_object_exist(conn, fname, &sbuf1)) {
3926 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3927 DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
3928 continue;
3930 error = can_rename(fname,conn,attrs,&sbuf1);
3931 if (!NT_STATUS_IS_OK(error)) {
3932 DEBUG(6,("rename %s refused\n", fname));
3933 continue;
3935 pstrcpy(destname,newname);
3937 if (!resolve_wildcards(fname,destname)) {
3938 DEBUG(6,("resolve_wildcards %s %s failed\n",
3939 fname, destname));
3940 continue;
3943 if (strcsequal(fname,destname)) {
3944 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3945 DEBUG(3,("rename_internals: identical names in wildcard rename %s - success\n", fname));
3946 count++;
3947 error = NT_STATUS_OK;
3948 continue;
3951 if (!replace_if_exists &&
3952 vfs_file_exist(conn,destname, NULL)) {
3953 DEBUG(6,("file_exist %s\n", destname));
3954 error = NT_STATUS_OBJECT_NAME_COLLISION;
3955 continue;
3958 if (!SMB_VFS_RENAME(conn,fname,destname)) {
3959 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3960 count++;
3961 error = NT_STATUS_OK;
3963 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3965 CloseDir(dirptr);
3968 if (!NT_STATUS_EQUAL(error,NT_STATUS_NO_SUCH_FILE)) {
3969 if (!rcdest && bad_path_dest) {
3970 if (ms_has_wild(last_component_dest))
3971 return NT_STATUS_OBJECT_NAME_INVALID;
3972 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3977 if (count == 0 && NT_STATUS_IS_OK(error)) {
3978 error = map_nt_error_from_unix(errno);
3981 return error;
3984 /****************************************************************************
3985 Reply to a mv.
3986 ****************************************************************************/
3988 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
3989 int dum_buffsize)
3991 int outsize = 0;
3992 pstring name;
3993 pstring newname;
3994 char *p;
3995 uint16 attrs = SVAL(inbuf,smb_vwv0);
3996 NTSTATUS status;
3998 START_PROFILE(SMBmv);
4000 p = smb_buf(inbuf) + 1;
4001 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True);
4002 if (!NT_STATUS_IS_OK(status)) {
4003 END_PROFILE(SMBmv);
4004 return ERROR_NT(status);
4006 p++;
4007 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True);
4008 if (!NT_STATUS_IS_OK(status)) {
4009 END_PROFILE(SMBmv);
4010 return ERROR_NT(status);
4013 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
4014 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4016 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
4018 status = rename_internals(conn, name, newname, attrs, False);
4019 if (!NT_STATUS_IS_OK(status)) {
4020 END_PROFILE(SMBmv);
4021 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4022 /* We have re-scheduled this call. */
4023 clear_cached_errors();
4024 return -1;
4026 return ERROR_NT(status);
4030 * Win2k needs a changenotify request response before it will
4031 * update after a rename..
4033 process_pending_change_notify_queue((time_t)0);
4034 outsize = set_message(outbuf,0,0,True);
4036 END_PROFILE(SMBmv);
4037 return(outsize);
4040 /*******************************************************************
4041 Copy a file as part of a reply_copy.
4042 ******************************************************************/
4044 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
4045 int count,BOOL target_is_directory, int *err_ret)
4047 int Access,action;
4048 SMB_STRUCT_STAT src_sbuf, sbuf2;
4049 SMB_OFF_T ret=-1;
4050 files_struct *fsp1,*fsp2;
4051 pstring dest;
4052 uint32 dosattrs;
4054 *err_ret = 0;
4056 pstrcpy(dest,dest1);
4057 if (target_is_directory) {
4058 char *p = strrchr_m(src,'/');
4059 if (p)
4060 p++;
4061 else
4062 p = src;
4063 pstrcat(dest,"/");
4064 pstrcat(dest,p);
4067 if (!vfs_file_exist(conn,src,&src_sbuf))
4068 return(False);
4070 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
4071 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),FILE_ATTRIBUTE_NORMAL,INTERNAL_OPEN_ONLY,
4072 &Access,&action);
4074 if (!fsp1)
4075 return(False);
4077 if (!target_is_directory && count)
4078 ofun = FILE_EXISTS_OPEN;
4080 dosattrs = dos_mode(conn, src, &src_sbuf);
4081 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1)
4082 ZERO_STRUCTP(&sbuf2);
4084 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
4085 ofun,dosattrs,INTERNAL_OPEN_ONLY,&Access,&action);
4087 if (!fsp2) {
4088 close_file(fsp1,False);
4089 return(False);
4092 if ((ofun&3) == 1) {
4093 if(SMB_VFS_LSEEK(fsp2,fsp2->fd,0,SEEK_END) == -1) {
4094 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
4096 * Stop the copy from occurring.
4098 ret = -1;
4099 src_sbuf.st_size = 0;
4103 if (src_sbuf.st_size)
4104 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
4106 close_file(fsp1,False);
4108 /* Ensure the modtime is set correctly on the destination file. */
4109 fsp2->pending_modtime = src_sbuf.st_mtime;
4112 * As we are opening fsp1 read-only we only expect
4113 * an error on close on fsp2 if we are out of space.
4114 * Thus we don't look at the error return from the
4115 * close of fsp1.
4117 *err_ret = close_file(fsp2,False);
4119 return(ret == (SMB_OFF_T)src_sbuf.st_size);
4122 /****************************************************************************
4123 Reply to a file copy.
4124 ****************************************************************************/
4126 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4128 int outsize = 0;
4129 pstring name;
4130 pstring directory;
4131 pstring mask,newname;
4132 char *p;
4133 int count=0;
4134 int error = ERRnoaccess;
4135 int err = 0;
4136 BOOL has_wild;
4137 BOOL exists=False;
4138 int tid2 = SVAL(inbuf,smb_vwv0);
4139 int ofun = SVAL(inbuf,smb_vwv1);
4140 int flags = SVAL(inbuf,smb_vwv2);
4141 BOOL target_is_directory=False;
4142 BOOL bad_path1 = False;
4143 BOOL bad_path2 = False;
4144 BOOL rc = True;
4145 SMB_STRUCT_STAT sbuf1, sbuf2;
4146 NTSTATUS status;
4148 START_PROFILE(SMBcopy);
4150 *directory = *mask = 0;
4152 p = smb_buf(inbuf);
4153 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True);
4154 if (!NT_STATUS_IS_OK(status)) {
4155 END_PROFILE(SMBcopy);
4156 return ERROR_NT(status);
4158 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True);
4159 if (!NT_STATUS_IS_OK(status)) {
4160 END_PROFILE(SMBcopy);
4161 return ERROR_NT(status);
4164 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
4166 if (tid2 != conn->cnum) {
4167 /* can't currently handle inter share copies XXXX */
4168 DEBUG(3,("Rejecting inter-share copy\n"));
4169 END_PROFILE(SMBcopy);
4170 return ERROR_DOS(ERRSRV,ERRinvdevice);
4173 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
4174 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4176 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
4177 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
4179 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
4181 if ((flags&1) && target_is_directory) {
4182 END_PROFILE(SMBcopy);
4183 return ERROR_DOS(ERRDOS,ERRbadfile);
4186 if ((flags&2) && !target_is_directory) {
4187 END_PROFILE(SMBcopy);
4188 return ERROR_DOS(ERRDOS,ERRbadpath);
4191 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
4192 /* wants a tree copy! XXXX */
4193 DEBUG(3,("Rejecting tree copy\n"));
4194 END_PROFILE(SMBcopy);
4195 return ERROR_DOS(ERRSRV,ERRerror);
4198 p = strrchr_m(name,'/');
4199 if (!p) {
4200 pstrcpy(directory,"./");
4201 pstrcpy(mask,name);
4202 } else {
4203 *p = 0;
4204 pstrcpy(directory,name);
4205 pstrcpy(mask,p+1);
4209 * We should only check the mangled cache
4210 * here if unix_convert failed. This means
4211 * that the path in 'mask' doesn't exist
4212 * on the file system and so we need to look
4213 * for a possible mangle. This patch from
4214 * Tine Smukavec <valentin.smukavec@hermes.si>.
4217 if (!rc && mangle_is_mangled(mask))
4218 mangle_check_cache( mask, sizeof(pstring)-1 );
4220 has_wild = ms_has_wild(mask);
4222 if (!has_wild) {
4223 pstrcat(directory,"/");
4224 pstrcat(directory,mask);
4225 if (resolve_wildcards(directory,newname) &&
4226 copy_file(directory,newname,conn,ofun, count,target_is_directory,&err))
4227 count++;
4228 if(!count && err) {
4229 errno = err;
4230 END_PROFILE(SMBcopy);
4231 return(UNIXERROR(ERRHRD,ERRgeneral));
4233 if (!count) {
4234 exists = vfs_file_exist(conn,directory,NULL);
4236 } else {
4237 void *dirptr = NULL;
4238 const char *dname;
4239 pstring destname;
4241 if (check_name(directory,conn))
4242 dirptr = OpenDir(conn, directory, True);
4244 if (dirptr) {
4245 error = ERRbadfile;
4247 if (strequal(mask,"????????.???"))
4248 pstrcpy(mask,"*");
4250 while ((dname = ReadDirName(dirptr))) {
4251 pstring fname;
4252 pstrcpy(fname,dname);
4254 if(!mask_match(fname, mask, conn->case_sensitive))
4255 continue;
4257 error = ERRnoaccess;
4258 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
4259 pstrcpy(destname,newname);
4260 if (resolve_wildcards(fname,destname) &&
4261 copy_file(fname,destname,conn,ofun,
4262 count,target_is_directory,&err))
4263 count++;
4264 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
4266 CloseDir(dirptr);
4270 if (count == 0) {
4271 if(err) {
4272 /* Error on close... */
4273 errno = err;
4274 END_PROFILE(SMBcopy);
4275 return(UNIXERROR(ERRHRD,ERRgeneral));
4278 if (exists) {
4279 END_PROFILE(SMBcopy);
4280 return ERROR_DOS(ERRDOS,error);
4281 } else {
4282 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
4283 unix_ERR_class = ERRDOS;
4284 unix_ERR_code = ERRbadpath;
4286 END_PROFILE(SMBcopy);
4287 return(UNIXERROR(ERRDOS,error));
4291 outsize = set_message(outbuf,1,0,True);
4292 SSVAL(outbuf,smb_vwv0,count);
4294 END_PROFILE(SMBcopy);
4295 return(outsize);
4298 /****************************************************************************
4299 Reply to a setdir.
4300 ****************************************************************************/
4302 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4304 int snum;
4305 int outsize = 0;
4306 BOOL ok = False;
4307 pstring newdir;
4308 NTSTATUS status;
4310 START_PROFILE(pathworks_setdir);
4312 snum = SNUM(conn);
4313 if (!CAN_SETDIR(snum)) {
4314 END_PROFILE(pathworks_setdir);
4315 return ERROR_DOS(ERRDOS,ERRnoaccess);
4318 srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status, False);
4319 if (!NT_STATUS_IS_OK(status)) {
4320 END_PROFILE(pathworks_setdir);
4321 return ERROR_NT(status);
4324 if (strlen(newdir) == 0) {
4325 ok = True;
4326 } else {
4327 ok = vfs_directory_exist(conn,newdir,NULL);
4328 if (ok)
4329 string_set(&conn->connectpath,newdir);
4332 if (!ok) {
4333 END_PROFILE(pathworks_setdir);
4334 return ERROR_DOS(ERRDOS,ERRbadpath);
4337 outsize = set_message(outbuf,0,0,True);
4338 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
4340 DEBUG(3,("setdir %s\n", newdir));
4342 END_PROFILE(pathworks_setdir);
4343 return(outsize);
4346 /****************************************************************************
4347 Get a lock pid, dealing with large count requests.
4348 ****************************************************************************/
4350 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
4352 if(!large_file_format)
4353 return SVAL(data,SMB_LPID_OFFSET(data_offset));
4354 else
4355 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
4358 /****************************************************************************
4359 Get a lock count, dealing with large count requests.
4360 ****************************************************************************/
4362 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4364 SMB_BIG_UINT count = 0;
4366 if(!large_file_format) {
4367 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4368 } else {
4370 #if defined(HAVE_LONGLONG)
4371 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4372 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4373 #else /* HAVE_LONGLONG */
4376 * NT4.x seems to be broken in that it sends large file (64 bit)
4377 * lockingX calls even if the CAP_LARGE_FILES was *not*
4378 * negotiated. For boxes without large unsigned ints truncate the
4379 * lock count by dropping the top 32 bits.
4382 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4383 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4384 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4385 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4386 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4389 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4390 #endif /* HAVE_LONGLONG */
4393 return count;
4396 #if !defined(HAVE_LONGLONG)
4397 /****************************************************************************
4398 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
4399 ****************************************************************************/
4401 static uint32 map_lock_offset(uint32 high, uint32 low)
4403 unsigned int i;
4404 uint32 mask = 0;
4405 uint32 highcopy = high;
4408 * Try and find out how many significant bits there are in high.
4411 for(i = 0; highcopy; i++)
4412 highcopy >>= 1;
4415 * We use 31 bits not 32 here as POSIX
4416 * lock offsets may not be negative.
4419 mask = (~0) << (31 - i);
4421 if(low & mask)
4422 return 0; /* Fail. */
4424 high <<= (31 - i);
4426 return (high|low);
4428 #endif /* !defined(HAVE_LONGLONG) */
4430 /****************************************************************************
4431 Get a lock offset, dealing with large offset requests.
4432 ****************************************************************************/
4434 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4436 SMB_BIG_UINT offset = 0;
4438 *err = False;
4440 if(!large_file_format) {
4441 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4442 } else {
4444 #if defined(HAVE_LONGLONG)
4445 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4446 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4447 #else /* HAVE_LONGLONG */
4450 * NT4.x seems to be broken in that it sends large file (64 bit)
4451 * lockingX calls even if the CAP_LARGE_FILES was *not*
4452 * negotiated. For boxes without large unsigned ints mangle the
4453 * lock offset by mapping the top 32 bits onto the lower 32.
4456 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4457 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4458 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4459 uint32 new_low = 0;
4461 if((new_low = map_lock_offset(high, low)) == 0) {
4462 *err = True;
4463 return (SMB_BIG_UINT)-1;
4466 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4467 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4468 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4469 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4472 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4473 #endif /* HAVE_LONGLONG */
4476 return offset;
4479 /****************************************************************************
4480 Reply to a lockingX request.
4481 ****************************************************************************/
4483 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4485 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4486 unsigned char locktype = CVAL(inbuf,smb_vwv3);
4487 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4488 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4489 uint16 num_locks = SVAL(inbuf,smb_vwv7);
4490 SMB_BIG_UINT count = 0, offset = 0;
4491 uint16 lock_pid;
4492 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4493 int i;
4494 char *data;
4495 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4496 BOOL err;
4497 BOOL my_lock_ctx = False;
4498 NTSTATUS status;
4500 START_PROFILE(SMBlockingX);
4502 CHECK_FSP(fsp,conn);
4504 data = smb_buf(inbuf);
4506 if (locktype & (LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_CHANGE_LOCKTYPE)) {
4507 /* we don't support these - and CANCEL_LOCK makes w2k
4508 and XP reboot so I don't really want to be
4509 compatible! (tridge) */
4510 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
4513 /* Check if this is an oplock break on a file
4514 we have granted an oplock on.
4516 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
4517 /* Client can insist on breaking to none. */
4518 BOOL break_to_none = (oplocklevel == 0);
4520 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4521 (unsigned int)oplocklevel, fsp->fnum ));
4524 * Make sure we have granted an exclusive or batch oplock on this file.
4527 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
4528 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4529 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4531 /* if this is a pure oplock break request then don't send a reply */
4532 if (num_locks == 0 && num_ulocks == 0) {
4533 END_PROFILE(SMBlockingX);
4534 return -1;
4535 } else {
4536 END_PROFILE(SMBlockingX);
4537 return ERROR_DOS(ERRDOS,ERRlock);
4541 if (remove_oplock(fsp, break_to_none) == False) {
4542 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4543 fsp->fsp_name ));
4546 /* if this is a pure oplock break request then don't send a reply */
4547 if (num_locks == 0 && num_ulocks == 0) {
4548 /* Sanity check - ensure a pure oplock break is not a
4549 chained request. */
4550 if(CVAL(inbuf,smb_vwv0) != 0xff)
4551 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4552 (unsigned int)CVAL(inbuf,smb_vwv0) ));
4553 END_PROFILE(SMBlockingX);
4554 return -1;
4559 * We do this check *after* we have checked this is not a oplock break
4560 * response message. JRA.
4563 release_level_2_oplocks_on_change(fsp);
4565 /* Data now points at the beginning of the list
4566 of smb_unlkrng structs */
4567 for(i = 0; i < (int)num_ulocks; i++) {
4568 lock_pid = get_lock_pid( data, i, large_file_format);
4569 count = get_lock_count( data, i, large_file_format);
4570 offset = get_lock_offset( data, i, large_file_format, &err);
4573 * There is no error code marked "stupid client bug".... :-).
4575 if(err) {
4576 END_PROFILE(SMBlockingX);
4577 return ERROR_DOS(ERRDOS,ERRnoaccess);
4580 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4581 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4583 status = do_unlock(fsp,conn,lock_pid,count,offset);
4584 if (NT_STATUS_V(status)) {
4585 END_PROFILE(SMBlockingX);
4586 return ERROR_NT(status);
4590 /* Setup the timeout in seconds. */
4592 lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000);
4594 /* Now do any requested locks */
4595 data += ((large_file_format ? 20 : 10)*num_ulocks);
4597 /* Data now points at the beginning of the list
4598 of smb_lkrng structs */
4600 for(i = 0; i < (int)num_locks; i++) {
4601 lock_pid = get_lock_pid( data, i, large_file_format);
4602 count = get_lock_count( data, i, large_file_format);
4603 offset = get_lock_offset( data, i, large_file_format, &err);
4606 * There is no error code marked "stupid client bug".... :-).
4608 if(err) {
4609 END_PROFILE(SMBlockingX);
4610 return ERROR_DOS(ERRDOS,ERRnoaccess);
4613 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
4614 (double)offset, (double)count, (unsigned int)lock_pid,
4615 fsp->fsp_name, (int)lock_timeout ));
4617 status = do_lock_spin(fsp,conn,lock_pid, count,offset,
4618 ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &my_lock_ctx);
4619 if (NT_STATUS_V(status)) {
4621 * Interesting fact found by IFSTEST /t LockOverlappedTest...
4622 * Even if it's our own lock context, we need to wait here as
4623 * there may be an unlock on the way.
4624 * So I removed a "&& !my_lock_ctx" from the following
4625 * if statement. JRA.
4627 if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
4629 * A blocking lock was requested. Package up
4630 * this smb into a queued request and push it
4631 * onto the blocking lock queue.
4633 if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) {
4634 END_PROFILE(SMBlockingX);
4635 return -1;
4638 break;
4642 /* If any of the above locks failed, then we must unlock
4643 all of the previous locks (X/Open spec). */
4644 if (i != num_locks && num_locks != 0) {
4646 * Ensure we don't do a remove on the lock that just failed,
4647 * as under POSIX rules, if we have a lock already there, we
4648 * will delete it (and we shouldn't) .....
4650 for(i--; i >= 0; i--) {
4651 lock_pid = get_lock_pid( data, i, large_file_format);
4652 count = get_lock_count( data, i, large_file_format);
4653 offset = get_lock_offset( data, i, large_file_format, &err);
4656 * There is no error code marked "stupid client bug".... :-).
4658 if(err) {
4659 END_PROFILE(SMBlockingX);
4660 return ERROR_DOS(ERRDOS,ERRnoaccess);
4663 do_unlock(fsp,conn,lock_pid,count,offset);
4665 END_PROFILE(SMBlockingX);
4666 return ERROR_NT(status);
4669 set_message(outbuf,2,0,True);
4671 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4672 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4674 END_PROFILE(SMBlockingX);
4675 return chain_reply(inbuf,outbuf,length,bufsize);
4678 /****************************************************************************
4679 Reply to a SMBreadbmpx (read block multiplex) request.
4680 ****************************************************************************/
4682 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4684 ssize_t nread = -1;
4685 ssize_t total_read;
4686 char *data;
4687 SMB_OFF_T startpos;
4688 int outsize;
4689 size_t maxcount;
4690 int max_per_packet;
4691 size_t tcount;
4692 int pad;
4693 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4694 START_PROFILE(SMBreadBmpx);
4696 /* this function doesn't seem to work - disable by default */
4697 if (!lp_readbmpx()) {
4698 END_PROFILE(SMBreadBmpx);
4699 return ERROR_DOS(ERRSRV,ERRuseSTD);
4702 outsize = set_message(outbuf,8,0,True);
4704 CHECK_FSP(fsp,conn);
4705 CHECK_READ(fsp);
4707 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
4708 maxcount = SVAL(inbuf,smb_vwv3);
4710 data = smb_buf(outbuf);
4711 pad = ((long)data)%4;
4712 if (pad)
4713 pad = 4 - pad;
4714 data += pad;
4716 max_per_packet = bufsize-(outsize+pad);
4717 tcount = maxcount;
4718 total_read = 0;
4720 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
4721 END_PROFILE(SMBreadBmpx);
4722 return ERROR_DOS(ERRDOS,ERRlock);
4725 do {
4726 size_t N = MIN(max_per_packet,tcount-total_read);
4728 nread = read_file(fsp,data,startpos,N);
4730 if (nread <= 0)
4731 nread = 0;
4733 if (nread < (ssize_t)N)
4734 tcount = total_read + nread;
4736 set_message(outbuf,8,nread,False);
4737 SIVAL(outbuf,smb_vwv0,startpos);
4738 SSVAL(outbuf,smb_vwv2,tcount);
4739 SSVAL(outbuf,smb_vwv6,nread);
4740 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4742 if (!send_smb(smbd_server_fd(),outbuf))
4743 exit_server("reply_readbmpx: send_smb failed.");
4745 total_read += nread;
4746 startpos += nread;
4747 } while (total_read < (ssize_t)tcount);
4749 END_PROFILE(SMBreadBmpx);
4750 return(-1);
4753 /****************************************************************************
4754 Reply to a SMBsetattrE.
4755 ****************************************************************************/
4757 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4759 struct utimbuf unix_times;
4760 int outsize = 0;
4761 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4762 START_PROFILE(SMBsetattrE);
4764 outsize = set_message(outbuf,0,0,True);
4766 if(!fsp || (fsp->conn != conn)) {
4767 END_PROFILE(SMBgetattrE);
4768 return ERROR_DOS(ERRDOS,ERRbadfid);
4772 * Convert the DOS times into unix times. Ignore create
4773 * time as UNIX can't set this.
4776 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4777 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4780 * Patch from Ray Frush <frush@engr.colostate.edu>
4781 * Sometimes times are sent as zero - ignore them.
4784 if ((unix_times.actime == 0) && (unix_times.modtime == 0)) {
4785 /* Ignore request */
4786 if( DEBUGLVL( 3 ) ) {
4787 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4788 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4790 END_PROFILE(SMBsetattrE);
4791 return(outsize);
4792 } else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) {
4793 /* set modify time = to access time if modify time was 0 */
4794 unix_times.modtime = unix_times.actime;
4797 /* Set the date on this file */
4798 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4799 END_PROFILE(SMBsetattrE);
4800 return ERROR_DOS(ERRDOS,ERRnoaccess);
4803 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4804 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4806 END_PROFILE(SMBsetattrE);
4807 return(outsize);
4811 /* Back from the dead for OS/2..... JRA. */
4813 /****************************************************************************
4814 Reply to a SMBwritebmpx (write block multiplex primary) request.
4815 ****************************************************************************/
4817 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4819 size_t numtowrite;
4820 ssize_t nwritten = -1;
4821 int outsize = 0;
4822 SMB_OFF_T startpos;
4823 size_t tcount;
4824 BOOL write_through;
4825 int smb_doff;
4826 char *data;
4827 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4828 START_PROFILE(SMBwriteBmpx);
4830 CHECK_FSP(fsp,conn);
4831 CHECK_WRITE(fsp);
4832 CHECK_ERROR(fsp);
4834 tcount = SVAL(inbuf,smb_vwv1);
4835 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
4836 write_through = BITSETW(inbuf+smb_vwv7,0);
4837 numtowrite = SVAL(inbuf,smb_vwv10);
4838 smb_doff = SVAL(inbuf,smb_vwv11);
4840 data = smb_base(inbuf) + smb_doff;
4842 /* If this fails we need to send an SMBwriteC response,
4843 not an SMBwritebmpx - set this up now so we don't forget */
4844 SCVAL(outbuf,smb_com,SMBwritec);
4846 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK,False)) {
4847 END_PROFILE(SMBwriteBmpx);
4848 return(ERROR_DOS(ERRDOS,ERRlock));
4851 nwritten = write_file(fsp,data,startpos,numtowrite);
4853 if(lp_syncalways(SNUM(conn)) || write_through)
4854 sync_file(conn,fsp);
4856 if(nwritten < (ssize_t)numtowrite) {
4857 END_PROFILE(SMBwriteBmpx);
4858 return(UNIXERROR(ERRHRD,ERRdiskfull));
4861 /* If the maximum to be written to this file
4862 is greater than what we just wrote then set
4863 up a secondary struct to be attached to this
4864 fd, we will use this to cache error messages etc. */
4866 if((ssize_t)tcount > nwritten) {
4867 write_bmpx_struct *wbms;
4868 if(fsp->wbmpx_ptr != NULL)
4869 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4870 else
4871 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
4872 if(!wbms) {
4873 DEBUG(0,("Out of memory in reply_readmpx\n"));
4874 END_PROFILE(SMBwriteBmpx);
4875 return(ERROR_DOS(ERRSRV,ERRnoresource));
4877 wbms->wr_mode = write_through;
4878 wbms->wr_discard = False; /* No errors yet */
4879 wbms->wr_total_written = nwritten;
4880 wbms->wr_errclass = 0;
4881 wbms->wr_error = 0;
4882 fsp->wbmpx_ptr = wbms;
4885 /* We are returning successfully, set the message type back to
4886 SMBwritebmpx */
4887 SCVAL(outbuf,smb_com,SMBwriteBmpx);
4889 outsize = set_message(outbuf,1,0,True);
4891 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
4893 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4894 fsp->fnum, (int)numtowrite, (int)nwritten ) );
4896 if (write_through && tcount==nwritten) {
4897 /* We need to send both a primary and a secondary response */
4898 smb_setlen(outbuf,outsize - 4);
4899 if (!send_smb(smbd_server_fd(),outbuf))
4900 exit_server("reply_writebmpx: send_smb failed.");
4902 /* Now the secondary */
4903 outsize = set_message(outbuf,1,0,True);
4904 SCVAL(outbuf,smb_com,SMBwritec);
4905 SSVAL(outbuf,smb_vwv0,nwritten);
4908 END_PROFILE(SMBwriteBmpx);
4909 return(outsize);
4912 /****************************************************************************
4913 Reply to a SMBwritebs (write block multiplex secondary) request.
4914 ****************************************************************************/
4916 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4918 size_t numtowrite;
4919 ssize_t nwritten = -1;
4920 int outsize = 0;
4921 SMB_OFF_T startpos;
4922 size_t tcount;
4923 BOOL write_through;
4924 int smb_doff;
4925 char *data;
4926 write_bmpx_struct *wbms;
4927 BOOL send_response = False;
4928 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4929 START_PROFILE(SMBwriteBs);
4931 CHECK_FSP(fsp,conn);
4932 CHECK_WRITE(fsp);
4934 tcount = SVAL(inbuf,smb_vwv1);
4935 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
4936 numtowrite = SVAL(inbuf,smb_vwv6);
4937 smb_doff = SVAL(inbuf,smb_vwv7);
4939 data = smb_base(inbuf) + smb_doff;
4941 /* We need to send an SMBwriteC response, not an SMBwritebs */
4942 SCVAL(outbuf,smb_com,SMBwritec);
4944 /* This fd should have an auxiliary struct attached,
4945 check that it does */
4946 wbms = fsp->wbmpx_ptr;
4947 if(!wbms) {
4948 END_PROFILE(SMBwriteBs);
4949 return(-1);
4952 /* If write through is set we can return errors, else we must cache them */
4953 write_through = wbms->wr_mode;
4955 /* Check for an earlier error */
4956 if(wbms->wr_discard) {
4957 END_PROFILE(SMBwriteBs);
4958 return -1; /* Just discard the packet */
4961 nwritten = write_file(fsp,data,startpos,numtowrite);
4963 if(lp_syncalways(SNUM(conn)) || write_through)
4964 sync_file(conn,fsp);
4966 if (nwritten < (ssize_t)numtowrite) {
4967 if(write_through) {
4968 /* We are returning an error - we can delete the aux struct */
4969 if (wbms)
4970 free((char *)wbms);
4971 fsp->wbmpx_ptr = NULL;
4972 END_PROFILE(SMBwriteBs);
4973 return(ERROR_DOS(ERRHRD,ERRdiskfull));
4975 END_PROFILE(SMBwriteBs);
4976 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4979 /* Increment the total written, if this matches tcount
4980 we can discard the auxiliary struct (hurrah !) and return a writeC */
4981 wbms->wr_total_written += nwritten;
4982 if(wbms->wr_total_written >= tcount) {
4983 if (write_through) {
4984 outsize = set_message(outbuf,1,0,True);
4985 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
4986 send_response = True;
4989 free((char *)wbms);
4990 fsp->wbmpx_ptr = NULL;
4993 if(send_response) {
4994 END_PROFILE(SMBwriteBs);
4995 return(outsize);
4998 END_PROFILE(SMBwriteBs);
4999 return(-1);
5002 /****************************************************************************
5003 Reply to a SMBgetattrE.
5004 ****************************************************************************/
5006 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5008 SMB_STRUCT_STAT sbuf;
5009 int outsize = 0;
5010 int mode;
5011 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5012 START_PROFILE(SMBgetattrE);
5014 outsize = set_message(outbuf,11,0,True);
5016 if(!fsp || (fsp->conn != conn)) {
5017 END_PROFILE(SMBgetattrE);
5018 return ERROR_DOS(ERRDOS,ERRbadfid);
5021 /* Do an fstat on this file */
5022 if(fsp_stat(fsp, &sbuf)) {
5023 END_PROFILE(SMBgetattrE);
5024 return(UNIXERROR(ERRDOS,ERRnoaccess));
5027 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
5030 * Convert the times into dos times. Set create
5031 * date to be last modify date as UNIX doesn't save
5032 * this.
5035 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
5036 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
5037 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
5039 if (mode & aDIR) {
5040 SIVAL(outbuf,smb_vwv6,0);
5041 SIVAL(outbuf,smb_vwv8,0);
5042 } else {
5043 uint32 allocation_size = get_allocation_size(fsp, &sbuf);
5044 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
5045 SIVAL(outbuf,smb_vwv8,allocation_size);
5047 SSVAL(outbuf,smb_vwv10, mode);
5049 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
5051 END_PROFILE(SMBgetattrE);
5052 return(outsize);