r1899: this is 3.0.6 -- will release tomorrow
[Samba.git] / source / smbd / reply.c
blob611fb04c19bb02f8b6dc4964f3507edc277ddc34
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] == '.') && (IS_DIRECTORY_SEP(s[1]) || (s[1] == '\0'))) {
103 * No mb char starts with '.' so we're safe checking the directory separator here.
106 /* "./" or ".\\" fails with a different error depending on where it is... */
108 if (s == srcname) {
109 ret = NT_STATUS_OBJECT_NAME_INVALID;
110 break;
111 } else {
112 if (s[1] != '\0' && s[2] == '\0') {
113 ret = NT_STATUS_INVALID_PARAMETER;
114 break;
116 ret = NT_STATUS_OBJECT_PATH_NOT_FOUND;
117 break;
119 s++;
120 } else {
121 if (!(*s & 0x80)) {
122 if (allow_wcard_names) {
123 *d++ = *s++;
124 } else {
125 switch (*s) {
126 case '*':
127 case '?':
128 case '<':
129 case '>':
130 case '"':
131 return NT_STATUS_OBJECT_NAME_INVALID;
132 default:
133 *d++ = *s++;
134 break;
137 } else {
138 switch(next_mb_char_size(s)) {
139 case 4:
140 *d++ = *s++;
141 case 3:
142 *d++ = *s++;
143 case 2:
144 *d++ = *s++;
145 case 1:
146 *d++ = *s++;
147 break;
148 default:
149 DEBUG(0,("check_path_syntax: character length assumptions invalid !\n"));
150 *d = '\0';
151 return NT_STATUS_INVALID_PARAMETER;
156 *d = '\0';
157 return ret;
160 /****************************************************************************
161 Pull a string and check the path - provide for error return.
162 ****************************************************************************/
164 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)
166 pstring tmppath;
167 char *tmppath_ptr = tmppath;
168 size_t ret;
169 #ifdef DEVELOPER
170 SMB_ASSERT(dest_len == sizeof(pstring));
171 #endif
173 if (src_len == 0) {
174 ret = srvstr_pull_buf( inbuf, tmppath_ptr, src, dest_len, flags);
175 } else {
176 ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags);
178 *err = check_path_syntax(dest, tmppath, allow_wcard_names);
179 return ret;
182 /****************************************************************************
183 Reply to a special message.
184 ****************************************************************************/
186 int reply_special(char *inbuf,char *outbuf)
188 int outsize = 4;
189 int msg_type = CVAL(inbuf,0);
190 int msg_flags = CVAL(inbuf,1);
191 fstring name1,name2;
192 char name_type = 0;
194 static BOOL already_got_session = False;
196 *name1 = *name2 = 0;
198 memset(outbuf,'\0',smb_size);
200 smb_setlen(outbuf,0);
202 switch (msg_type) {
203 case 0x81: /* session request */
205 if (already_got_session) {
206 exit_server("multiple session request not permitted");
209 SCVAL(outbuf,0,0x82);
210 SCVAL(outbuf,3,0);
211 if (name_len(inbuf+4) > 50 ||
212 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
213 DEBUG(0,("Invalid name length in session request\n"));
214 return(0);
216 name_extract(inbuf,4,name1);
217 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
218 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
219 name1,name2));
221 set_local_machine_name(name1, True);
222 set_remote_machine_name(name2, True);
224 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
225 get_local_machine_name(), get_remote_machine_name(),
226 name_type));
228 if (name_type == 'R') {
229 /* We are being asked for a pathworks session ---
230 no thanks! */
231 SCVAL(outbuf, 0,0x83);
232 break;
235 /* only add the client's machine name to the list
236 of possibly valid usernames if we are operating
237 in share mode security */
238 if (lp_security() == SEC_SHARE) {
239 add_session_user(get_remote_machine_name());
242 reload_services(True);
243 reopen_logs();
245 claim_connection(NULL,"",0,True,FLAG_MSG_GENERAL|FLAG_MSG_SMBD|FLAG_MSG_PRINT_GENERAL);
247 already_got_session = True;
248 break;
250 case 0x89: /* session keepalive request
251 (some old clients produce this?) */
252 SCVAL(outbuf,0,SMBkeepalive);
253 SCVAL(outbuf,3,0);
254 break;
256 case 0x82: /* positive session response */
257 case 0x83: /* negative session response */
258 case 0x84: /* retarget session response */
259 DEBUG(0,("Unexpected session response\n"));
260 break;
262 case SMBkeepalive: /* session keepalive */
263 default:
264 return(0);
267 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
268 msg_type, msg_flags));
270 return(outsize);
273 /****************************************************************************
274 Reply to a tcon.
275 ****************************************************************************/
277 int reply_tcon(connection_struct *conn,
278 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
280 const char *service;
281 pstring service_buf;
282 pstring password;
283 pstring dev;
284 int outsize = 0;
285 uint16 vuid = SVAL(inbuf,smb_uid);
286 int pwlen=0;
287 NTSTATUS nt_status;
288 char *p;
289 DATA_BLOB password_blob;
291 START_PROFILE(SMBtcon);
293 *service_buf = *password = *dev = 0;
295 p = smb_buf(inbuf)+1;
296 p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service_buf), STR_TERMINATE) + 1;
297 pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1;
298 p += pwlen;
299 p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1;
301 p = strrchr_m(service_buf,'\\');
302 if (p) {
303 service = p+1;
304 } else {
305 service = service_buf;
308 password_blob = data_blob(password, pwlen+1);
310 conn = make_connection(service,password_blob,dev,vuid,&nt_status);
312 data_blob_clear_free(&password_blob);
314 if (!conn) {
315 END_PROFILE(SMBtcon);
316 return ERROR_NT(nt_status);
319 outsize = set_message(outbuf,2,0,True);
320 SSVAL(outbuf,smb_vwv0,max_recv);
321 SSVAL(outbuf,smb_vwv1,conn->cnum);
322 SSVAL(outbuf,smb_tid,conn->cnum);
324 DEBUG(3,("tcon service=%s cnum=%d\n",
325 service, conn->cnum));
327 END_PROFILE(SMBtcon);
328 return(outsize);
331 /****************************************************************************
332 Reply to a tcon and X.
333 ****************************************************************************/
335 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
337 fstring service;
338 DATA_BLOB password;
340 /* what the cleint thinks the device is */
341 fstring client_devicetype;
342 /* what the server tells the client the share represents */
343 const char *server_devicetype;
344 NTSTATUS nt_status;
345 uint16 vuid = SVAL(inbuf,smb_uid);
346 int passlen = SVAL(inbuf,smb_vwv3);
347 pstring path;
348 char *p, *q;
349 extern BOOL global_encrypted_passwords_negotiated;
351 START_PROFILE(SMBtconX);
353 *service = *client_devicetype = 0;
355 /* we might have to close an old one */
356 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
357 close_cnum(conn,vuid);
360 if (passlen > MAX_PASS_LEN) {
361 return ERROR_DOS(ERRDOS,ERRbuftoosmall);
364 if (global_encrypted_passwords_negotiated) {
365 password = data_blob(smb_buf(inbuf),passlen);
366 } else {
367 password = data_blob(smb_buf(inbuf),passlen+1);
368 /* Ensure correct termination */
369 password.data[passlen]=0;
372 p = smb_buf(inbuf) + passlen;
373 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
376 * the service name can be either: \\server\share
377 * or share directly like on the DELL PowerVault 705
379 if (*path=='\\') {
380 q = strchr_m(path+2,'\\');
381 if (!q) {
382 END_PROFILE(SMBtconX);
383 return(ERROR_DOS(ERRDOS,ERRnosuchshare));
385 fstrcpy(service,q+1);
387 else
388 fstrcpy(service,path);
390 p += srvstr_pull(inbuf, client_devicetype, p, sizeof(client_devicetype), 6, STR_ASCII);
392 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
394 conn = make_connection(service,password,client_devicetype,vuid,&nt_status);
396 data_blob_clear_free(&password);
398 if (!conn) {
399 END_PROFILE(SMBtconX);
400 return ERROR_NT(nt_status);
403 if ( IS_IPC(conn) )
404 server_devicetype = "IPC";
405 else if ( IS_PRINT(conn) )
406 server_devicetype = "LPT1:";
407 else
408 server_devicetype = "A:";
410 if (Protocol < PROTOCOL_NT1) {
411 set_message(outbuf,2,0,True);
412 p = smb_buf(outbuf);
413 p += srvstr_push(outbuf, p, server_devicetype, -1,
414 STR_TERMINATE|STR_ASCII);
415 set_message_end(outbuf,p);
416 } else {
417 /* NT sets the fstype of IPC$ to the null string */
418 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
420 set_message(outbuf,3,0,True);
422 p = smb_buf(outbuf);
423 p += srvstr_push(outbuf, p, server_devicetype, -1,
424 STR_TERMINATE|STR_ASCII);
425 p += srvstr_push(outbuf, p, fstype, -1,
426 STR_TERMINATE);
428 set_message_end(outbuf,p);
430 /* what does setting this bit do? It is set by NT4 and
431 may affect the ability to autorun mounted cdroms */
432 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
433 (lp_csc_policy(SNUM(conn)) << 2));
435 init_dfsroot(conn, inbuf, outbuf);
439 DEBUG(3,("tconX service=%s \n",
440 service));
442 /* set the incoming and outgoing tid to the just created one */
443 SSVAL(inbuf,smb_tid,conn->cnum);
444 SSVAL(outbuf,smb_tid,conn->cnum);
446 END_PROFILE(SMBtconX);
447 return chain_reply(inbuf,outbuf,length,bufsize);
450 /****************************************************************************
451 Reply to an unknown type.
452 ****************************************************************************/
454 int reply_unknown(char *inbuf,char *outbuf)
456 int type;
457 type = CVAL(inbuf,smb_com);
459 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
460 smb_fn_name(type), type, type));
462 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
465 /****************************************************************************
466 Reply to an ioctl.
467 ****************************************************************************/
469 int reply_ioctl(connection_struct *conn,
470 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
472 uint16 device = SVAL(inbuf,smb_vwv1);
473 uint16 function = SVAL(inbuf,smb_vwv2);
474 uint32 ioctl_code = (device << 16) + function;
475 int replysize, outsize;
476 char *p;
477 START_PROFILE(SMBioctl);
479 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
481 switch (ioctl_code) {
482 case IOCTL_QUERY_JOB_INFO:
483 replysize = 32;
484 break;
485 default:
486 END_PROFILE(SMBioctl);
487 return(ERROR_DOS(ERRSRV,ERRnosupport));
490 outsize = set_message(outbuf,8,replysize+1,True);
491 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
492 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
493 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
494 p = smb_buf(outbuf) + 1; /* Allow for alignment */
496 switch (ioctl_code) {
497 case IOCTL_QUERY_JOB_INFO:
499 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
500 if (!fsp) {
501 END_PROFILE(SMBioctl);
502 return(UNIXERROR(ERRDOS,ERRbadfid));
504 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
505 srvstr_push(outbuf, p+2, global_myname(), 15, STR_TERMINATE|STR_ASCII);
506 if (conn) {
507 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
509 break;
513 END_PROFILE(SMBioctl);
514 return outsize;
517 /****************************************************************************
518 Reply to a chkpth.
519 ****************************************************************************/
521 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
523 int outsize = 0;
524 int mode;
525 pstring name;
526 BOOL ok = False;
527 BOOL bad_path = False;
528 SMB_STRUCT_STAT sbuf;
529 NTSTATUS status;
531 START_PROFILE(SMBchkpth);
533 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, False);
534 if (!NT_STATUS_IS_OK(status)) {
535 END_PROFILE(SMBchkpth);
536 return ERROR_NT(status);
539 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
541 unix_convert(name,conn,0,&bad_path,&sbuf);
542 if (bad_path) {
543 END_PROFILE(SMBchkpth);
544 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
547 mode = SVAL(inbuf,smb_vwv0);
549 if (check_name(name,conn)) {
550 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,name,&sbuf) == 0)
551 if (!(ok = S_ISDIR(sbuf.st_mode))) {
552 END_PROFILE(SMBchkpth);
553 return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath);
557 if (!ok) {
558 /* We special case this - as when a Windows machine
559 is parsing a path is steps through the components
560 one at a time - if a component fails it expects
561 ERRbadpath, not ERRbadfile.
563 if(errno == ENOENT) {
565 * Windows returns different error codes if
566 * the parent directory is valid but not the
567 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
568 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
569 * if the path is invalid. This is different from set_bad_path_error()
570 * in the non-NT error case.
572 END_PROFILE(SMBchkpth);
573 return ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpath);
576 END_PROFILE(SMBchkpth);
577 return(UNIXERROR(ERRDOS,ERRbadpath));
580 outsize = set_message(outbuf,0,0,True);
582 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
584 END_PROFILE(SMBchkpth);
585 return(outsize);
588 /****************************************************************************
589 Reply to a getatr.
590 ****************************************************************************/
592 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
594 pstring fname;
595 int outsize = 0;
596 SMB_STRUCT_STAT sbuf;
597 BOOL ok = False;
598 int mode=0;
599 SMB_OFF_T size=0;
600 time_t mtime=0;
601 BOOL bad_path = False;
602 char *p;
603 NTSTATUS status;
605 START_PROFILE(SMBgetatr);
607 p = smb_buf(inbuf) + 1;
608 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status, False);
609 if (!NT_STATUS_IS_OK(status)) {
610 END_PROFILE(SMBgetatr);
611 return ERROR_NT(status);
614 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
616 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
617 under WfWg - weird! */
618 if (! (*fname)) {
619 mode = aHIDDEN | aDIR;
620 if (!CAN_WRITE(conn))
621 mode |= aRONLY;
622 size = 0;
623 mtime = 0;
624 ok = True;
625 } else {
626 unix_convert(fname,conn,0,&bad_path,&sbuf);
627 if (bad_path) {
628 END_PROFILE(SMBgetatr);
629 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
631 if (check_name(fname,conn)) {
632 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,fname,&sbuf) == 0) {
633 mode = dos_mode(conn,fname,&sbuf);
634 size = sbuf.st_size;
635 mtime = sbuf.st_mtime;
636 if (mode & aDIR)
637 size = 0;
638 ok = True;
639 } else {
640 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
645 if (!ok) {
646 END_PROFILE(SMBgetatr);
647 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadfile);
650 outsize = set_message(outbuf,10,0,True);
652 SSVAL(outbuf,smb_vwv0,mode);
653 if(lp_dos_filetime_resolution(SNUM(conn)) )
654 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
655 else
656 put_dos_date3(outbuf,smb_vwv1,mtime);
657 SIVAL(outbuf,smb_vwv3,(uint32)size);
659 if (Protocol >= PROTOCOL_NT1)
660 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
662 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
664 END_PROFILE(SMBgetatr);
665 return(outsize);
668 /****************************************************************************
669 Reply to a setatr.
670 ****************************************************************************/
672 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
674 pstring fname;
675 int outsize = 0;
676 BOOL ok=False;
677 int mode;
678 time_t mtime;
679 SMB_STRUCT_STAT sbuf;
680 BOOL bad_path = False;
681 char *p;
682 NTSTATUS status;
684 START_PROFILE(SMBsetatr);
686 p = smb_buf(inbuf) + 1;
687 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status, False);
688 if (!NT_STATUS_IS_OK(status)) {
689 END_PROFILE(SMBsetatr);
690 return ERROR_NT(status);
693 unix_convert(fname,conn,0,&bad_path,&sbuf);
694 if (bad_path) {
695 END_PROFILE(SMBsetatr);
696 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
699 mode = SVAL(inbuf,smb_vwv0);
700 mtime = make_unix_date3(inbuf+smb_vwv1);
702 if (mode != FILE_ATTRIBUTE_NORMAL) {
703 if (VALID_STAT_OF_DIR(sbuf))
704 mode |= aDIR;
705 else
706 mode &= ~aDIR;
708 if (check_name(fname,conn)) {
709 ok = (file_set_dosmode(conn,fname,mode,NULL) == 0);
711 } else {
712 ok = True;
715 if (ok)
716 ok = set_filetime(conn,fname,mtime);
718 if (!ok) {
719 END_PROFILE(SMBsetatr);
720 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
723 outsize = set_message(outbuf,0,0,True);
725 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
727 END_PROFILE(SMBsetatr);
728 return(outsize);
731 /****************************************************************************
732 Reply to a dskattr.
733 ****************************************************************************/
735 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
737 int outsize = 0;
738 SMB_BIG_UINT dfree,dsize,bsize;
739 START_PROFILE(SMBdskattr);
741 SMB_VFS_DISK_FREE(conn,".",True,&bsize,&dfree,&dsize);
743 outsize = set_message(outbuf,5,0,True);
745 if (Protocol <= PROTOCOL_LANMAN2) {
746 double total_space, free_space;
747 /* we need to scale this to a number that DOS6 can handle. We
748 use floating point so we can handle large drives on systems
749 that don't have 64 bit integers
751 we end up displaying a maximum of 2G to DOS systems
753 total_space = dsize * (double)bsize;
754 free_space = dfree * (double)bsize;
756 dsize = (total_space+63*512) / (64*512);
757 dfree = (free_space+63*512) / (64*512);
759 if (dsize > 0xFFFF) dsize = 0xFFFF;
760 if (dfree > 0xFFFF) dfree = 0xFFFF;
762 SSVAL(outbuf,smb_vwv0,dsize);
763 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
764 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
765 SSVAL(outbuf,smb_vwv3,dfree);
766 } else {
767 SSVAL(outbuf,smb_vwv0,dsize);
768 SSVAL(outbuf,smb_vwv1,bsize/512);
769 SSVAL(outbuf,smb_vwv2,512);
770 SSVAL(outbuf,smb_vwv3,dfree);
773 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
775 END_PROFILE(SMBdskattr);
776 return(outsize);
779 /****************************************************************************
780 Reply to a search.
781 Can be called from SMBsearch, SMBffirst or SMBfunique.
782 ****************************************************************************/
784 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
786 pstring mask;
787 pstring directory;
788 pstring fname;
789 SMB_OFF_T size;
790 int mode;
791 time_t date;
792 int dirtype;
793 int outsize = 0;
794 unsigned int numentries = 0;
795 unsigned int maxentries = 0;
796 BOOL finished = False;
797 char *p;
798 BOOL ok = False;
799 int status_len;
800 pstring path;
801 char status[21];
802 int dptr_num= -1;
803 BOOL check_descend = False;
804 BOOL expect_close = False;
805 BOOL can_open = True;
806 BOOL bad_path = False;
807 NTSTATUS nt_status;
808 START_PROFILE(SMBsearch);
810 *mask = *directory = *fname = 0;
812 /* If we were called as SMBffirst then we must expect close. */
813 if(CVAL(inbuf,smb_com) == SMBffirst)
814 expect_close = True;
816 outsize = set_message(outbuf,1,3,True);
817 maxentries = SVAL(inbuf,smb_vwv0);
818 dirtype = SVAL(inbuf,smb_vwv1);
819 p = smb_buf(inbuf) + 1;
820 p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &nt_status, True);
821 if (!NT_STATUS_IS_OK(nt_status)) {
822 END_PROFILE(SMBsearch);
823 return ERROR_NT(nt_status);
825 p++;
826 status_len = SVAL(p, 0);
827 p += 2;
829 /* dirtype &= ~aDIR; */
831 if (status_len == 0) {
832 SMB_STRUCT_STAT sbuf;
833 pstring dir2;
835 pstrcpy(directory,path);
836 pstrcpy(dir2,path);
837 unix_convert(directory,conn,0,&bad_path,&sbuf);
838 unix_format(dir2);
840 if (!check_name(directory,conn))
841 can_open = False;
843 p = strrchr_m(dir2,'/');
844 if (p == NULL) {
845 pstrcpy(mask,dir2);
846 *dir2 = 0;
847 } else {
848 *p = 0;
849 pstrcpy(mask,p+1);
852 p = strrchr_m(directory,'/');
853 if (!p)
854 *directory = 0;
855 else
856 *p = 0;
858 if (strlen(directory) == 0)
859 pstrcpy(directory,".");
860 memset((char *)status,'\0',21);
861 SCVAL(status,0,(dirtype & 0x1F));
862 } else {
863 int status_dirtype;
865 memcpy(status,p,21);
866 status_dirtype = CVAL(status,0) & 0x1F;
867 if (status_dirtype != (dirtype & 0x1F))
868 dirtype = status_dirtype;
870 conn->dirptr = dptr_fetch(status+12,&dptr_num);
871 if (!conn->dirptr)
872 goto SearchEmpty;
873 string_set(&conn->dirpath,dptr_path(dptr_num));
874 pstrcpy(mask, dptr_wcard(dptr_num));
877 if (can_open) {
878 p = smb_buf(outbuf) + 3;
879 ok = True;
881 if (status_len == 0) {
882 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
883 if (dptr_num < 0) {
884 if(dptr_num == -2) {
885 END_PROFILE(SMBsearch);
886 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnofids);
888 END_PROFILE(SMBsearch);
889 return ERROR_DOS(ERRDOS,ERRnofids);
891 dptr_set_wcard(dptr_num, strdup(mask));
892 dptr_set_attr(dptr_num, dirtype);
893 } else {
894 dirtype = dptr_attr(dptr_num);
897 DEBUG(4,("dptr_num is %d\n",dptr_num));
899 if (ok) {
900 if ((dirtype&0x1F) == aVOLID) {
901 memcpy(p,status,21);
902 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0,conn->case_sensitive);
903 dptr_fill(p+12,dptr_num);
904 if (dptr_zero(p+12) && (status_len==0))
905 numentries = 1;
906 else
907 numentries = 0;
908 p += DIR_STRUCT_SIZE;
909 } else {
910 unsigned int i;
911 maxentries = MIN(maxentries, ((BUFFER_SIZE - (p - outbuf))/DIR_STRUCT_SIZE));
913 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
914 conn->dirpath,lp_dontdescend(SNUM(conn))));
915 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
916 check_descend = True;
918 for (i=numentries;(i<maxentries) && !finished;i++) {
919 finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
920 if (!finished) {
921 memcpy(p,status,21);
922 make_dir_struct(p,mask,fname,size,mode,date,conn->case_sensitive);
923 dptr_fill(p+12,dptr_num);
924 numentries++;
926 p += DIR_STRUCT_SIZE;
929 } /* if (ok ) */
933 SearchEmpty:
935 /* If we were called as SMBffirst with smb_search_id == NULL
936 and no entries were found then return error and close dirptr
937 (X/Open spec) */
939 if(ok && expect_close && numentries == 0 && status_len == 0) {
940 if (Protocol < PROTOCOL_NT1) {
941 SCVAL(outbuf,smb_rcls,ERRDOS);
942 SSVAL(outbuf,smb_err,ERRnofiles);
944 /* Also close the dptr - we know it's gone */
945 dptr_close(&dptr_num);
946 } else if (numentries == 0 || !ok) {
947 if (Protocol < PROTOCOL_NT1) {
948 SCVAL(outbuf,smb_rcls,ERRDOS);
949 SSVAL(outbuf,smb_err,ERRnofiles);
951 dptr_close(&dptr_num);
954 /* If we were called as SMBfunique, then we can close the dirptr now ! */
955 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
956 dptr_close(&dptr_num);
958 SSVAL(outbuf,smb_vwv0,numentries);
959 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
960 SCVAL(smb_buf(outbuf),0,5);
961 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
963 if (Protocol >= PROTOCOL_NT1)
964 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
966 outsize += DIR_STRUCT_SIZE*numentries;
967 smb_setlen(outbuf,outsize - 4);
969 if ((! *directory) && dptr_path(dptr_num))
970 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
972 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
973 smb_fn_name(CVAL(inbuf,smb_com)),
974 mask, directory, dirtype, numentries, maxentries ) );
976 END_PROFILE(SMBsearch);
977 return(outsize);
980 /****************************************************************************
981 Reply to a fclose (stop directory search).
982 ****************************************************************************/
984 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
986 int outsize = 0;
987 int status_len;
988 pstring path;
989 char status[21];
990 int dptr_num= -2;
991 char *p;
992 NTSTATUS err;
994 START_PROFILE(SMBfclose);
996 outsize = set_message(outbuf,1,0,True);
997 p = smb_buf(inbuf) + 1;
998 p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err, True);
999 if (!NT_STATUS_IS_OK(err)) {
1000 END_PROFILE(SMBfclose);
1001 return ERROR_NT(err);
1003 p++;
1004 status_len = SVAL(p,0);
1005 p += 2;
1007 if (status_len == 0) {
1008 END_PROFILE(SMBfclose);
1009 return ERROR_DOS(ERRSRV,ERRsrverror);
1012 memcpy(status,p,21);
1014 if(dptr_fetch(status+12,&dptr_num)) {
1015 /* Close the dptr - we know it's gone */
1016 dptr_close(&dptr_num);
1019 SSVAL(outbuf,smb_vwv0,0);
1021 DEBUG(3,("search close\n"));
1023 END_PROFILE(SMBfclose);
1024 return(outsize);
1027 /****************************************************************************
1028 Reply to an open.
1029 ****************************************************************************/
1031 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1033 pstring fname;
1034 int outsize = 0;
1035 int fmode=0;
1036 int share_mode;
1037 SMB_OFF_T size = 0;
1038 time_t mtime=0;
1039 int rmode=0;
1040 SMB_STRUCT_STAT sbuf;
1041 BOOL bad_path = False;
1042 files_struct *fsp;
1043 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1044 uint16 dos_attr = SVAL(inbuf,smb_vwv1);
1045 NTSTATUS status;
1046 START_PROFILE(SMBopen);
1048 share_mode = SVAL(inbuf,smb_vwv0);
1050 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status, False);
1051 if (!NT_STATUS_IS_OK(status)) {
1052 END_PROFILE(SMBopen);
1053 return ERROR_NT(status);
1056 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1058 unix_convert(fname,conn,0,&bad_path,&sbuf);
1059 if (bad_path) {
1060 END_PROFILE(SMBopen);
1061 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1064 fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1065 (uint32)dos_attr, oplock_request,&rmode,NULL);
1067 if (!fsp) {
1068 END_PROFILE(SMBopen);
1069 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1070 /* We have re-scheduled this call. */
1071 clear_cached_errors();
1072 return -1;
1074 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1077 size = sbuf.st_size;
1078 fmode = dos_mode(conn,fname,&sbuf);
1079 mtime = sbuf.st_mtime;
1081 if (fmode & aDIR) {
1082 DEBUG(3,("attempt to open a directory %s\n",fname));
1083 close_file(fsp,False);
1084 END_PROFILE(SMBopen);
1085 return ERROR_DOS(ERRDOS,ERRnoaccess);
1088 outsize = set_message(outbuf,7,0,True);
1089 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1090 SSVAL(outbuf,smb_vwv1,fmode);
1091 if(lp_dos_filetime_resolution(SNUM(conn)) )
1092 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1093 else
1094 put_dos_date3(outbuf,smb_vwv2,mtime);
1095 SIVAL(outbuf,smb_vwv4,(uint32)size);
1096 SSVAL(outbuf,smb_vwv6,rmode);
1098 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1099 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1101 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1102 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1103 END_PROFILE(SMBopen);
1104 return(outsize);
1107 /****************************************************************************
1108 Reply to an open and X.
1109 ****************************************************************************/
1111 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1113 pstring fname;
1114 int smb_mode = SVAL(inbuf,smb_vwv3);
1115 int smb_attr = SVAL(inbuf,smb_vwv5);
1116 /* Breakout the oplock request bits so we can set the
1117 reply bits separately. */
1118 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1119 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1120 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1121 #if 0
1122 int open_flags = SVAL(inbuf,smb_vwv2);
1123 int smb_sattr = SVAL(inbuf,smb_vwv4);
1124 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1125 #endif
1126 int smb_ofun = SVAL(inbuf,smb_vwv8);
1127 SMB_OFF_T size=0;
1128 int fmode=0,mtime=0,rmode=0;
1129 SMB_STRUCT_STAT sbuf;
1130 int smb_action = 0;
1131 BOOL bad_path = False;
1132 files_struct *fsp;
1133 NTSTATUS status;
1134 START_PROFILE(SMBopenX);
1136 /* If it's an IPC, pass off the pipe handler. */
1137 if (IS_IPC(conn)) {
1138 if (lp_nt_pipe_support()) {
1139 END_PROFILE(SMBopenX);
1140 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1141 } else {
1142 END_PROFILE(SMBopenX);
1143 return ERROR_DOS(ERRSRV,ERRaccess);
1147 /* XXXX we need to handle passed times, sattr and flags */
1148 srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status, False);
1149 if (!NT_STATUS_IS_OK(status)) {
1150 END_PROFILE(SMBopenX);
1151 return ERROR_NT(status);
1154 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1156 unix_convert(fname,conn,0,&bad_path,&sbuf);
1157 if (bad_path) {
1158 END_PROFILE(SMBopenX);
1159 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1162 fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,(uint32)smb_attr,
1163 oplock_request, &rmode,&smb_action);
1165 if (!fsp) {
1166 END_PROFILE(SMBopenX);
1167 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1168 /* We have re-scheduled this call. */
1169 clear_cached_errors();
1170 return -1;
1172 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1175 size = sbuf.st_size;
1176 fmode = dos_mode(conn,fname,&sbuf);
1177 mtime = sbuf.st_mtime;
1178 if (fmode & aDIR) {
1179 close_file(fsp,False);
1180 END_PROFILE(SMBopenX);
1181 return ERROR_DOS(ERRDOS,ERRnoaccess);
1184 /* If the caller set the extended oplock request bit
1185 and we granted one (by whatever means) - set the
1186 correct bit for extended oplock reply.
1189 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn)))
1190 smb_action |= EXTENDED_OPLOCK_GRANTED;
1192 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1193 smb_action |= EXTENDED_OPLOCK_GRANTED;
1195 /* If the caller set the core oplock request bit
1196 and we granted one (by whatever means) - set the
1197 correct bit for core oplock reply.
1200 if (core_oplock_request && lp_fake_oplocks(SNUM(conn)))
1201 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1203 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1204 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1206 set_message(outbuf,15,0,True);
1207 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1208 SSVAL(outbuf,smb_vwv3,fmode);
1209 if(lp_dos_filetime_resolution(SNUM(conn)) )
1210 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1211 else
1212 put_dos_date3(outbuf,smb_vwv4,mtime);
1213 SIVAL(outbuf,smb_vwv6,(uint32)size);
1214 SSVAL(outbuf,smb_vwv8,rmode);
1215 SSVAL(outbuf,smb_vwv11,smb_action);
1217 END_PROFILE(SMBopenX);
1218 return chain_reply(inbuf,outbuf,length,bufsize);
1221 /****************************************************************************
1222 Reply to a SMBulogoffX.
1223 ****************************************************************************/
1225 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1227 uint16 vuid = SVAL(inbuf,smb_uid);
1228 user_struct *vuser = get_valid_user_struct(vuid);
1229 START_PROFILE(SMBulogoffX);
1231 if(vuser == 0)
1232 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1234 /* in user level security we are supposed to close any files
1235 open by this user */
1236 if ((vuser != 0) && (lp_security() != SEC_SHARE))
1237 file_close_user(vuid);
1239 invalidate_vuid(vuid);
1241 set_message(outbuf,2,0,True);
1243 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1245 END_PROFILE(SMBulogoffX);
1246 return chain_reply(inbuf,outbuf,length,bufsize);
1249 /****************************************************************************
1250 Reply to a mknew or a create.
1251 ****************************************************************************/
1253 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1255 pstring fname;
1256 int com;
1257 int outsize = 0;
1258 int createmode;
1259 int ofun = 0;
1260 BOOL bad_path = False;
1261 files_struct *fsp;
1262 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1263 SMB_STRUCT_STAT sbuf;
1264 NTSTATUS status;
1265 START_PROFILE(SMBcreate);
1267 com = SVAL(inbuf,smb_com);
1269 createmode = SVAL(inbuf,smb_vwv0);
1270 srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status, False);
1271 if (!NT_STATUS_IS_OK(status)) {
1272 END_PROFILE(SMBcreate);
1273 return ERROR_NT(status);
1276 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1278 unix_convert(fname,conn,0,&bad_path,&sbuf);
1279 if (bad_path) {
1280 END_PROFILE(SMBcreate);
1281 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1284 if (createmode & aVOLID)
1285 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1287 if(com == SMBmknew) {
1288 /* We should fail if file exists. */
1289 ofun = FILE_CREATE_IF_NOT_EXIST;
1290 } else {
1291 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1292 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1295 /* Open file in dos compatibility share mode. */
1296 fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1297 ofun, (uint32)createmode, oplock_request, NULL, NULL);
1299 if (!fsp) {
1300 END_PROFILE(SMBcreate);
1301 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1302 /* We have re-scheduled this call. */
1303 clear_cached_errors();
1304 return -1;
1306 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1309 outsize = set_message(outbuf,1,0,True);
1310 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1312 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1313 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1315 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1316 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1318 DEBUG( 2, ( "new file %s\n", fname ) );
1319 DEBUG( 3, ( "mknew %s fd=%d dmode=%d\n", fname, fsp->fd, createmode ) );
1321 END_PROFILE(SMBcreate);
1322 return(outsize);
1325 /****************************************************************************
1326 Reply to a create temporary file.
1327 ****************************************************************************/
1329 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1331 pstring fname;
1332 int outsize = 0;
1333 int createattr;
1334 BOOL bad_path = False;
1335 files_struct *fsp;
1336 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1337 int tmpfd;
1338 SMB_STRUCT_STAT sbuf;
1339 char *p, *s;
1340 NTSTATUS status;
1341 unsigned int namelen;
1343 START_PROFILE(SMBctemp);
1345 createattr = SVAL(inbuf,smb_vwv0);
1346 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status, False);
1347 if (!NT_STATUS_IS_OK(status)) {
1348 END_PROFILE(SMBctemp);
1349 return ERROR_NT(status);
1351 if (*fname) {
1352 pstrcat(fname,"/TMXXXXXX");
1353 } else {
1354 pstrcat(fname,"TMXXXXXX");
1357 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1359 unix_convert(fname,conn,0,&bad_path,&sbuf);
1360 if (bad_path) {
1361 END_PROFILE(SMBctemp);
1362 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1365 tmpfd = smb_mkstemp(fname);
1366 if (tmpfd == -1) {
1367 END_PROFILE(SMBctemp);
1368 return(UNIXERROR(ERRDOS,ERRnoaccess));
1371 SMB_VFS_STAT(conn,fname,&sbuf);
1373 /* Open file in dos compatibility share mode. */
1374 /* We should fail if file does not exist. */
1375 fsp = open_file_shared(conn,fname,&sbuf,
1376 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1377 FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
1378 (uint32)createattr, oplock_request, NULL, NULL);
1380 /* close fd from smb_mkstemp() */
1381 close(tmpfd);
1383 if (!fsp) {
1384 END_PROFILE(SMBctemp);
1385 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1386 /* We have re-scheduled this call. */
1387 clear_cached_errors();
1388 return -1;
1390 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1393 outsize = set_message(outbuf,1,0,True);
1394 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1396 /* the returned filename is relative to the directory */
1397 s = strrchr_m(fname, '/');
1398 if (!s)
1399 s = fname;
1400 else
1401 s++;
1403 p = smb_buf(outbuf);
1404 #if 0
1405 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
1406 thing in the byte section. JRA */
1407 SSVALS(p, 0, -1); /* what is this? not in spec */
1408 #endif
1409 namelen = srvstr_push(outbuf, p, s, -1, STR_ASCII|STR_TERMINATE);
1410 p += namelen;
1411 outsize = set_message_end(outbuf, p);
1413 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1414 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1416 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1417 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1419 DEBUG( 2, ( "created temp file %s\n", fname ) );
1420 DEBUG( 3, ( "ctemp %s fd=%d umode=%o\n",
1421 fname, fsp->fd, sbuf.st_mode ) );
1423 END_PROFILE(SMBctemp);
1424 return(outsize);
1427 /*******************************************************************
1428 Check if a user is allowed to rename a file.
1429 ********************************************************************/
1431 static NTSTATUS can_rename(char *fname,connection_struct *conn, uint16 dirtype, SMB_STRUCT_STAT *pst)
1433 int smb_action;
1434 int access_mode;
1435 files_struct *fsp;
1436 uint16 fmode;
1438 if (!CAN_WRITE(conn))
1439 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1441 fmode = dos_mode(conn,fname,pst);
1442 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1443 return NT_STATUS_NO_SUCH_FILE;
1445 if (S_ISDIR(pst->st_mode))
1446 return NT_STATUS_OK;
1448 /* We need a better way to return NT status codes from open... */
1449 unix_ERR_class = 0;
1450 unix_ERR_code = 0;
1452 fsp = open_file_shared1(conn, fname, pst, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1453 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action);
1455 if (!fsp) {
1456 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1457 if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1458 ret = NT_STATUS_SHARING_VIOLATION;
1459 unix_ERR_class = 0;
1460 unix_ERR_code = 0;
1461 unix_ERR_ntstatus = NT_STATUS_OK;
1462 return ret;
1464 close_file(fsp,False);
1465 return NT_STATUS_OK;
1468 /*******************************************************************
1469 Check if a user is allowed to delete a file.
1470 ********************************************************************/
1472 static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype, BOOL bad_path)
1474 SMB_STRUCT_STAT sbuf;
1475 int fmode;
1476 int smb_action;
1477 int access_mode;
1478 files_struct *fsp;
1480 DEBUG(10,("can_delete: %s, dirtype = %d\n",
1481 fname, dirtype ));
1483 if (!CAN_WRITE(conn))
1484 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1486 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
1487 if(errno == ENOENT) {
1488 if (bad_path)
1489 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1490 else
1491 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1493 return map_nt_error_from_unix(errno);
1496 fmode = dos_mode(conn,fname,&sbuf);
1498 /* Can't delete a directory. */
1499 if (fmode & aDIR)
1500 return NT_STATUS_FILE_IS_A_DIRECTORY;
1501 #if 0 /* JRATEST */
1502 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
1503 return NT_STATUS_OBJECT_NAME_INVALID;
1504 #endif /* JRATEST */
1506 if (!lp_delete_readonly(SNUM(conn))) {
1507 if (fmode & aRONLY)
1508 return NT_STATUS_CANNOT_DELETE;
1510 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1511 return NT_STATUS_NO_SUCH_FILE;
1513 /* We need a better way to return NT status codes from open... */
1514 unix_ERR_class = 0;
1515 unix_ERR_code = 0;
1517 fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1518 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action);
1520 if (!fsp) {
1521 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1522 if (!NT_STATUS_IS_OK(unix_ERR_ntstatus))
1523 ret = unix_ERR_ntstatus;
1524 else if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1525 ret = NT_STATUS_SHARING_VIOLATION;
1526 unix_ERR_class = 0;
1527 unix_ERR_code = 0;
1528 unix_ERR_ntstatus = NT_STATUS_OK;
1529 return ret;
1531 close_file(fsp,False);
1532 return NT_STATUS_OK;
1535 /****************************************************************************
1536 The guts of the unlink command, split out so it may be called by the NT SMB
1537 code.
1538 ****************************************************************************/
1540 NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
1542 pstring directory;
1543 pstring mask;
1544 char *p;
1545 int count=0;
1546 NTSTATUS error = NT_STATUS_OK;
1547 BOOL has_wild;
1548 BOOL bad_path = False;
1549 BOOL rc = True;
1550 SMB_STRUCT_STAT sbuf;
1552 *directory = *mask = 0;
1554 /* We must check for wildcards in the name given
1555 * directly by the client - before any unmangling.
1556 * This prevents an unmangling of a UNIX name containing
1557 * a DOS wildcard like '*' or '?' from unmangling into
1558 * a wildcard delete which was not intended.
1559 * FIX for #226. JRA.
1562 has_wild = ms_has_wild(name);
1564 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1566 p = strrchr_m(name,'/');
1567 if (!p) {
1568 pstrcpy(directory,".");
1569 pstrcpy(mask,name);
1570 } else {
1571 *p = 0;
1572 pstrcpy(directory,name);
1573 pstrcpy(mask,p+1);
1577 * We should only check the mangled cache
1578 * here if unix_convert failed. This means
1579 * that the path in 'mask' doesn't exist
1580 * on the file system and so we need to look
1581 * for a possible mangle. This patch from
1582 * Tine Smukavec <valentin.smukavec@hermes.si>.
1585 if (!rc && mangle_is_mangled(mask))
1586 mangle_check_cache( mask, sizeof(pstring)-1 );
1588 if (!has_wild) {
1589 pstrcat(directory,"/");
1590 pstrcat(directory,mask);
1591 error = can_delete(directory,conn,dirtype,bad_path);
1592 if (!NT_STATUS_IS_OK(error))
1593 return error;
1595 if (SMB_VFS_UNLINK(conn,directory) == 0) {
1596 count++;
1598 } else {
1599 void *dirptr = NULL;
1600 const char *dname;
1602 if (check_name(directory,conn))
1603 dirptr = OpenDir(conn, directory, True);
1605 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1606 the pattern matches against the long name, otherwise the short name
1607 We don't implement this yet XXXX
1610 if (dirptr) {
1611 error = NT_STATUS_NO_SUCH_FILE;
1613 if (strequal(mask,"????????.???"))
1614 pstrcpy(mask,"*");
1616 while ((dname = ReadDirName(dirptr))) {
1617 pstring fname;
1618 BOOL sys_direntry = False;
1619 pstrcpy(fname,dname);
1621 /* Quick check for "." and ".." */
1622 if (fname[0] == '.') {
1623 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
1624 if ((dirtype & FILE_ATTRIBUTE_DIRECTORY) && (dirtype & FILE_ATTRIBUTE_SYSTEM)) {
1625 sys_direntry = True;
1626 } else {
1627 continue;
1632 if(!mask_match(fname, mask, conn->case_sensitive))
1633 continue;
1635 if (sys_direntry) {
1636 error = NT_STATUS_OBJECT_NAME_INVALID;
1637 DEBUG(3,("unlink_internals: system directory delete denied [%s] mask [%s]\n",
1638 fname, mask));
1639 break;
1642 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1643 error = can_delete(fname,conn,dirtype,bad_path);
1644 if (!NT_STATUS_IS_OK(error)) {
1645 continue;
1647 if (SMB_VFS_UNLINK(conn,fname) == 0)
1648 count++;
1649 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
1651 CloseDir(dirptr);
1655 if (count == 0 && NT_STATUS_IS_OK(error)) {
1656 error = map_nt_error_from_unix(errno);
1659 return error;
1662 /****************************************************************************
1663 Reply to a unlink
1664 ****************************************************************************/
1666 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
1667 int dum_buffsize)
1669 int outsize = 0;
1670 pstring name;
1671 int dirtype;
1672 NTSTATUS status;
1673 START_PROFILE(SMBunlink);
1675 dirtype = SVAL(inbuf,smb_vwv0);
1677 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, True);
1678 if (!NT_STATUS_IS_OK(status)) {
1679 END_PROFILE(SMBunlink);
1680 return ERROR_NT(status);
1683 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1685 DEBUG(3,("reply_unlink : %s\n",name));
1687 status = unlink_internals(conn, dirtype, name);
1688 if (!NT_STATUS_IS_OK(status)) {
1689 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1690 /* We have re-scheduled this call. */
1691 clear_cached_errors();
1692 return -1;
1694 return ERROR_NT(status);
1698 * Win2k needs a changenotify request response before it will
1699 * update after a rename..
1701 process_pending_change_notify_queue((time_t)0);
1703 outsize = set_message(outbuf,0,0,True);
1705 END_PROFILE(SMBunlink);
1706 return outsize;
1709 /****************************************************************************
1710 Fail for readbraw.
1711 ****************************************************************************/
1713 void fail_readraw(void)
1715 pstring errstr;
1716 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
1717 strerror(errno) );
1718 exit_server(errstr);
1721 /****************************************************************************
1722 Use sendfile in readbraw.
1723 ****************************************************************************/
1725 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
1726 ssize_t mincount, char *outbuf)
1728 ssize_t ret=0;
1730 #if defined(WITH_SENDFILE)
1732 * We can only use sendfile on a non-chained packet
1733 * but we can use on a non-oplocked file. tridge proved this
1734 * on a train in Germany :-). JRA.
1735 * reply_readbraw has already checked the length.
1738 if (chain_size ==0 && (nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) && lp_use_sendfile(SNUM(conn)) ) {
1739 DATA_BLOB header;
1741 _smb_setlen(outbuf,nread);
1742 header.data = outbuf;
1743 header.length = 4;
1744 header.free = NULL;
1746 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) {
1748 * Special hack for broken Linux with no 64 bit clean sendfile. If we
1749 * return ENOSYS then pretend we just got a normal read.
1751 if (errno == ENOSYS) {
1752 set_use_sendfile(SNUM(conn), False);
1753 goto normal_read;
1756 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
1757 fsp->fsp_name, strerror(errno) ));
1758 exit_server("send_file_readbraw sendfile failed");
1763 normal_read:
1764 #endif
1766 if (nread > 0) {
1767 ret = read_file(fsp,outbuf+4,startpos,nread);
1768 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1769 if (ret < mincount)
1770 ret = 0;
1771 #else
1772 if (ret < nread)
1773 ret = 0;
1774 #endif
1777 _smb_setlen(outbuf,ret);
1778 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
1779 fail_readraw();
1782 /****************************************************************************
1783 Reply to a readbraw (core+ protocol).
1784 ****************************************************************************/
1786 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
1788 extern struct current_user current_user;
1789 ssize_t maxcount,mincount;
1790 size_t nread = 0;
1791 SMB_OFF_T startpos;
1792 char *header = outbuf;
1793 files_struct *fsp;
1794 START_PROFILE(SMBreadbraw);
1796 if (srv_is_signing_active()) {
1797 exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
1801 * Special check if an oplock break has been issued
1802 * and the readraw request croses on the wire, we must
1803 * return a zero length response here.
1806 if(global_oplock_break) {
1807 _smb_setlen(header,0);
1808 if (write_data(smbd_server_fd(),header,4) != 4)
1809 fail_readraw();
1810 DEBUG(5,("readbraw - oplock break finished\n"));
1811 END_PROFILE(SMBreadbraw);
1812 return -1;
1815 fsp = file_fsp(inbuf,smb_vwv0);
1817 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1819 * fsp could be NULL here so use the value from the packet. JRA.
1821 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
1822 _smb_setlen(header,0);
1823 if (write_data(smbd_server_fd(),header,4) != 4)
1824 fail_readraw();
1825 END_PROFILE(SMBreadbraw);
1826 return(-1);
1829 CHECK_FSP(fsp,conn);
1831 flush_write_cache(fsp, READRAW_FLUSH);
1833 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
1834 if(CVAL(inbuf,smb_wct) == 10) {
1836 * This is a large offset (64 bit) read.
1838 #ifdef LARGE_SMB_OFF_T
1840 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
1842 #else /* !LARGE_SMB_OFF_T */
1845 * Ensure we haven't been sent a >32 bit offset.
1848 if(IVAL(inbuf,smb_vwv8) != 0) {
1849 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
1850 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
1851 _smb_setlen(header,0);
1852 if (write_data(smbd_server_fd(),header,4) != 4)
1853 fail_readraw();
1854 END_PROFILE(SMBreadbraw);
1855 return(-1);
1858 #endif /* LARGE_SMB_OFF_T */
1860 if(startpos < 0) {
1861 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
1862 _smb_setlen(header,0);
1863 if (write_data(smbd_server_fd(),header,4) != 4)
1864 fail_readraw();
1865 END_PROFILE(SMBreadbraw);
1866 return(-1);
1869 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
1870 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
1872 /* ensure we don't overrun the packet size */
1873 maxcount = MIN(65535,maxcount);
1875 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1876 SMB_OFF_T size = fsp->size;
1877 SMB_OFF_T sizeneeded = startpos + maxcount;
1879 if (size < sizeneeded) {
1880 SMB_STRUCT_STAT st;
1881 if (SMB_VFS_FSTAT(fsp,fsp->fd,&st) == 0)
1882 size = st.st_size;
1883 if (!fsp->can_write)
1884 fsp->size = size;
1887 if (startpos >= size)
1888 nread = 0;
1889 else
1890 nread = MIN(maxcount,(size - startpos));
1893 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1894 if (nread < mincount)
1895 nread = 0;
1896 #endif
1898 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
1899 (int)maxcount, (int)mincount, (int)nread ) );
1901 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf);
1903 DEBUG(5,("readbraw finished\n"));
1904 END_PROFILE(SMBreadbraw);
1905 return -1;
1908 /****************************************************************************
1909 Reply to a lockread (core+ protocol).
1910 ****************************************************************************/
1912 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
1914 ssize_t nread = -1;
1915 char *data;
1916 int outsize = 0;
1917 SMB_OFF_T startpos;
1918 size_t numtoread;
1919 NTSTATUS status;
1920 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1921 BOOL my_lock_ctx = False;
1922 START_PROFILE(SMBlockread);
1924 CHECK_FSP(fsp,conn);
1925 CHECK_READ(fsp);
1927 release_level_2_oplocks_on_change(fsp);
1929 numtoread = SVAL(inbuf,smb_vwv1);
1930 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
1932 outsize = set_message(outbuf,5,3,True);
1933 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1934 data = smb_buf(outbuf) + 3;
1937 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
1938 * protocol request that predates the read/write lock concept.
1939 * Thus instead of asking for a read lock here we need to ask
1940 * for a write lock. JRA.
1941 * Note that the requested lock size is unaffected by max_recv.
1944 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid),
1945 (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, &my_lock_ctx);
1947 if (NT_STATUS_V(status)) {
1948 #if 0
1950 * We used to make lockread a blocking lock. It turns out
1951 * that this isn't on W2k. Found by the Samba 4 RAW-READ torture
1952 * tester. JRA.
1955 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
1957 * A blocking lock was requested. Package up
1958 * this smb into a queued request and push it
1959 * onto the blocking lock queue.
1961 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)startpos,
1962 (SMB_BIG_UINT)numtoread)) {
1963 END_PROFILE(SMBlockread);
1964 return -1;
1967 #endif
1968 END_PROFILE(SMBlockread);
1969 return ERROR_NT(status);
1973 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
1976 if (numtoread > max_recv) {
1977 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
1978 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
1979 (unsigned int)numtoread, (unsigned int)max_recv ));
1980 numtoread = MIN(numtoread,max_recv);
1982 nread = read_file(fsp,data,startpos,numtoread);
1984 if (nread < 0) {
1985 END_PROFILE(SMBlockread);
1986 return(UNIXERROR(ERRDOS,ERRnoaccess));
1989 outsize += nread;
1990 SSVAL(outbuf,smb_vwv0,nread);
1991 SSVAL(outbuf,smb_vwv5,nread+3);
1992 SSVAL(smb_buf(outbuf),1,nread);
1994 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
1995 fsp->fnum, (int)numtoread, (int)nread));
1997 END_PROFILE(SMBlockread);
1998 return(outsize);
2001 /****************************************************************************
2002 Reply to a read.
2003 ****************************************************************************/
2005 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2007 size_t numtoread;
2008 ssize_t nread = 0;
2009 char *data;
2010 SMB_OFF_T startpos;
2011 int outsize = 0;
2012 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2013 START_PROFILE(SMBread);
2015 CHECK_FSP(fsp,conn);
2016 CHECK_READ(fsp);
2018 numtoread = SVAL(inbuf,smb_vwv1);
2019 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2021 outsize = set_message(outbuf,5,3,True);
2022 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2024 * The requested read size cannot be greater than max_recv. JRA.
2026 if (numtoread > max_recv) {
2027 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
2028 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2029 (unsigned int)numtoread, (unsigned int)max_recv ));
2030 numtoread = MIN(numtoread,max_recv);
2033 data = smb_buf(outbuf) + 3;
2035 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
2036 END_PROFILE(SMBread);
2037 return ERROR_DOS(ERRDOS,ERRlock);
2040 if (numtoread > 0)
2041 nread = read_file(fsp,data,startpos,numtoread);
2043 if (nread < 0) {
2044 END_PROFILE(SMBread);
2045 return(UNIXERROR(ERRDOS,ERRnoaccess));
2048 outsize += nread;
2049 SSVAL(outbuf,smb_vwv0,nread);
2050 SSVAL(outbuf,smb_vwv5,nread+3);
2051 SCVAL(smb_buf(outbuf),0,1);
2052 SSVAL(smb_buf(outbuf),1,nread);
2054 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2055 fsp->fnum, (int)numtoread, (int)nread ) );
2057 END_PROFILE(SMBread);
2058 return(outsize);
2061 /****************************************************************************
2062 Reply to a read and X - possibly using sendfile.
2063 ****************************************************************************/
2065 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length,
2066 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
2068 ssize_t nread = -1;
2069 char *data = smb_buf(outbuf);
2071 #if defined(WITH_SENDFILE)
2073 * We can only use sendfile on a non-chained packet
2074 * but we can use on a non-oplocked file. tridge proved this
2075 * on a train in Germany :-). JRA.
2078 if (chain_size ==0 && (CVAL(inbuf,smb_vwv0) == 0xFF) && lp_use_sendfile(SNUM(conn)) &&
2079 (lp_write_cache_size(SNUM(conn)) == 0) ) {
2080 SMB_STRUCT_STAT sbuf;
2081 DATA_BLOB header;
2083 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1)
2084 return(UNIXERROR(ERRDOS,ERRnoaccess));
2086 if (startpos > sbuf.st_size)
2087 goto normal_read;
2089 if (smb_maxcnt > (sbuf.st_size - startpos))
2090 smb_maxcnt = (sbuf.st_size - startpos);
2092 if (smb_maxcnt == 0)
2093 goto normal_read;
2096 * Set up the packet header before send. We
2097 * assume here the sendfile will work (get the
2098 * correct amount of data).
2101 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2102 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
2103 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2104 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
2105 SCVAL(outbuf,smb_vwv0,0xFF);
2106 set_message(outbuf,12,smb_maxcnt,False);
2107 header.data = outbuf;
2108 header.length = data - outbuf;
2109 header.free = NULL;
2111 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt) == -1) {
2113 * Special hack for broken Linux with no 64 bit clean sendfile. If we
2114 * return ENOSYS then pretend we just got a normal read.
2116 if (errno == ENOSYS) {
2117 set_use_sendfile(SNUM(conn), False);
2118 goto normal_read;
2121 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2122 fsp->fsp_name, strerror(errno) ));
2123 exit_server("send_file_readX sendfile failed");
2126 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2127 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2128 return -1;
2131 normal_read:
2133 #endif
2135 nread = read_file(fsp,data,startpos,smb_maxcnt);
2137 if (nread < 0) {
2138 END_PROFILE(SMBreadX);
2139 return(UNIXERROR(ERRDOS,ERRnoaccess));
2142 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2143 SSVAL(outbuf,smb_vwv5,nread);
2144 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2145 SSVAL(smb_buf(outbuf),-2,nread);
2147 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2148 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2150 return nread;
2153 /****************************************************************************
2154 Reply to a read and X.
2155 ****************************************************************************/
2157 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2159 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2160 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2161 ssize_t nread = -1;
2162 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2163 #if 0
2164 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2165 #endif
2167 START_PROFILE(SMBreadX);
2169 /* If it's an IPC, pass off the pipe handler. */
2170 if (IS_IPC(conn)) {
2171 END_PROFILE(SMBreadX);
2172 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2175 CHECK_FSP(fsp,conn);
2176 CHECK_READ(fsp);
2178 set_message(outbuf,12,0,True);
2180 if(CVAL(inbuf,smb_wct) == 12) {
2181 #ifdef LARGE_SMB_OFF_T
2183 * This is a large offset (64 bit) read.
2185 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2187 #else /* !LARGE_SMB_OFF_T */
2190 * Ensure we haven't been sent a >32 bit offset.
2193 if(IVAL(inbuf,smb_vwv10) != 0) {
2194 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2195 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2196 END_PROFILE(SMBreadX);
2197 return ERROR_DOS(ERRDOS,ERRbadaccess);
2200 #endif /* LARGE_SMB_OFF_T */
2204 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
2205 END_PROFILE(SMBreadX);
2206 return ERROR_DOS(ERRDOS,ERRlock);
2209 nread = send_file_readX(conn, inbuf, outbuf, length, fsp, startpos, smb_maxcnt);
2210 if (nread != -1)
2211 nread = chain_reply(inbuf,outbuf,length,bufsize);
2213 END_PROFILE(SMBreadX);
2214 return nread;
2217 /****************************************************************************
2218 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2219 ****************************************************************************/
2221 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2223 ssize_t nwritten=0;
2224 ssize_t total_written=0;
2225 size_t numtowrite=0;
2226 size_t tcount;
2227 SMB_OFF_T startpos;
2228 char *data=NULL;
2229 BOOL write_through;
2230 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2231 int outsize = 0;
2232 START_PROFILE(SMBwritebraw);
2234 if (srv_is_signing_active()) {
2235 exit_server("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2238 CHECK_FSP(fsp,conn);
2239 CHECK_WRITE(fsp);
2241 tcount = IVAL(inbuf,smb_vwv1);
2242 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2243 write_through = BITSETW(inbuf+smb_vwv7,0);
2245 /* We have to deal with slightly different formats depending
2246 on whether we are using the core+ or lanman1.0 protocol */
2248 if(Protocol <= PROTOCOL_COREPLUS) {
2249 numtowrite = SVAL(smb_buf(inbuf),-2);
2250 data = smb_buf(inbuf);
2251 } else {
2252 numtowrite = SVAL(inbuf,smb_vwv10);
2253 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2256 /* force the error type */
2257 SCVAL(inbuf,smb_com,SMBwritec);
2258 SCVAL(outbuf,smb_com,SMBwritec);
2260 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2261 END_PROFILE(SMBwritebraw);
2262 return(ERROR_DOS(ERRDOS,ERRlock));
2265 if (numtowrite>0)
2266 nwritten = write_file(fsp,data,startpos,numtowrite);
2268 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2269 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2271 if (nwritten < (ssize_t)numtowrite) {
2272 END_PROFILE(SMBwritebraw);
2273 return(UNIXERROR(ERRHRD,ERRdiskfull));
2276 total_written = nwritten;
2278 /* Return a message to the redirector to tell it to send more bytes */
2279 SCVAL(outbuf,smb_com,SMBwritebraw);
2280 SSVALS(outbuf,smb_vwv0,-1);
2281 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2282 if (!send_smb(smbd_server_fd(),outbuf))
2283 exit_server("reply_writebraw: send_smb failed.");
2285 /* Now read the raw data into the buffer and write it */
2286 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2287 exit_server("secondary writebraw failed");
2290 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2291 numtowrite = smb_len(inbuf);
2293 /* Set up outbuf to return the correct return */
2294 outsize = set_message(outbuf,1,0,True);
2295 SCVAL(outbuf,smb_com,SMBwritec);
2296 SSVAL(outbuf,smb_vwv0,total_written);
2298 if (numtowrite != 0) {
2300 if (numtowrite > BUFFER_SIZE) {
2301 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2302 (unsigned int)numtowrite ));
2303 exit_server("secondary writebraw failed");
2306 if (tcount > nwritten+numtowrite) {
2307 DEBUG(3,("Client overestimated the write %d %d %d\n",
2308 (int)tcount,(int)nwritten,(int)numtowrite));
2311 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2312 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2313 strerror(errno) ));
2314 exit_server("secondary writebraw failed");
2317 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2319 if (nwritten < (ssize_t)numtowrite) {
2320 SCVAL(outbuf,smb_rcls,ERRHRD);
2321 SSVAL(outbuf,smb_err,ERRdiskfull);
2324 if (nwritten > 0)
2325 total_written += nwritten;
2328 if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn)))
2329 sync_file(conn,fsp);
2331 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2332 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2334 /* we won't return a status if write through is not selected - this follows what WfWg does */
2335 END_PROFILE(SMBwritebraw);
2336 if (!write_through && total_written==tcount) {
2338 #if RABBIT_PELLET_FIX
2340 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2341 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2343 if (!send_keepalive(smbd_server_fd()))
2344 exit_server("reply_writebraw: send of keepalive failed");
2345 #endif
2346 return(-1);
2349 return(outsize);
2352 /****************************************************************************
2353 Reply to a writeunlock (core+).
2354 ****************************************************************************/
2356 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
2357 int size, int dum_buffsize)
2359 ssize_t nwritten = -1;
2360 size_t numtowrite;
2361 SMB_OFF_T startpos;
2362 char *data;
2363 NTSTATUS status = NT_STATUS_OK;
2364 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2365 int outsize = 0;
2366 START_PROFILE(SMBwriteunlock);
2368 CHECK_FSP(fsp,conn);
2369 CHECK_WRITE(fsp);
2371 numtowrite = SVAL(inbuf,smb_vwv1);
2372 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2373 data = smb_buf(inbuf) + 3;
2375 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos,
2376 WRITE_LOCK,False)) {
2377 END_PROFILE(SMBwriteunlock);
2378 return ERROR_DOS(ERRDOS,ERRlock);
2381 /* The special X/Open SMB protocol handling of
2382 zero length writes is *NOT* done for
2383 this call */
2384 if(numtowrite == 0)
2385 nwritten = 0;
2386 else
2387 nwritten = write_file(fsp,data,startpos,numtowrite);
2389 if (lp_syncalways(SNUM(conn)))
2390 sync_file(conn,fsp);
2392 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2393 END_PROFILE(SMBwriteunlock);
2394 return(UNIXERROR(ERRHRD,ERRdiskfull));
2397 if (numtowrite) {
2398 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite,
2399 (SMB_BIG_UINT)startpos);
2400 if (NT_STATUS_V(status)) {
2401 END_PROFILE(SMBwriteunlock);
2402 return ERROR_NT(status);
2406 outsize = set_message(outbuf,1,0,True);
2408 SSVAL(outbuf,smb_vwv0,nwritten);
2410 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2411 fsp->fnum, (int)numtowrite, (int)nwritten));
2413 END_PROFILE(SMBwriteunlock);
2414 return outsize;
2417 /****************************************************************************
2418 Reply to a write.
2419 ****************************************************************************/
2421 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2423 size_t numtowrite;
2424 ssize_t nwritten = -1;
2425 SMB_OFF_T startpos;
2426 char *data;
2427 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2428 int outsize = 0;
2429 START_PROFILE(SMBwrite);
2431 /* If it's an IPC, pass off the pipe handler. */
2432 if (IS_IPC(conn)) {
2433 END_PROFILE(SMBwrite);
2434 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2437 CHECK_FSP(fsp,conn);
2438 CHECK_WRITE(fsp);
2440 numtowrite = SVAL(inbuf,smb_vwv1);
2441 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2442 data = smb_buf(inbuf) + 3;
2444 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2445 END_PROFILE(SMBwrite);
2446 return ERROR_DOS(ERRDOS,ERRlock);
2450 * X/Open SMB protocol says that if smb_vwv1 is
2451 * zero then the file size should be extended or
2452 * truncated to the size given in smb_vwv[2-3].
2455 if(numtowrite == 0) {
2457 * This is actually an allocate call, and set EOF. JRA.
2459 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2460 if (nwritten < 0) {
2461 END_PROFILE(SMBwrite);
2462 return ERROR_NT(NT_STATUS_DISK_FULL);
2464 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2465 if (nwritten < 0) {
2466 END_PROFILE(SMBwrite);
2467 return ERROR_NT(NT_STATUS_DISK_FULL);
2469 } else
2470 nwritten = write_file(fsp,data,startpos,numtowrite);
2472 if (lp_syncalways(SNUM(conn)))
2473 sync_file(conn,fsp);
2475 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2476 END_PROFILE(SMBwrite);
2477 return(UNIXERROR(ERRHRD,ERRdiskfull));
2480 outsize = set_message(outbuf,1,0,True);
2482 SSVAL(outbuf,smb_vwv0,nwritten);
2484 if (nwritten < (ssize_t)numtowrite) {
2485 SCVAL(outbuf,smb_rcls,ERRHRD);
2486 SSVAL(outbuf,smb_err,ERRdiskfull);
2489 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2491 END_PROFILE(SMBwrite);
2492 return(outsize);
2495 /****************************************************************************
2496 Reply to a write and X.
2497 ****************************************************************************/
2499 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2501 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2502 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2503 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2504 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2505 ssize_t nwritten = -1;
2506 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2507 unsigned int smblen = smb_len(inbuf);
2508 char *data;
2509 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2510 START_PROFILE(SMBwriteX);
2512 /* If it's an IPC, pass off the pipe handler. */
2513 if (IS_IPC(conn)) {
2514 END_PROFILE(SMBwriteX);
2515 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2518 CHECK_FSP(fsp,conn);
2519 CHECK_WRITE(fsp);
2521 /* Deal with possible LARGE_WRITEX */
2522 if (large_writeX)
2523 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2525 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2526 END_PROFILE(SMBwriteX);
2527 return ERROR_DOS(ERRDOS,ERRbadmem);
2530 data = smb_base(inbuf) + smb_doff;
2532 if(CVAL(inbuf,smb_wct) == 14) {
2533 #ifdef LARGE_SMB_OFF_T
2535 * This is a large offset (64 bit) write.
2537 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2539 #else /* !LARGE_SMB_OFF_T */
2542 * Ensure we haven't been sent a >32 bit offset.
2545 if(IVAL(inbuf,smb_vwv12) != 0) {
2546 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2547 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2548 END_PROFILE(SMBwriteX);
2549 return ERROR_DOS(ERRDOS,ERRbadaccess);
2552 #endif /* LARGE_SMB_OFF_T */
2555 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2556 END_PROFILE(SMBwriteX);
2557 return ERROR_DOS(ERRDOS,ERRlock);
2560 /* X/Open SMB protocol says that, unlike SMBwrite
2561 if the length is zero then NO truncation is
2562 done, just a write of zero. To truncate a file,
2563 use SMBwrite. */
2565 if(numtowrite == 0)
2566 nwritten = 0;
2567 else
2568 nwritten = write_file(fsp,data,startpos,numtowrite);
2570 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2571 END_PROFILE(SMBwriteX);
2572 return(UNIXERROR(ERRHRD,ERRdiskfull));
2575 set_message(outbuf,6,0,True);
2577 SSVAL(outbuf,smb_vwv2,nwritten);
2578 if (large_writeX)
2579 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2581 if (nwritten < (ssize_t)numtowrite) {
2582 SCVAL(outbuf,smb_rcls,ERRHRD);
2583 SSVAL(outbuf,smb_err,ERRdiskfull);
2586 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2587 fsp->fnum, (int)numtowrite, (int)nwritten));
2589 if (lp_syncalways(SNUM(conn)) || write_through)
2590 sync_file(conn,fsp);
2592 END_PROFILE(SMBwriteX);
2593 return chain_reply(inbuf,outbuf,length,bufsize);
2596 /****************************************************************************
2597 Reply to a lseek.
2598 ****************************************************************************/
2600 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2602 SMB_OFF_T startpos;
2603 SMB_OFF_T res= -1;
2604 int mode,umode;
2605 int outsize = 0;
2606 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2607 START_PROFILE(SMBlseek);
2609 CHECK_FSP(fsp,conn);
2611 flush_write_cache(fsp, SEEK_FLUSH);
2613 mode = SVAL(inbuf,smb_vwv1) & 3;
2614 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
2615 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
2617 switch (mode) {
2618 case 0:
2619 umode = SEEK_SET;
2620 res = startpos;
2621 break;
2622 case 1:
2623 umode = SEEK_CUR;
2624 res = fsp->pos + startpos;
2625 break;
2626 case 2:
2627 umode = SEEK_END;
2628 break;
2629 default:
2630 umode = SEEK_SET;
2631 res = startpos;
2632 break;
2635 if (umode == SEEK_END) {
2636 if((res = SMB_VFS_LSEEK(fsp,fsp->fd,startpos,umode)) == -1) {
2637 if(errno == EINVAL) {
2638 SMB_OFF_T current_pos = startpos;
2639 SMB_STRUCT_STAT sbuf;
2641 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) {
2642 END_PROFILE(SMBlseek);
2643 return(UNIXERROR(ERRDOS,ERRnoaccess));
2646 current_pos += sbuf.st_size;
2647 if(current_pos < 0)
2648 res = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_SET);
2652 if(res == -1) {
2653 END_PROFILE(SMBlseek);
2654 return(UNIXERROR(ERRDOS,ERRnoaccess));
2658 fsp->pos = res;
2660 outsize = set_message(outbuf,2,0,True);
2661 SIVAL(outbuf,smb_vwv0,res);
2663 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2664 fsp->fnum, (double)startpos, (double)res, mode));
2666 END_PROFILE(SMBlseek);
2667 return(outsize);
2670 /****************************************************************************
2671 Reply to a flush.
2672 ****************************************************************************/
2674 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2676 int outsize = set_message(outbuf,0,0,True);
2677 uint16 fnum = SVAL(inbuf,smb_vwv0);
2678 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2679 START_PROFILE(SMBflush);
2681 if (fnum != 0xFFFF)
2682 CHECK_FSP(fsp,conn);
2684 if (!fsp) {
2685 file_sync_all(conn);
2686 } else {
2687 sync_file(conn,fsp);
2690 DEBUG(3,("flush\n"));
2691 END_PROFILE(SMBflush);
2692 return(outsize);
2695 /****************************************************************************
2696 Reply to a exit.
2697 ****************************************************************************/
2699 int reply_exit(connection_struct *conn,
2700 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2702 int outsize;
2703 START_PROFILE(SMBexit);
2705 file_close_pid(SVAL(inbuf,smb_pid));
2707 outsize = set_message(outbuf,0,0,True);
2709 DEBUG(3,("exit\n"));
2711 END_PROFILE(SMBexit);
2712 return(outsize);
2715 /****************************************************************************
2716 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2717 ****************************************************************************/
2719 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2720 int dum_buffsize)
2722 extern struct current_user current_user;
2723 int outsize = 0;
2724 time_t mtime;
2725 int32 eclass = 0, err = 0;
2726 files_struct *fsp = NULL;
2727 START_PROFILE(SMBclose);
2729 outsize = set_message(outbuf,0,0,True);
2731 /* If it's an IPC, pass off to the pipe handler. */
2732 if (IS_IPC(conn)) {
2733 END_PROFILE(SMBclose);
2734 return reply_pipe_close(conn, inbuf,outbuf);
2737 fsp = file_fsp(inbuf,smb_vwv0);
2740 * We can only use CHECK_FSP if we know it's not a directory.
2743 if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
2744 END_PROFILE(SMBclose);
2745 return ERROR_DOS(ERRDOS,ERRbadfid);
2748 if(fsp->is_directory) {
2750 * Special case - close NT SMB directory handle.
2752 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2753 close_file(fsp,True);
2754 } else {
2756 * Close ordinary file.
2758 int close_err;
2759 pstring file_name;
2761 /* Save the name for time set in close. */
2762 pstrcpy( file_name, fsp->fsp_name);
2764 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2765 fsp->fd, fsp->fnum,
2766 conn->num_files_open));
2769 * close_file() returns the unix errno if an error
2770 * was detected on close - normally this is due to
2771 * a disk full error. If not then it was probably an I/O error.
2774 if((close_err = close_file(fsp,True)) != 0) {
2775 errno = close_err;
2776 END_PROFILE(SMBclose);
2777 return (UNIXERROR(ERRHRD,ERRgeneral));
2781 * Now take care of any time sent in the close.
2784 mtime = make_unix_date3(inbuf+smb_vwv1);
2786 /* try and set the date */
2787 set_filetime(conn, file_name, mtime);
2791 /* We have a cached error */
2792 if(eclass || err) {
2793 END_PROFILE(SMBclose);
2794 return ERROR_DOS(eclass,err);
2797 END_PROFILE(SMBclose);
2798 return(outsize);
2801 /****************************************************************************
2802 Reply to a writeclose (Core+ protocol).
2803 ****************************************************************************/
2805 int reply_writeclose(connection_struct *conn,
2806 char *inbuf,char *outbuf, int size, int dum_buffsize)
2808 size_t numtowrite;
2809 ssize_t nwritten = -1;
2810 int outsize = 0;
2811 int close_err = 0;
2812 SMB_OFF_T startpos;
2813 char *data;
2814 time_t mtime;
2815 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2816 START_PROFILE(SMBwriteclose);
2818 CHECK_FSP(fsp,conn);
2819 CHECK_WRITE(fsp);
2821 numtowrite = SVAL(inbuf,smb_vwv1);
2822 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2823 mtime = make_unix_date3(inbuf+smb_vwv4);
2824 data = smb_buf(inbuf) + 1;
2826 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2827 END_PROFILE(SMBwriteclose);
2828 return ERROR_DOS(ERRDOS,ERRlock);
2831 nwritten = write_file(fsp,data,startpos,numtowrite);
2833 set_filetime(conn, fsp->fsp_name,mtime);
2836 * More insanity. W2K only closes the file if writelen > 0.
2837 * JRA.
2840 if (numtowrite) {
2841 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
2842 fsp->fsp_name ));
2843 close_err = close_file(fsp,True);
2846 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2847 fsp->fnum, (int)numtowrite, (int)nwritten,
2848 conn->num_files_open));
2850 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2851 END_PROFILE(SMBwriteclose);
2852 return(UNIXERROR(ERRHRD,ERRdiskfull));
2855 if(close_err != 0) {
2856 errno = close_err;
2857 END_PROFILE(SMBwriteclose);
2858 return(UNIXERROR(ERRHRD,ERRgeneral));
2861 outsize = set_message(outbuf,1,0,True);
2863 SSVAL(outbuf,smb_vwv0,nwritten);
2864 END_PROFILE(SMBwriteclose);
2865 return(outsize);
2868 /****************************************************************************
2869 Reply to a lock.
2870 ****************************************************************************/
2872 int reply_lock(connection_struct *conn,
2873 char *inbuf,char *outbuf, int length, int dum_buffsize)
2875 int outsize = set_message(outbuf,0,0,True);
2876 SMB_BIG_UINT count,offset;
2877 NTSTATUS status;
2878 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2879 BOOL my_lock_ctx = False;
2881 START_PROFILE(SMBlock);
2883 CHECK_FSP(fsp,conn);
2885 release_level_2_oplocks_on_change(fsp);
2887 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2888 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2890 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2891 fsp->fd, fsp->fnum, (double)offset, (double)count));
2893 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &my_lock_ctx);
2894 if (NT_STATUS_V(status)) {
2895 #if 0
2896 /* Tests using Samba4 against W2K show this call never creates a blocking lock. */
2897 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
2899 * A blocking lock was requested. Package up
2900 * this smb into a queued request and push it
2901 * onto the blocking lock queue.
2903 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), offset, count)) {
2904 END_PROFILE(SMBlock);
2905 return -1;
2908 #endif
2909 END_PROFILE(SMBlock);
2910 return ERROR_NT(status);
2913 END_PROFILE(SMBlock);
2914 return(outsize);
2917 /****************************************************************************
2918 Reply to a unlock.
2919 ****************************************************************************/
2921 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
2922 int dum_buffsize)
2924 int outsize = set_message(outbuf,0,0,True);
2925 SMB_BIG_UINT count,offset;
2926 NTSTATUS status;
2927 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2928 START_PROFILE(SMBunlock);
2930 CHECK_FSP(fsp,conn);
2932 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2933 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2935 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
2936 if (NT_STATUS_V(status)) {
2937 END_PROFILE(SMBunlock);
2938 return ERROR_NT(status);
2941 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2942 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
2944 END_PROFILE(SMBunlock);
2945 return(outsize);
2948 /****************************************************************************
2949 Reply to a tdis.
2950 ****************************************************************************/
2952 int reply_tdis(connection_struct *conn,
2953 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2955 int outsize = set_message(outbuf,0,0,True);
2956 uint16 vuid;
2957 START_PROFILE(SMBtdis);
2959 vuid = SVAL(inbuf,smb_uid);
2961 if (!conn) {
2962 DEBUG(4,("Invalid connection in tdis\n"));
2963 END_PROFILE(SMBtdis);
2964 return ERROR_DOS(ERRSRV,ERRinvnid);
2967 conn->used = False;
2969 close_cnum(conn,vuid);
2971 END_PROFILE(SMBtdis);
2972 return outsize;
2975 /****************************************************************************
2976 Reply to a echo.
2977 ****************************************************************************/
2979 int reply_echo(connection_struct *conn,
2980 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2982 int smb_reverb = SVAL(inbuf,smb_vwv0);
2983 int seq_num;
2984 unsigned int data_len = smb_buflen(inbuf);
2985 int outsize = set_message(outbuf,1,data_len,True);
2986 START_PROFILE(SMBecho);
2988 if (data_len > BUFFER_SIZE) {
2989 DEBUG(0,("reply_echo: data_len too large.\n"));
2990 END_PROFILE(SMBecho);
2991 return -1;
2994 /* copy any incoming data back out */
2995 if (data_len > 0)
2996 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2998 if (smb_reverb > 100) {
2999 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3000 smb_reverb = 100;
3003 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3004 SSVAL(outbuf,smb_vwv0,seq_num);
3006 smb_setlen(outbuf,outsize - 4);
3008 if (!send_smb(smbd_server_fd(),outbuf))
3009 exit_server("reply_echo: send_smb failed.");
3012 DEBUG(3,("echo %d times\n", smb_reverb));
3014 smb_echo_count++;
3016 END_PROFILE(SMBecho);
3017 return -1;
3020 /****************************************************************************
3021 Reply to a printopen.
3022 ****************************************************************************/
3024 int reply_printopen(connection_struct *conn,
3025 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3027 int outsize = 0;
3028 files_struct *fsp;
3029 START_PROFILE(SMBsplopen);
3031 if (!CAN_PRINT(conn)) {
3032 END_PROFILE(SMBsplopen);
3033 return ERROR_DOS(ERRDOS,ERRnoaccess);
3036 /* Open for exclusive use, write only. */
3037 fsp = print_fsp_open(conn, NULL);
3039 if (!fsp) {
3040 END_PROFILE(SMBsplopen);
3041 return(UNIXERROR(ERRDOS,ERRnoaccess));
3044 outsize = set_message(outbuf,1,0,True);
3045 SSVAL(outbuf,smb_vwv0,fsp->fnum);
3047 DEBUG(3,("openprint fd=%d fnum=%d\n",
3048 fsp->fd, fsp->fnum));
3050 END_PROFILE(SMBsplopen);
3051 return(outsize);
3054 /****************************************************************************
3055 Reply to a printclose.
3056 ****************************************************************************/
3058 int reply_printclose(connection_struct *conn,
3059 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3061 int outsize = set_message(outbuf,0,0,True);
3062 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3063 int close_err = 0;
3064 START_PROFILE(SMBsplclose);
3066 CHECK_FSP(fsp,conn);
3068 if (!CAN_PRINT(conn)) {
3069 END_PROFILE(SMBsplclose);
3070 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
3073 DEBUG(3,("printclose fd=%d fnum=%d\n",
3074 fsp->fd,fsp->fnum));
3076 close_err = close_file(fsp,True);
3078 if(close_err != 0) {
3079 errno = close_err;
3080 END_PROFILE(SMBsplclose);
3081 return(UNIXERROR(ERRHRD,ERRgeneral));
3084 END_PROFILE(SMBsplclose);
3085 return(outsize);
3088 /****************************************************************************
3089 Reply to a printqueue.
3090 ****************************************************************************/
3092 int reply_printqueue(connection_struct *conn,
3093 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3095 int outsize = set_message(outbuf,2,3,True);
3096 int max_count = SVAL(inbuf,smb_vwv0);
3097 int start_index = SVAL(inbuf,smb_vwv1);
3098 START_PROFILE(SMBsplretq);
3100 /* we used to allow the client to get the cnum wrong, but that
3101 is really quite gross and only worked when there was only
3102 one printer - I think we should now only accept it if they
3103 get it right (tridge) */
3104 if (!CAN_PRINT(conn)) {
3105 END_PROFILE(SMBsplretq);
3106 return ERROR_DOS(ERRDOS,ERRnoaccess);
3109 SSVAL(outbuf,smb_vwv0,0);
3110 SSVAL(outbuf,smb_vwv1,0);
3111 SCVAL(smb_buf(outbuf),0,1);
3112 SSVAL(smb_buf(outbuf),1,0);
3114 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3115 start_index, max_count));
3118 print_queue_struct *queue = NULL;
3119 print_status_struct status;
3120 char *p = smb_buf(outbuf) + 3;
3121 int count = print_queue_status(SNUM(conn), &queue, &status);
3122 int num_to_get = ABS(max_count);
3123 int first = (max_count>0?start_index:start_index+max_count+1);
3124 int i;
3126 if (first >= count)
3127 num_to_get = 0;
3128 else
3129 num_to_get = MIN(num_to_get,count-first);
3132 for (i=first;i<first+num_to_get;i++) {
3133 put_dos_date2(p,0,queue[i].time);
3134 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
3135 SSVAL(p,5, queue[i].job);
3136 SIVAL(p,7,queue[i].size);
3137 SCVAL(p,11,0);
3138 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
3139 p += 28;
3142 if (count > 0) {
3143 outsize = set_message(outbuf,2,28*count+3,False);
3144 SSVAL(outbuf,smb_vwv0,count);
3145 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3146 SCVAL(smb_buf(outbuf),0,1);
3147 SSVAL(smb_buf(outbuf),1,28*count);
3150 SAFE_FREE(queue);
3152 DEBUG(3,("%d entries returned in queue\n",count));
3155 END_PROFILE(SMBsplretq);
3156 return(outsize);
3159 /****************************************************************************
3160 Reply to a printwrite.
3161 ****************************************************************************/
3163 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3165 int numtowrite;
3166 int outsize = set_message(outbuf,0,0,True);
3167 char *data;
3168 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3170 START_PROFILE(SMBsplwr);
3172 if (!CAN_PRINT(conn)) {
3173 END_PROFILE(SMBsplwr);
3174 return ERROR_DOS(ERRDOS,ERRnoaccess);
3177 CHECK_FSP(fsp,conn);
3178 CHECK_WRITE(fsp);
3180 numtowrite = SVAL(smb_buf(inbuf),1);
3181 data = smb_buf(inbuf) + 3;
3183 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3184 END_PROFILE(SMBsplwr);
3185 return(UNIXERROR(ERRHRD,ERRdiskfull));
3188 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3190 END_PROFILE(SMBsplwr);
3191 return(outsize);
3194 /****************************************************************************
3195 The guts of the mkdir command, split out so it may be called by the NT SMB
3196 code.
3197 ****************************************************************************/
3199 NTSTATUS mkdir_internal(connection_struct *conn, pstring directory)
3201 BOOL bad_path = False;
3202 SMB_STRUCT_STAT sbuf;
3203 int ret= -1;
3205 unix_convert(directory,conn,0,&bad_path,&sbuf);
3207 if( strchr_m(directory, ':')) {
3208 return NT_STATUS_NOT_A_DIRECTORY;
3211 if (ms_has_wild(directory)) {
3212 return NT_STATUS_OBJECT_NAME_INVALID;
3215 if (bad_path) {
3216 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3219 if (check_name(directory, conn))
3220 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory));
3222 if (ret == -1) {
3223 if(errno == ENOENT) {
3224 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3226 return map_nt_error_from_unix(errno);
3229 return NT_STATUS_OK;
3232 /****************************************************************************
3233 Reply to a mkdir.
3234 ****************************************************************************/
3236 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3238 pstring directory;
3239 int outsize;
3240 NTSTATUS status;
3241 START_PROFILE(SMBmkdir);
3243 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False);
3244 if (!NT_STATUS_IS_OK(status)) {
3245 END_PROFILE(SMBmkdir);
3246 return ERROR_NT(status);
3249 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
3251 status = mkdir_internal(conn, directory);
3252 if (!NT_STATUS_IS_OK(status)) {
3253 END_PROFILE(SMBmkdir);
3254 return ERROR_NT(status);
3257 outsize = set_message(outbuf,0,0,True);
3259 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3261 END_PROFILE(SMBmkdir);
3262 return(outsize);
3265 /****************************************************************************
3266 Static function used by reply_rmdir to delete an entire directory
3267 tree recursively. Return False on ok, True on fail.
3268 ****************************************************************************/
3270 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3272 const char *dname = NULL;
3273 BOOL ret = False;
3274 void *dirptr = OpenDir(conn, directory, False);
3276 if(dirptr == NULL)
3277 return True;
3279 while((dname = ReadDirName(dirptr))) {
3280 pstring fullname;
3281 SMB_STRUCT_STAT st;
3283 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3284 continue;
3286 /* Construct the full name. */
3287 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3288 errno = ENOMEM;
3289 ret = True;
3290 break;
3293 pstrcpy(fullname, directory);
3294 pstrcat(fullname, "/");
3295 pstrcat(fullname, dname);
3297 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
3298 ret = True;
3299 break;
3302 if(st.st_mode & S_IFDIR) {
3303 if(recursive_rmdir(conn, fullname)!=0) {
3304 ret = True;
3305 break;
3307 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
3308 ret = True;
3309 break;
3311 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
3312 ret = True;
3313 break;
3316 CloseDir(dirptr);
3317 return ret;
3320 /****************************************************************************
3321 The internals of the rmdir code - called elsewhere.
3322 ****************************************************************************/
3324 BOOL rmdir_internals(connection_struct *conn, char *directory)
3326 BOOL ok;
3328 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3329 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3331 * Check to see if the only thing in this directory are
3332 * vetoed files/directories. If so then delete them and
3333 * retry. If we fail to delete any of them (and we *don't*
3334 * do a recursive delete) then fail the rmdir.
3336 BOOL all_veto_files = True;
3337 const char *dname;
3338 void *dirptr = OpenDir(conn, directory, False);
3340 if(dirptr != NULL) {
3341 int dirpos = TellDir(dirptr);
3342 while ((dname = ReadDirName(dirptr))) {
3343 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3344 continue;
3345 if(!IS_VETO_PATH(conn, dname)) {
3346 all_veto_files = False;
3347 break;
3351 if(all_veto_files) {
3352 SeekDir(dirptr,dirpos);
3353 while ((dname = ReadDirName(dirptr))) {
3354 pstring fullname;
3355 SMB_STRUCT_STAT st;
3357 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3358 continue;
3360 /* Construct the full name. */
3361 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3362 errno = ENOMEM;
3363 break;
3366 pstrcpy(fullname, directory);
3367 pstrcat(fullname, "/");
3368 pstrcat(fullname, dname);
3370 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
3371 break;
3372 if(st.st_mode & S_IFDIR) {
3373 if(lp_recursive_veto_delete(SNUM(conn))) {
3374 if(recursive_rmdir(conn, fullname) != 0)
3375 break;
3377 if(SMB_VFS_RMDIR(conn,fullname) != 0)
3378 break;
3379 } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
3380 break;
3382 CloseDir(dirptr);
3383 /* Retry the rmdir */
3384 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3385 } else {
3386 CloseDir(dirptr);
3388 } else {
3389 errno = ENOTEMPTY;
3393 if (!ok)
3394 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
3396 return ok;
3399 /****************************************************************************
3400 Reply to a rmdir.
3401 ****************************************************************************/
3403 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3405 pstring directory;
3406 int outsize = 0;
3407 BOOL ok = False;
3408 BOOL bad_path = False;
3409 SMB_STRUCT_STAT sbuf;
3410 NTSTATUS status;
3411 START_PROFILE(SMBrmdir);
3413 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False);
3414 if (!NT_STATUS_IS_OK(status)) {
3415 END_PROFILE(SMBrmdir);
3416 return ERROR_NT(status);
3419 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3421 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3422 if (bad_path) {
3423 END_PROFILE(SMBrmdir);
3424 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3427 if (check_name(directory,conn)) {
3428 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3429 ok = rmdir_internals(conn, directory);
3432 if (!ok) {
3433 END_PROFILE(SMBrmdir);
3434 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRbadpath);
3437 outsize = set_message(outbuf,0,0,True);
3439 DEBUG( 3, ( "rmdir %s\n", directory ) );
3441 END_PROFILE(SMBrmdir);
3442 return(outsize);
3445 /*******************************************************************
3446 Resolve wildcards in a filename rename.
3447 Note that name is in UNIX charset and thus potentially can be more
3448 than fstring buffer (255 bytes) especially in default UTF-8 case.
3449 Therefore, we use pstring inside and all calls should ensure that
3450 name2 is at least pstring-long (they do already)
3451 ********************************************************************/
3453 static BOOL resolve_wildcards(const char *name1, char *name2)
3455 pstring root1,root2;
3456 pstring ext1,ext2;
3457 char *p,*p2, *pname1, *pname2;
3458 int available_space, actual_space;
3461 pname1 = strrchr_m(name1,'/');
3462 pname2 = strrchr_m(name2,'/');
3464 if (!pname1 || !pname2)
3465 return(False);
3467 pstrcpy(root1,pname1);
3468 pstrcpy(root2,pname2);
3469 p = strrchr_m(root1,'.');
3470 if (p) {
3471 *p = 0;
3472 pstrcpy(ext1,p+1);
3473 } else {
3474 pstrcpy(ext1,"");
3476 p = strrchr_m(root2,'.');
3477 if (p) {
3478 *p = 0;
3479 pstrcpy(ext2,p+1);
3480 } else {
3481 pstrcpy(ext2,"");
3484 p = root1;
3485 p2 = root2;
3486 while (*p2) {
3487 if (*p2 == '?') {
3488 *p2 = *p;
3489 p2++;
3490 } else if (*p2 == '*') {
3491 pstrcpy(p2, p);
3492 break;
3493 } else {
3494 p2++;
3496 if (*p)
3497 p++;
3500 p = ext1;
3501 p2 = ext2;
3502 while (*p2) {
3503 if (*p2 == '?') {
3504 *p2 = *p;
3505 p2++;
3506 } else if (*p2 == '*') {
3507 pstrcpy(p2, p);
3508 break;
3509 } else {
3510 p2++;
3512 if (*p)
3513 p++;
3516 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
3518 if (ext2[0]) {
3519 actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
3520 if (actual_space >= available_space - 1) {
3521 DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
3522 actual_space - available_space));
3524 } else {
3525 pstrcpy_base(pname2, root2, name2);
3528 return(True);
3531 /****************************************************************************
3532 Ensure open files have their names updates.
3533 ****************************************************************************/
3535 static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode, char *newname)
3537 files_struct *fsp;
3538 BOOL did_rename = False;
3540 for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
3541 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
3542 fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
3543 fsp->fsp_name, newname ));
3544 string_set(&fsp->fsp_name, newname);
3545 did_rename = True;
3548 if (!did_rename)
3549 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
3550 (unsigned int)dev, (double)inode, newname ));
3553 /****************************************************************************
3554 Rename an open file - given an fsp.
3555 ****************************************************************************/
3557 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, uint16 attrs, BOOL replace_if_exists)
3559 SMB_STRUCT_STAT sbuf;
3560 BOOL bad_path = False;
3561 pstring newname_last_component;
3562 NTSTATUS error = NT_STATUS_OK;
3563 BOOL dest_exists;
3564 BOOL rcdest = True;
3566 ZERO_STRUCT(sbuf);
3567 rcdest = unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf);
3569 /* Quick check for "." and ".." */
3570 if (!bad_path && newname_last_component[0] == '.') {
3571 if (!newname_last_component[1] || (newname_last_component[1] == '.' && !newname_last_component[2])) {
3572 return NT_STATUS_ACCESS_DENIED;
3575 if (!rcdest && bad_path) {
3576 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3579 /* Ensure newname contains a '/' */
3580 if(strrchr_m(newname,'/') == 0) {
3581 pstring tmpstr;
3583 pstrcpy(tmpstr, "./");
3584 pstrcat(tmpstr, newname);
3585 pstrcpy(newname, tmpstr);
3589 * Check for special case with case preserving and not
3590 * case sensitive. If the old last component differs from the original
3591 * last component only by case, then we should allow
3592 * the rename (user is trying to change the case of the
3593 * filename).
3596 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
3597 strequal(newname, fsp->fsp_name)) {
3598 char *p;
3599 pstring newname_modified_last_component;
3602 * Get the last component of the modified name.
3603 * Note that we guarantee that newname contains a '/'
3604 * character above.
3606 p = strrchr_m(newname,'/');
3607 pstrcpy(newname_modified_last_component,p+1);
3609 if(strcsequal(newname_modified_last_component,
3610 newname_last_component) == False) {
3612 * Replace the modified last component with
3613 * the original.
3615 pstrcpy(p+1, newname_last_component);
3620 * If the src and dest names are identical - including case,
3621 * don't do the rename, just return success.
3624 if (strcsequal(fsp->fsp_name, newname)) {
3625 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
3626 newname));
3627 return NT_STATUS_OK;
3630 dest_exists = vfs_object_exist(conn,newname,NULL);
3632 if(!replace_if_exists && dest_exists) {
3633 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
3634 fsp->fsp_name,newname));
3635 return NT_STATUS_OBJECT_NAME_COLLISION;
3638 error = can_rename(newname,conn,attrs,&sbuf);
3640 if (dest_exists && !NT_STATUS_IS_OK(error)) {
3641 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3642 nt_errstr(error), fsp->fsp_name,newname));
3643 if (NT_STATUS_EQUAL(error,NT_STATUS_SHARING_VIOLATION))
3644 error = NT_STATUS_ACCESS_DENIED;
3645 return error;
3648 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
3649 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
3650 fsp->fsp_name,newname));
3651 rename_open_files(conn, fsp->dev, fsp->inode, newname);
3652 return NT_STATUS_OK;
3655 if (errno == ENOTDIR || errno == EISDIR)
3656 error = NT_STATUS_OBJECT_NAME_COLLISION;
3657 else
3658 error = map_nt_error_from_unix(errno);
3660 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
3661 nt_errstr(error), fsp->fsp_name,newname));
3663 return error;
3666 /****************************************************************************
3667 The guts of the rename command, split out so it may be called by the NT SMB
3668 code.
3669 ****************************************************************************/
3671 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, uint16 attrs, BOOL replace_if_exists)
3673 pstring directory;
3674 pstring mask;
3675 pstring last_component_src;
3676 pstring last_component_dest;
3677 char *p;
3678 BOOL has_wild;
3679 BOOL bad_path_src = False;
3680 BOOL bad_path_dest = False;
3681 int count=0;
3682 NTSTATUS error = NT_STATUS_OK;
3683 BOOL rc = True;
3684 BOOL rcdest = True;
3685 SMB_STRUCT_STAT sbuf1, sbuf2;
3687 *directory = *mask = 0;
3689 ZERO_STRUCT(sbuf1);
3690 ZERO_STRUCT(sbuf2);
3692 rc = unix_convert(name,conn,last_component_src,&bad_path_src,&sbuf1);
3693 if (!rc && bad_path_src) {
3694 if (ms_has_wild(last_component_src))
3695 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3696 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3699 /* Quick check for "." and ".." */
3700 if (last_component_src[0] == '.') {
3701 if (!last_component_src[1] || (last_component_src[1] == '.' && !last_component_src[2])) {
3702 return NT_STATUS_OBJECT_NAME_INVALID;
3706 rcdest = unix_convert(newname,conn,last_component_dest,&bad_path_dest,&sbuf2);
3708 /* Quick check for "." and ".." */
3709 if (last_component_dest[0] == '.') {
3710 if (!last_component_dest[1] || (last_component_dest[1] == '.' && !last_component_dest[2])) {
3711 return NT_STATUS_OBJECT_NAME_INVALID;
3716 * Split the old name into directory and last component
3717 * strings. Note that unix_convert may have stripped off a
3718 * leading ./ from both name and newname if the rename is
3719 * at the root of the share. We need to make sure either both
3720 * name and newname contain a / character or neither of them do
3721 * as this is checked in resolve_wildcards().
3724 p = strrchr_m(name,'/');
3725 if (!p) {
3726 pstrcpy(directory,".");
3727 pstrcpy(mask,name);
3728 } else {
3729 *p = 0;
3730 pstrcpy(directory,name);
3731 pstrcpy(mask,p+1);
3732 *p = '/'; /* Replace needed for exceptional test below. */
3736 * We should only check the mangled cache
3737 * here if unix_convert failed. This means
3738 * that the path in 'mask' doesn't exist
3739 * on the file system and so we need to look
3740 * for a possible mangle. This patch from
3741 * Tine Smukavec <valentin.smukavec@hermes.si>.
3744 if (!rc && mangle_is_mangled(mask))
3745 mangle_check_cache( mask, sizeof(pstring)-1 );
3747 has_wild = ms_has_wild(mask);
3749 if (!has_wild) {
3751 * No wildcards - just process the one file.
3753 BOOL is_short_name = mangle_is_8_3(name, True);
3755 /* Add a terminating '/' to the directory name. */
3756 pstrcat(directory,"/");
3757 pstrcat(directory,mask);
3759 /* Ensure newname contains a '/' also */
3760 if(strrchr_m(newname,'/') == 0) {
3761 pstring tmpstr;
3763 pstrcpy(tmpstr, "./");
3764 pstrcat(tmpstr, newname);
3765 pstrcpy(newname, tmpstr);
3768 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
3769 directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
3770 conn->case_sensitive, conn->case_preserve, conn->short_case_preserve, directory,
3771 newname, last_component_dest, is_short_name));
3774 * Check for special case with case preserving and not
3775 * case sensitive, if directory and newname are identical,
3776 * and the old last component differs from the original
3777 * last component only by case, then we should allow
3778 * the rename (user is trying to change the case of the
3779 * filename).
3781 if((conn->case_sensitive == False) &&
3782 (((conn->case_preserve == True) &&
3783 (is_short_name == False)) ||
3784 ((conn->short_case_preserve == True) &&
3785 (is_short_name == True))) &&
3786 strcsequal(directory, newname)) {
3787 pstring modified_last_component;
3790 * Get the last component of the modified name.
3791 * Note that we guarantee that newname contains a '/'
3792 * character above.
3794 p = strrchr_m(newname,'/');
3795 pstrcpy(modified_last_component,p+1);
3797 if(strcsequal(modified_last_component,
3798 last_component_dest) == False) {
3800 * Replace the modified last component with
3801 * the original.
3803 pstrcpy(p+1, last_component_dest);
3807 resolve_wildcards(directory,newname);
3810 * The source object must exist.
3813 if (!vfs_object_exist(conn, directory, &sbuf1)) {
3814 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
3815 directory,newname));
3817 if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
3819 * Must return different errors depending on whether the parent
3820 * directory existed or not.
3823 p = strrchr_m(directory, '/');
3824 if (!p)
3825 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3826 *p = '\0';
3827 if (vfs_object_exist(conn, directory, NULL))
3828 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3829 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3831 error = map_nt_error_from_unix(errno);
3832 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3833 nt_errstr(error), directory,newname));
3835 return error;
3838 if (!rcdest && bad_path_dest) {
3839 if (ms_has_wild(last_component_dest))
3840 return NT_STATUS_OBJECT_NAME_INVALID;
3841 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3844 error = can_rename(directory,conn,attrs,&sbuf1);
3846 if (!NT_STATUS_IS_OK(error)) {
3847 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3848 nt_errstr(error), directory,newname));
3849 return error;
3853 * If the src and dest names are identical - including case,
3854 * don't do the rename, just return success.
3857 if (strcsequal(directory, newname)) {
3858 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3859 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
3860 return NT_STATUS_OK;
3863 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
3864 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
3865 directory,newname));
3866 return NT_STATUS_OBJECT_NAME_COLLISION;
3869 if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
3870 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
3871 directory,newname));
3872 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3873 return NT_STATUS_OK;
3876 if (errno == ENOTDIR || errno == EISDIR)
3877 error = NT_STATUS_OBJECT_NAME_COLLISION;
3878 else
3879 error = map_nt_error_from_unix(errno);
3881 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3882 nt_errstr(error), directory,newname));
3884 return error;
3885 } else {
3887 * Wildcards - process each file that matches.
3889 void *dirptr = NULL;
3890 const char *dname;
3891 pstring destname;
3893 if (check_name(directory,conn))
3894 dirptr = OpenDir(conn, directory, True);
3896 if (dirptr) {
3897 error = NT_STATUS_NO_SUCH_FILE;
3898 /* Was error = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */
3900 if (strequal(mask,"????????.???"))
3901 pstrcpy(mask,"*");
3903 while ((dname = ReadDirName(dirptr))) {
3904 pstring fname;
3905 BOOL sysdir_entry = False;
3907 pstrcpy(fname,dname);
3909 /* Quick check for "." and ".." */
3910 if (fname[0] == '.') {
3911 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
3912 if (attrs & aDIR) {
3913 sysdir_entry = True;
3914 } else {
3915 continue;
3920 if(!mask_match(fname, mask, conn->case_sensitive))
3921 continue;
3923 if (sysdir_entry) {
3924 error = NT_STATUS_OBJECT_NAME_INVALID;
3925 break;
3928 error = NT_STATUS_ACCESS_DENIED;
3929 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3930 if (!vfs_object_exist(conn, fname, &sbuf1)) {
3931 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3932 DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
3933 continue;
3935 error = can_rename(fname,conn,attrs,&sbuf1);
3936 if (!NT_STATUS_IS_OK(error)) {
3937 DEBUG(6,("rename %s refused\n", fname));
3938 continue;
3940 pstrcpy(destname,newname);
3942 if (!resolve_wildcards(fname,destname)) {
3943 DEBUG(6,("resolve_wildcards %s %s failed\n",
3944 fname, destname));
3945 continue;
3948 if (strcsequal(fname,destname)) {
3949 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3950 DEBUG(3,("rename_internals: identical names in wildcard rename %s - success\n", fname));
3951 count++;
3952 error = NT_STATUS_OK;
3953 continue;
3956 if (!replace_if_exists &&
3957 vfs_file_exist(conn,destname, NULL)) {
3958 DEBUG(6,("file_exist %s\n", destname));
3959 error = NT_STATUS_OBJECT_NAME_COLLISION;
3960 continue;
3963 if (!SMB_VFS_RENAME(conn,fname,destname)) {
3964 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3965 count++;
3966 error = NT_STATUS_OK;
3968 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3970 CloseDir(dirptr);
3973 if (!NT_STATUS_EQUAL(error,NT_STATUS_NO_SUCH_FILE)) {
3974 if (!rcdest && bad_path_dest) {
3975 if (ms_has_wild(last_component_dest))
3976 return NT_STATUS_OBJECT_NAME_INVALID;
3977 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3982 if (count == 0 && NT_STATUS_IS_OK(error)) {
3983 error = map_nt_error_from_unix(errno);
3986 return error;
3989 /****************************************************************************
3990 Reply to a mv.
3991 ****************************************************************************/
3993 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
3994 int dum_buffsize)
3996 int outsize = 0;
3997 pstring name;
3998 pstring newname;
3999 char *p;
4000 uint16 attrs = SVAL(inbuf,smb_vwv0);
4001 NTSTATUS status;
4003 START_PROFILE(SMBmv);
4005 p = smb_buf(inbuf) + 1;
4006 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True);
4007 if (!NT_STATUS_IS_OK(status)) {
4008 END_PROFILE(SMBmv);
4009 return ERROR_NT(status);
4011 p++;
4012 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True);
4013 if (!NT_STATUS_IS_OK(status)) {
4014 END_PROFILE(SMBmv);
4015 return ERROR_NT(status);
4018 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
4019 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4021 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
4023 status = rename_internals(conn, name, newname, attrs, False);
4024 if (!NT_STATUS_IS_OK(status)) {
4025 END_PROFILE(SMBmv);
4026 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4027 /* We have re-scheduled this call. */
4028 clear_cached_errors();
4029 return -1;
4031 return ERROR_NT(status);
4035 * Win2k needs a changenotify request response before it will
4036 * update after a rename..
4038 process_pending_change_notify_queue((time_t)0);
4039 outsize = set_message(outbuf,0,0,True);
4041 END_PROFILE(SMBmv);
4042 return(outsize);
4045 /*******************************************************************
4046 Copy a file as part of a reply_copy.
4047 ******************************************************************/
4049 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
4050 int count,BOOL target_is_directory, int *err_ret)
4052 int Access,action;
4053 SMB_STRUCT_STAT src_sbuf, sbuf2;
4054 SMB_OFF_T ret=-1;
4055 files_struct *fsp1,*fsp2;
4056 pstring dest;
4057 uint32 dosattrs;
4059 *err_ret = 0;
4061 pstrcpy(dest,dest1);
4062 if (target_is_directory) {
4063 char *p = strrchr_m(src,'/');
4064 if (p)
4065 p++;
4066 else
4067 p = src;
4068 pstrcat(dest,"/");
4069 pstrcat(dest,p);
4072 if (!vfs_file_exist(conn,src,&src_sbuf))
4073 return(False);
4075 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
4076 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),FILE_ATTRIBUTE_NORMAL,INTERNAL_OPEN_ONLY,
4077 &Access,&action);
4079 if (!fsp1)
4080 return(False);
4082 if (!target_is_directory && count)
4083 ofun = FILE_EXISTS_OPEN;
4085 dosattrs = dos_mode(conn, src, &src_sbuf);
4086 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1)
4087 ZERO_STRUCTP(&sbuf2);
4089 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
4090 ofun,dosattrs,INTERNAL_OPEN_ONLY,&Access,&action);
4092 if (!fsp2) {
4093 close_file(fsp1,False);
4094 return(False);
4097 if ((ofun&3) == 1) {
4098 if(SMB_VFS_LSEEK(fsp2,fsp2->fd,0,SEEK_END) == -1) {
4099 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
4101 * Stop the copy from occurring.
4103 ret = -1;
4104 src_sbuf.st_size = 0;
4108 if (src_sbuf.st_size)
4109 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
4111 close_file(fsp1,False);
4113 /* Ensure the modtime is set correctly on the destination file. */
4114 fsp2->pending_modtime = src_sbuf.st_mtime;
4117 * As we are opening fsp1 read-only we only expect
4118 * an error on close on fsp2 if we are out of space.
4119 * Thus we don't look at the error return from the
4120 * close of fsp1.
4122 *err_ret = close_file(fsp2,False);
4124 return(ret == (SMB_OFF_T)src_sbuf.st_size);
4127 /****************************************************************************
4128 Reply to a file copy.
4129 ****************************************************************************/
4131 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4133 int outsize = 0;
4134 pstring name;
4135 pstring directory;
4136 pstring mask,newname;
4137 char *p;
4138 int count=0;
4139 int error = ERRnoaccess;
4140 int err = 0;
4141 BOOL has_wild;
4142 BOOL exists=False;
4143 int tid2 = SVAL(inbuf,smb_vwv0);
4144 int ofun = SVAL(inbuf,smb_vwv1);
4145 int flags = SVAL(inbuf,smb_vwv2);
4146 BOOL target_is_directory=False;
4147 BOOL bad_path1 = False;
4148 BOOL bad_path2 = False;
4149 BOOL rc = True;
4150 SMB_STRUCT_STAT sbuf1, sbuf2;
4151 NTSTATUS status;
4153 START_PROFILE(SMBcopy);
4155 *directory = *mask = 0;
4157 p = smb_buf(inbuf);
4158 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True);
4159 if (!NT_STATUS_IS_OK(status)) {
4160 END_PROFILE(SMBcopy);
4161 return ERROR_NT(status);
4163 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True);
4164 if (!NT_STATUS_IS_OK(status)) {
4165 END_PROFILE(SMBcopy);
4166 return ERROR_NT(status);
4169 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
4171 if (tid2 != conn->cnum) {
4172 /* can't currently handle inter share copies XXXX */
4173 DEBUG(3,("Rejecting inter-share copy\n"));
4174 END_PROFILE(SMBcopy);
4175 return ERROR_DOS(ERRSRV,ERRinvdevice);
4178 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
4179 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4181 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
4182 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
4184 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
4186 if ((flags&1) && target_is_directory) {
4187 END_PROFILE(SMBcopy);
4188 return ERROR_DOS(ERRDOS,ERRbadfile);
4191 if ((flags&2) && !target_is_directory) {
4192 END_PROFILE(SMBcopy);
4193 return ERROR_DOS(ERRDOS,ERRbadpath);
4196 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
4197 /* wants a tree copy! XXXX */
4198 DEBUG(3,("Rejecting tree copy\n"));
4199 END_PROFILE(SMBcopy);
4200 return ERROR_DOS(ERRSRV,ERRerror);
4203 p = strrchr_m(name,'/');
4204 if (!p) {
4205 pstrcpy(directory,"./");
4206 pstrcpy(mask,name);
4207 } else {
4208 *p = 0;
4209 pstrcpy(directory,name);
4210 pstrcpy(mask,p+1);
4214 * We should only check the mangled cache
4215 * here if unix_convert failed. This means
4216 * that the path in 'mask' doesn't exist
4217 * on the file system and so we need to look
4218 * for a possible mangle. This patch from
4219 * Tine Smukavec <valentin.smukavec@hermes.si>.
4222 if (!rc && mangle_is_mangled(mask))
4223 mangle_check_cache( mask, sizeof(pstring)-1 );
4225 has_wild = ms_has_wild(mask);
4227 if (!has_wild) {
4228 pstrcat(directory,"/");
4229 pstrcat(directory,mask);
4230 if (resolve_wildcards(directory,newname) &&
4231 copy_file(directory,newname,conn,ofun, count,target_is_directory,&err))
4232 count++;
4233 if(!count && err) {
4234 errno = err;
4235 END_PROFILE(SMBcopy);
4236 return(UNIXERROR(ERRHRD,ERRgeneral));
4238 if (!count) {
4239 exists = vfs_file_exist(conn,directory,NULL);
4241 } else {
4242 void *dirptr = NULL;
4243 const char *dname;
4244 pstring destname;
4246 if (check_name(directory,conn))
4247 dirptr = OpenDir(conn, directory, True);
4249 if (dirptr) {
4250 error = ERRbadfile;
4252 if (strequal(mask,"????????.???"))
4253 pstrcpy(mask,"*");
4255 while ((dname = ReadDirName(dirptr))) {
4256 pstring fname;
4257 pstrcpy(fname,dname);
4259 if(!mask_match(fname, mask, conn->case_sensitive))
4260 continue;
4262 error = ERRnoaccess;
4263 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
4264 pstrcpy(destname,newname);
4265 if (resolve_wildcards(fname,destname) &&
4266 copy_file(fname,destname,conn,ofun,
4267 count,target_is_directory,&err))
4268 count++;
4269 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
4271 CloseDir(dirptr);
4275 if (count == 0) {
4276 if(err) {
4277 /* Error on close... */
4278 errno = err;
4279 END_PROFILE(SMBcopy);
4280 return(UNIXERROR(ERRHRD,ERRgeneral));
4283 if (exists) {
4284 END_PROFILE(SMBcopy);
4285 return ERROR_DOS(ERRDOS,error);
4286 } else {
4287 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
4288 unix_ERR_class = ERRDOS;
4289 unix_ERR_code = ERRbadpath;
4291 END_PROFILE(SMBcopy);
4292 return(UNIXERROR(ERRDOS,error));
4296 outsize = set_message(outbuf,1,0,True);
4297 SSVAL(outbuf,smb_vwv0,count);
4299 END_PROFILE(SMBcopy);
4300 return(outsize);
4303 /****************************************************************************
4304 Reply to a setdir.
4305 ****************************************************************************/
4307 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4309 int snum;
4310 int outsize = 0;
4311 BOOL ok = False;
4312 pstring newdir;
4313 NTSTATUS status;
4315 START_PROFILE(pathworks_setdir);
4317 snum = SNUM(conn);
4318 if (!CAN_SETDIR(snum)) {
4319 END_PROFILE(pathworks_setdir);
4320 return ERROR_DOS(ERRDOS,ERRnoaccess);
4323 srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status, False);
4324 if (!NT_STATUS_IS_OK(status)) {
4325 END_PROFILE(pathworks_setdir);
4326 return ERROR_NT(status);
4329 if (strlen(newdir) == 0) {
4330 ok = True;
4331 } else {
4332 ok = vfs_directory_exist(conn,newdir,NULL);
4333 if (ok)
4334 string_set(&conn->connectpath,newdir);
4337 if (!ok) {
4338 END_PROFILE(pathworks_setdir);
4339 return ERROR_DOS(ERRDOS,ERRbadpath);
4342 outsize = set_message(outbuf,0,0,True);
4343 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
4345 DEBUG(3,("setdir %s\n", newdir));
4347 END_PROFILE(pathworks_setdir);
4348 return(outsize);
4351 /****************************************************************************
4352 Get a lock pid, dealing with large count requests.
4353 ****************************************************************************/
4355 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
4357 if(!large_file_format)
4358 return SVAL(data,SMB_LPID_OFFSET(data_offset));
4359 else
4360 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
4363 /****************************************************************************
4364 Get a lock count, dealing with large count requests.
4365 ****************************************************************************/
4367 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4369 SMB_BIG_UINT count = 0;
4371 if(!large_file_format) {
4372 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4373 } else {
4375 #if defined(HAVE_LONGLONG)
4376 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4377 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4378 #else /* HAVE_LONGLONG */
4381 * NT4.x seems to be broken in that it sends large file (64 bit)
4382 * lockingX calls even if the CAP_LARGE_FILES was *not*
4383 * negotiated. For boxes without large unsigned ints truncate the
4384 * lock count by dropping the top 32 bits.
4387 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4388 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4389 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4390 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4391 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4394 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4395 #endif /* HAVE_LONGLONG */
4398 return count;
4401 #if !defined(HAVE_LONGLONG)
4402 /****************************************************************************
4403 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
4404 ****************************************************************************/
4406 static uint32 map_lock_offset(uint32 high, uint32 low)
4408 unsigned int i;
4409 uint32 mask = 0;
4410 uint32 highcopy = high;
4413 * Try and find out how many significant bits there are in high.
4416 for(i = 0; highcopy; i++)
4417 highcopy >>= 1;
4420 * We use 31 bits not 32 here as POSIX
4421 * lock offsets may not be negative.
4424 mask = (~0) << (31 - i);
4426 if(low & mask)
4427 return 0; /* Fail. */
4429 high <<= (31 - i);
4431 return (high|low);
4433 #endif /* !defined(HAVE_LONGLONG) */
4435 /****************************************************************************
4436 Get a lock offset, dealing with large offset requests.
4437 ****************************************************************************/
4439 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4441 SMB_BIG_UINT offset = 0;
4443 *err = False;
4445 if(!large_file_format) {
4446 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4447 } else {
4449 #if defined(HAVE_LONGLONG)
4450 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4451 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4452 #else /* HAVE_LONGLONG */
4455 * NT4.x seems to be broken in that it sends large file (64 bit)
4456 * lockingX calls even if the CAP_LARGE_FILES was *not*
4457 * negotiated. For boxes without large unsigned ints mangle the
4458 * lock offset by mapping the top 32 bits onto the lower 32.
4461 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4462 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4463 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4464 uint32 new_low = 0;
4466 if((new_low = map_lock_offset(high, low)) == 0) {
4467 *err = True;
4468 return (SMB_BIG_UINT)-1;
4471 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4472 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4473 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4474 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4477 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4478 #endif /* HAVE_LONGLONG */
4481 return offset;
4484 /****************************************************************************
4485 Reply to a lockingX request.
4486 ****************************************************************************/
4488 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4490 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4491 unsigned char locktype = CVAL(inbuf,smb_vwv3);
4492 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4493 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4494 uint16 num_locks = SVAL(inbuf,smb_vwv7);
4495 SMB_BIG_UINT count = 0, offset = 0;
4496 uint16 lock_pid;
4497 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4498 int i;
4499 char *data;
4500 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4501 BOOL err;
4502 BOOL my_lock_ctx = False;
4503 NTSTATUS status;
4505 START_PROFILE(SMBlockingX);
4507 CHECK_FSP(fsp,conn);
4509 data = smb_buf(inbuf);
4511 if (locktype & (LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_CHANGE_LOCKTYPE)) {
4512 /* we don't support these - and CANCEL_LOCK makes w2k
4513 and XP reboot so I don't really want to be
4514 compatible! (tridge) */
4515 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
4518 /* Check if this is an oplock break on a file
4519 we have granted an oplock on.
4521 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
4522 /* Client can insist on breaking to none. */
4523 BOOL break_to_none = (oplocklevel == 0);
4525 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4526 (unsigned int)oplocklevel, fsp->fnum ));
4529 * Make sure we have granted an exclusive or batch oplock on this file.
4532 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
4533 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4534 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4536 /* if this is a pure oplock break request then don't send a reply */
4537 if (num_locks == 0 && num_ulocks == 0) {
4538 END_PROFILE(SMBlockingX);
4539 return -1;
4540 } else {
4541 END_PROFILE(SMBlockingX);
4542 return ERROR_DOS(ERRDOS,ERRlock);
4546 if (remove_oplock(fsp, break_to_none) == False) {
4547 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4548 fsp->fsp_name ));
4551 /* if this is a pure oplock break request then don't send a reply */
4552 if (num_locks == 0 && num_ulocks == 0) {
4553 /* Sanity check - ensure a pure oplock break is not a
4554 chained request. */
4555 if(CVAL(inbuf,smb_vwv0) != 0xff)
4556 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4557 (unsigned int)CVAL(inbuf,smb_vwv0) ));
4558 END_PROFILE(SMBlockingX);
4559 return -1;
4564 * We do this check *after* we have checked this is not a oplock break
4565 * response message. JRA.
4568 release_level_2_oplocks_on_change(fsp);
4570 /* Data now points at the beginning of the list
4571 of smb_unlkrng structs */
4572 for(i = 0; i < (int)num_ulocks; i++) {
4573 lock_pid = get_lock_pid( data, i, large_file_format);
4574 count = get_lock_count( data, i, large_file_format);
4575 offset = get_lock_offset( data, i, large_file_format, &err);
4578 * There is no error code marked "stupid client bug".... :-).
4580 if(err) {
4581 END_PROFILE(SMBlockingX);
4582 return ERROR_DOS(ERRDOS,ERRnoaccess);
4585 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4586 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4588 status = do_unlock(fsp,conn,lock_pid,count,offset);
4589 if (NT_STATUS_V(status)) {
4590 END_PROFILE(SMBlockingX);
4591 return ERROR_NT(status);
4595 /* Setup the timeout in seconds. */
4597 lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000);
4599 /* Now do any requested locks */
4600 data += ((large_file_format ? 20 : 10)*num_ulocks);
4602 /* Data now points at the beginning of the list
4603 of smb_lkrng structs */
4605 for(i = 0; i < (int)num_locks; i++) {
4606 lock_pid = get_lock_pid( data, i, large_file_format);
4607 count = get_lock_count( data, i, large_file_format);
4608 offset = get_lock_offset( data, i, large_file_format, &err);
4611 * There is no error code marked "stupid client bug".... :-).
4613 if(err) {
4614 END_PROFILE(SMBlockingX);
4615 return ERROR_DOS(ERRDOS,ERRnoaccess);
4618 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
4619 (double)offset, (double)count, (unsigned int)lock_pid,
4620 fsp->fsp_name, (int)lock_timeout ));
4622 status = do_lock_spin(fsp,conn,lock_pid, count,offset,
4623 ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &my_lock_ctx);
4624 if (NT_STATUS_V(status)) {
4626 * Interesting fact found by IFSTEST /t LockOverlappedTest...
4627 * Even if it's our own lock context, we need to wait here as
4628 * there may be an unlock on the way.
4629 * So I removed a "&& !my_lock_ctx" from the following
4630 * if statement. JRA.
4632 if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
4634 * A blocking lock was requested. Package up
4635 * this smb into a queued request and push it
4636 * onto the blocking lock queue.
4638 if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) {
4639 END_PROFILE(SMBlockingX);
4640 return -1;
4643 break;
4647 /* If any of the above locks failed, then we must unlock
4648 all of the previous locks (X/Open spec). */
4649 if (i != num_locks && num_locks != 0) {
4651 * Ensure we don't do a remove on the lock that just failed,
4652 * as under POSIX rules, if we have a lock already there, we
4653 * will delete it (and we shouldn't) .....
4655 for(i--; i >= 0; i--) {
4656 lock_pid = get_lock_pid( data, i, large_file_format);
4657 count = get_lock_count( data, i, large_file_format);
4658 offset = get_lock_offset( data, i, large_file_format, &err);
4661 * There is no error code marked "stupid client bug".... :-).
4663 if(err) {
4664 END_PROFILE(SMBlockingX);
4665 return ERROR_DOS(ERRDOS,ERRnoaccess);
4668 do_unlock(fsp,conn,lock_pid,count,offset);
4670 END_PROFILE(SMBlockingX);
4671 return ERROR_NT(status);
4674 set_message(outbuf,2,0,True);
4676 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4677 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4679 END_PROFILE(SMBlockingX);
4680 return chain_reply(inbuf,outbuf,length,bufsize);
4683 /****************************************************************************
4684 Reply to a SMBreadbmpx (read block multiplex) request.
4685 ****************************************************************************/
4687 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4689 ssize_t nread = -1;
4690 ssize_t total_read;
4691 char *data;
4692 SMB_OFF_T startpos;
4693 int outsize;
4694 size_t maxcount;
4695 int max_per_packet;
4696 size_t tcount;
4697 int pad;
4698 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4699 START_PROFILE(SMBreadBmpx);
4701 /* this function doesn't seem to work - disable by default */
4702 if (!lp_readbmpx()) {
4703 END_PROFILE(SMBreadBmpx);
4704 return ERROR_DOS(ERRSRV,ERRuseSTD);
4707 outsize = set_message(outbuf,8,0,True);
4709 CHECK_FSP(fsp,conn);
4710 CHECK_READ(fsp);
4712 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
4713 maxcount = SVAL(inbuf,smb_vwv3);
4715 data = smb_buf(outbuf);
4716 pad = ((long)data)%4;
4717 if (pad)
4718 pad = 4 - pad;
4719 data += pad;
4721 max_per_packet = bufsize-(outsize+pad);
4722 tcount = maxcount;
4723 total_read = 0;
4725 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
4726 END_PROFILE(SMBreadBmpx);
4727 return ERROR_DOS(ERRDOS,ERRlock);
4730 do {
4731 size_t N = MIN(max_per_packet,tcount-total_read);
4733 nread = read_file(fsp,data,startpos,N);
4735 if (nread <= 0)
4736 nread = 0;
4738 if (nread < (ssize_t)N)
4739 tcount = total_read + nread;
4741 set_message(outbuf,8,nread,False);
4742 SIVAL(outbuf,smb_vwv0,startpos);
4743 SSVAL(outbuf,smb_vwv2,tcount);
4744 SSVAL(outbuf,smb_vwv6,nread);
4745 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4747 if (!send_smb(smbd_server_fd(),outbuf))
4748 exit_server("reply_readbmpx: send_smb failed.");
4750 total_read += nread;
4751 startpos += nread;
4752 } while (total_read < (ssize_t)tcount);
4754 END_PROFILE(SMBreadBmpx);
4755 return(-1);
4758 /****************************************************************************
4759 Reply to a SMBsetattrE.
4760 ****************************************************************************/
4762 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4764 struct utimbuf unix_times;
4765 int outsize = 0;
4766 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4767 START_PROFILE(SMBsetattrE);
4769 outsize = set_message(outbuf,0,0,True);
4771 if(!fsp || (fsp->conn != conn)) {
4772 END_PROFILE(SMBgetattrE);
4773 return ERROR_DOS(ERRDOS,ERRbadfid);
4777 * Convert the DOS times into unix times. Ignore create
4778 * time as UNIX can't set this.
4781 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4782 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4785 * Patch from Ray Frush <frush@engr.colostate.edu>
4786 * Sometimes times are sent as zero - ignore them.
4789 if ((unix_times.actime == 0) && (unix_times.modtime == 0)) {
4790 /* Ignore request */
4791 if( DEBUGLVL( 3 ) ) {
4792 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4793 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4795 END_PROFILE(SMBsetattrE);
4796 return(outsize);
4797 } else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) {
4798 /* set modify time = to access time if modify time was 0 */
4799 unix_times.modtime = unix_times.actime;
4802 /* Set the date on this file */
4803 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4804 END_PROFILE(SMBsetattrE);
4805 return ERROR_DOS(ERRDOS,ERRnoaccess);
4808 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4809 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4811 END_PROFILE(SMBsetattrE);
4812 return(outsize);
4816 /* Back from the dead for OS/2..... JRA. */
4818 /****************************************************************************
4819 Reply to a SMBwritebmpx (write block multiplex primary) request.
4820 ****************************************************************************/
4822 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4824 size_t numtowrite;
4825 ssize_t nwritten = -1;
4826 int outsize = 0;
4827 SMB_OFF_T startpos;
4828 size_t tcount;
4829 BOOL write_through;
4830 int smb_doff;
4831 char *data;
4832 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4833 START_PROFILE(SMBwriteBmpx);
4835 CHECK_FSP(fsp,conn);
4836 CHECK_WRITE(fsp);
4837 CHECK_ERROR(fsp);
4839 tcount = SVAL(inbuf,smb_vwv1);
4840 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
4841 write_through = BITSETW(inbuf+smb_vwv7,0);
4842 numtowrite = SVAL(inbuf,smb_vwv10);
4843 smb_doff = SVAL(inbuf,smb_vwv11);
4845 data = smb_base(inbuf) + smb_doff;
4847 /* If this fails we need to send an SMBwriteC response,
4848 not an SMBwritebmpx - set this up now so we don't forget */
4849 SCVAL(outbuf,smb_com,SMBwritec);
4851 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK,False)) {
4852 END_PROFILE(SMBwriteBmpx);
4853 return(ERROR_DOS(ERRDOS,ERRlock));
4856 nwritten = write_file(fsp,data,startpos,numtowrite);
4858 if(lp_syncalways(SNUM(conn)) || write_through)
4859 sync_file(conn,fsp);
4861 if(nwritten < (ssize_t)numtowrite) {
4862 END_PROFILE(SMBwriteBmpx);
4863 return(UNIXERROR(ERRHRD,ERRdiskfull));
4866 /* If the maximum to be written to this file
4867 is greater than what we just wrote then set
4868 up a secondary struct to be attached to this
4869 fd, we will use this to cache error messages etc. */
4871 if((ssize_t)tcount > nwritten) {
4872 write_bmpx_struct *wbms;
4873 if(fsp->wbmpx_ptr != NULL)
4874 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4875 else
4876 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
4877 if(!wbms) {
4878 DEBUG(0,("Out of memory in reply_readmpx\n"));
4879 END_PROFILE(SMBwriteBmpx);
4880 return(ERROR_DOS(ERRSRV,ERRnoresource));
4882 wbms->wr_mode = write_through;
4883 wbms->wr_discard = False; /* No errors yet */
4884 wbms->wr_total_written = nwritten;
4885 wbms->wr_errclass = 0;
4886 wbms->wr_error = 0;
4887 fsp->wbmpx_ptr = wbms;
4890 /* We are returning successfully, set the message type back to
4891 SMBwritebmpx */
4892 SCVAL(outbuf,smb_com,SMBwriteBmpx);
4894 outsize = set_message(outbuf,1,0,True);
4896 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
4898 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4899 fsp->fnum, (int)numtowrite, (int)nwritten ) );
4901 if (write_through && tcount==nwritten) {
4902 /* We need to send both a primary and a secondary response */
4903 smb_setlen(outbuf,outsize - 4);
4904 if (!send_smb(smbd_server_fd(),outbuf))
4905 exit_server("reply_writebmpx: send_smb failed.");
4907 /* Now the secondary */
4908 outsize = set_message(outbuf,1,0,True);
4909 SCVAL(outbuf,smb_com,SMBwritec);
4910 SSVAL(outbuf,smb_vwv0,nwritten);
4913 END_PROFILE(SMBwriteBmpx);
4914 return(outsize);
4917 /****************************************************************************
4918 Reply to a SMBwritebs (write block multiplex secondary) request.
4919 ****************************************************************************/
4921 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4923 size_t numtowrite;
4924 ssize_t nwritten = -1;
4925 int outsize = 0;
4926 SMB_OFF_T startpos;
4927 size_t tcount;
4928 BOOL write_through;
4929 int smb_doff;
4930 char *data;
4931 write_bmpx_struct *wbms;
4932 BOOL send_response = False;
4933 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4934 START_PROFILE(SMBwriteBs);
4936 CHECK_FSP(fsp,conn);
4937 CHECK_WRITE(fsp);
4939 tcount = SVAL(inbuf,smb_vwv1);
4940 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
4941 numtowrite = SVAL(inbuf,smb_vwv6);
4942 smb_doff = SVAL(inbuf,smb_vwv7);
4944 data = smb_base(inbuf) + smb_doff;
4946 /* We need to send an SMBwriteC response, not an SMBwritebs */
4947 SCVAL(outbuf,smb_com,SMBwritec);
4949 /* This fd should have an auxiliary struct attached,
4950 check that it does */
4951 wbms = fsp->wbmpx_ptr;
4952 if(!wbms) {
4953 END_PROFILE(SMBwriteBs);
4954 return(-1);
4957 /* If write through is set we can return errors, else we must cache them */
4958 write_through = wbms->wr_mode;
4960 /* Check for an earlier error */
4961 if(wbms->wr_discard) {
4962 END_PROFILE(SMBwriteBs);
4963 return -1; /* Just discard the packet */
4966 nwritten = write_file(fsp,data,startpos,numtowrite);
4968 if(lp_syncalways(SNUM(conn)) || write_through)
4969 sync_file(conn,fsp);
4971 if (nwritten < (ssize_t)numtowrite) {
4972 if(write_through) {
4973 /* We are returning an error - we can delete the aux struct */
4974 if (wbms)
4975 free((char *)wbms);
4976 fsp->wbmpx_ptr = NULL;
4977 END_PROFILE(SMBwriteBs);
4978 return(ERROR_DOS(ERRHRD,ERRdiskfull));
4980 END_PROFILE(SMBwriteBs);
4981 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4984 /* Increment the total written, if this matches tcount
4985 we can discard the auxiliary struct (hurrah !) and return a writeC */
4986 wbms->wr_total_written += nwritten;
4987 if(wbms->wr_total_written >= tcount) {
4988 if (write_through) {
4989 outsize = set_message(outbuf,1,0,True);
4990 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
4991 send_response = True;
4994 free((char *)wbms);
4995 fsp->wbmpx_ptr = NULL;
4998 if(send_response) {
4999 END_PROFILE(SMBwriteBs);
5000 return(outsize);
5003 END_PROFILE(SMBwriteBs);
5004 return(-1);
5007 /****************************************************************************
5008 Reply to a SMBgetattrE.
5009 ****************************************************************************/
5011 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5013 SMB_STRUCT_STAT sbuf;
5014 int outsize = 0;
5015 int mode;
5016 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5017 START_PROFILE(SMBgetattrE);
5019 outsize = set_message(outbuf,11,0,True);
5021 if(!fsp || (fsp->conn != conn)) {
5022 END_PROFILE(SMBgetattrE);
5023 return ERROR_DOS(ERRDOS,ERRbadfid);
5026 /* Do an fstat on this file */
5027 if(fsp_stat(fsp, &sbuf)) {
5028 END_PROFILE(SMBgetattrE);
5029 return(UNIXERROR(ERRDOS,ERRnoaccess));
5032 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
5035 * Convert the times into dos times. Set create
5036 * date to be last modify date as UNIX doesn't save
5037 * this.
5040 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
5041 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
5042 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
5044 if (mode & aDIR) {
5045 SIVAL(outbuf,smb_vwv6,0);
5046 SIVAL(outbuf,smb_vwv8,0);
5047 } else {
5048 uint32 allocation_size = get_allocation_size(fsp, &sbuf);
5049 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
5050 SIVAL(outbuf,smb_vwv8,allocation_size);
5052 SSVAL(outbuf,smb_vwv10, mode);
5054 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
5056 END_PROFILE(SMBgetattrE);
5057 return(outsize);