Make sure we don't clobber the stack when response consists of the empty
[Samba/gebeck_regimport.git] / source3 / smbd / reply.c
blobbca7a75fbba9b4b614c45ef23e3759b90af42a06
1 /*
2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 This file handles most of the reply_ calls that the server
23 makes to handle specific protocols
26 #include "includes.h"
28 /* look in server.c for some explanation of these variables */
29 extern int Protocol;
30 extern int max_send;
31 extern int max_recv;
32 extern char magic_char;
33 extern BOOL case_sensitive;
34 extern BOOL case_preserve;
35 extern BOOL short_case_preserve;
36 extern int global_oplock_break;
37 unsigned int smb_echo_count = 0;
39 extern BOOL global_encrypted_passwords_negotiated;
41 /****************************************************************************
42 Ensure we check the path in *exactly* the same way as W2K.
43 We're assuming here that '/' is not the second byte in any multibyte char
44 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
45 set.
46 ****************************************************************************/
48 NTSTATUS check_path_syntax(pstring destname, const pstring srcname)
50 char *d = destname;
51 const char *s = srcname;
52 NTSTATUS ret = NT_STATUS_OK;
54 while (*s) {
55 if (IS_DIRECTORY_SEP(*s)) {
57 * Safe to assume is not the second part of a mb char as this is handled below.
59 /* Eat multiple '/' or '\\' */
60 while (IS_DIRECTORY_SEP(*s)) {
61 s++;
63 if ((d != destname) && (*s != '\0')) {
64 /* We only care about non-leading or trailing '/' or '\\' */
65 *d++ = '/';
67 } else if ((s[0] == '.') && (s[1] == '.') && (IS_DIRECTORY_SEP(s[2]) || s[2] == '\0')) {
68 /* Uh oh - "../" or "..\\" or "..\0" ! */
71 * No mb char starts with '.' so we're safe checking the directory separator here.
74 /* If we just added a '/', delete it. */
76 if ((d > destname) && (*(d-1) == '/')) {
77 *(d-1) = '\0';
78 if (d == (destname + 1)) {
79 d--;
80 } else {
81 d -= 2;
84 /* Are we at the start ? Can't go back further if so. */
85 if (d == destname) {
86 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
88 /* Go back one level... */
89 while (d > destname) {
90 if (*d == '/')
91 break;
92 d--;
94 s += 3;
95 } else if ((s[0] == '.') && IS_DIRECTORY_SEP(s[1])) {
98 * No mb char starts with '.' so we're safe checking the directory separator here.
101 /* "./" or ".\\" fails with a different error depending on where it is... */
103 if (s == srcname) {
104 ret = NT_STATUS_OBJECT_NAME_INVALID;
105 } else {
106 if (s[2] == '\0') {
107 return NT_STATUS_INVALID_PARAMETER;
109 ret = NT_STATUS_OBJECT_PATH_NOT_FOUND;
111 s++;
112 } else {
113 if ((*s & 0x80) && IS_DIRECTORY_SEP(s[1])) {
115 * Potential mb char with second char a directory separator.
116 * All the encodings we care about are 2 byte only, so do a
117 * conversion to unicode. If the one byte char converts then
118 * it really is a directory separator following. Otherwise if
119 * the two byte character converts (and it should or our assumption
120 * about character sets is broken and we return an error) then copy both
121 * bytes as it's a MB character, not a directory separator.
124 uint16 ucs2_val;
126 if (convert_string(CH_UNIX, CH_UCS2, s, 1, &ucs2_val, 2, False) == 2) {
128 } else if (convert_string(CH_UNIX, CH_UCS2, s, 2, &ucs2_val, 2, False) == 2) {
129 *d++ = *s++;
130 } else {
131 DEBUG(0,("check_path_syntax: directory separator assumptions invalid !\n"));
132 return NT_STATUS_INVALID_PARAMETER;
135 /* Just copy the char (or the second byte of the mb char). */
136 *d++ = *s++;
139 *d = '\0';
140 return ret;
143 /****************************************************************************
144 Pull a string and check the path - provide for error return.
145 ****************************************************************************/
147 size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags, NTSTATUS *err)
149 pstring tmppath;
150 char *tmppath_ptr = tmppath;
151 size_t ret;
152 #ifdef DEVELOPER
153 SMB_ASSERT(dest_len == sizeof(pstring));
154 #endif
156 if (src_len == 0) {
157 ret = srvstr_pull_buf( inbuf, tmppath_ptr, src, dest_len, flags);
158 } else {
159 ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags);
161 *err = check_path_syntax(dest, tmppath);
162 return ret;
165 /****************************************************************************
166 Reply to a special message.
167 ****************************************************************************/
169 int reply_special(char *inbuf,char *outbuf)
171 int outsize = 4;
172 int msg_type = CVAL(inbuf,0);
173 int msg_flags = CVAL(inbuf,1);
174 fstring name1,name2;
175 char name_type = 0;
177 static BOOL already_got_session = False;
179 *name1 = *name2 = 0;
181 memset(outbuf,'\0',smb_size);
183 smb_setlen(outbuf,0);
185 switch (msg_type) {
186 case 0x81: /* session request */
188 if (already_got_session) {
189 exit_server("multiple session request not permitted");
192 SCVAL(outbuf,0,0x82);
193 SCVAL(outbuf,3,0);
194 if (name_len(inbuf+4) > 50 ||
195 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
196 DEBUG(0,("Invalid name length in session request\n"));
197 return(0);
199 name_extract(inbuf,4,name1);
200 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
201 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
202 name1,name2));
204 set_local_machine_name(name1, True);
205 set_remote_machine_name(name2, True);
207 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
208 get_local_machine_name(), get_remote_machine_name(),
209 name_type));
211 if (name_type == 'R') {
212 /* We are being asked for a pathworks session ---
213 no thanks! */
214 SCVAL(outbuf, 0,0x83);
215 break;
218 /* only add the client's machine name to the list
219 of possibly valid usernames if we are operating
220 in share mode security */
221 if (lp_security() == SEC_SHARE) {
222 add_session_user(get_remote_machine_name());
225 reload_services(True);
226 reopen_logs();
228 claim_connection(NULL,"",0,True,FLAG_MSG_GENERAL|FLAG_MSG_SMBD);
230 already_got_session = True;
231 break;
233 case 0x89: /* session keepalive request
234 (some old clients produce this?) */
235 SCVAL(outbuf,0,SMBkeepalive);
236 SCVAL(outbuf,3,0);
237 break;
239 case 0x82: /* positive session response */
240 case 0x83: /* negative session response */
241 case 0x84: /* retarget session response */
242 DEBUG(0,("Unexpected session response\n"));
243 break;
245 case SMBkeepalive: /* session keepalive */
246 default:
247 return(0);
250 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
251 msg_type, msg_flags));
253 return(outsize);
256 /****************************************************************************
257 Reply to a tcon.
258 ****************************************************************************/
260 int reply_tcon(connection_struct *conn,
261 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
263 const char *service;
264 pstring service_buf;
265 pstring password;
266 pstring dev;
267 int outsize = 0;
268 uint16 vuid = SVAL(inbuf,smb_uid);
269 int pwlen=0;
270 NTSTATUS nt_status;
271 char *p;
272 DATA_BLOB password_blob;
274 START_PROFILE(SMBtcon);
276 *service_buf = *password = *dev = 0;
278 p = smb_buf(inbuf)+1;
279 p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service_buf), STR_TERMINATE) + 1;
280 pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1;
281 p += pwlen;
282 p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1;
284 p = strrchr_m(service_buf,'\\');
285 if (p) {
286 service = p+1;
287 } else {
288 service = service_buf;
291 password_blob = data_blob(password, pwlen+1);
293 conn = make_connection(service,password_blob,dev,vuid,&nt_status);
295 data_blob_clear_free(&password_blob);
297 if (!conn) {
298 END_PROFILE(SMBtcon);
299 return ERROR_NT(nt_status);
302 outsize = set_message(outbuf,2,0,True);
303 SSVAL(outbuf,smb_vwv0,max_recv);
304 SSVAL(outbuf,smb_vwv1,conn->cnum);
305 SSVAL(outbuf,smb_tid,conn->cnum);
307 DEBUG(3,("tcon service=%s cnum=%d\n",
308 service, conn->cnum));
310 END_PROFILE(SMBtcon);
311 return(outsize);
314 /****************************************************************************
315 Reply to a tcon and X.
316 ****************************************************************************/
318 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
320 fstring service;
321 DATA_BLOB password;
323 /* what the cleint thinks the device is */
324 fstring client_devicetype;
325 /* what the server tells the client the share represents */
326 const char *server_devicetype;
327 NTSTATUS nt_status;
328 uint16 vuid = SVAL(inbuf,smb_uid);
329 int passlen = SVAL(inbuf,smb_vwv3);
330 pstring path;
331 char *p, *q;
332 extern BOOL global_encrypted_passwords_negotiated;
334 START_PROFILE(SMBtconX);
336 *service = *client_devicetype = 0;
338 /* we might have to close an old one */
339 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
340 close_cnum(conn,vuid);
343 if (passlen > MAX_PASS_LEN) {
344 return ERROR_DOS(ERRDOS,ERRbuftoosmall);
347 if (global_encrypted_passwords_negotiated) {
348 password = data_blob(smb_buf(inbuf),passlen);
349 } else {
350 password = data_blob(smb_buf(inbuf),passlen+1);
351 /* Ensure correct termination */
352 password.data[passlen]=0;
355 p = smb_buf(inbuf) + passlen;
356 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
359 * the service name can be either: \\server\share
360 * or share directly like on the DELL PowerVault 705
362 if (*path=='\\') {
363 q = strchr_m(path+2,'\\');
364 if (!q) {
365 END_PROFILE(SMBtconX);
366 return(ERROR_DOS(ERRDOS,ERRnosuchshare));
368 fstrcpy(service,q+1);
370 else
371 fstrcpy(service,path);
373 p += srvstr_pull(inbuf, client_devicetype, p, sizeof(client_devicetype), 6, STR_ASCII);
375 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
377 conn = make_connection(service,password,client_devicetype,vuid,&nt_status);
379 data_blob_clear_free(&password);
381 if (!conn) {
382 END_PROFILE(SMBtconX);
383 return ERROR_NT(nt_status);
386 if ( IS_IPC(conn) )
387 server_devicetype = "IPC";
388 else if ( IS_PRINT(conn) )
389 server_devicetype = "LPT1:";
390 else
391 server_devicetype = "A:";
393 if (Protocol < PROTOCOL_NT1) {
394 set_message(outbuf,2,0,True);
395 p = smb_buf(outbuf);
396 p += srvstr_push(outbuf, p, server_devicetype, -1,
397 STR_TERMINATE|STR_ASCII);
398 set_message_end(outbuf,p);
399 } else {
400 /* NT sets the fstype of IPC$ to the null string */
401 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
403 set_message(outbuf,3,0,True);
405 p = smb_buf(outbuf);
406 p += srvstr_push(outbuf, p, server_devicetype, -1,
407 STR_TERMINATE|STR_ASCII);
408 p += srvstr_push(outbuf, p, fstype, -1,
409 STR_TERMINATE);
411 set_message_end(outbuf,p);
413 /* what does setting this bit do? It is set by NT4 and
414 may affect the ability to autorun mounted cdroms */
415 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
416 (lp_csc_policy(SNUM(conn)) << 2));
418 init_dfsroot(conn, inbuf, outbuf);
422 DEBUG(3,("tconX service=%s \n",
423 service));
425 /* set the incoming and outgoing tid to the just created one */
426 SSVAL(inbuf,smb_tid,conn->cnum);
427 SSVAL(outbuf,smb_tid,conn->cnum);
429 END_PROFILE(SMBtconX);
430 return chain_reply(inbuf,outbuf,length,bufsize);
433 /****************************************************************************
434 Reply to an unknown type.
435 ****************************************************************************/
437 int reply_unknown(char *inbuf,char *outbuf)
439 int type;
440 type = CVAL(inbuf,smb_com);
442 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
443 smb_fn_name(type), type, type));
445 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
448 /****************************************************************************
449 Reply to an ioctl.
450 ****************************************************************************/
452 int reply_ioctl(connection_struct *conn,
453 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
455 uint16 device = SVAL(inbuf,smb_vwv1);
456 uint16 function = SVAL(inbuf,smb_vwv2);
457 uint32 ioctl_code = (device << 16) + function;
458 int replysize, outsize;
459 char *p;
460 START_PROFILE(SMBioctl);
462 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
464 switch (ioctl_code) {
465 case IOCTL_QUERY_JOB_INFO:
466 replysize = 32;
467 break;
468 default:
469 END_PROFILE(SMBioctl);
470 return(ERROR_DOS(ERRSRV,ERRnosupport));
473 outsize = set_message(outbuf,8,replysize+1,True);
474 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
475 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
476 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
477 p = smb_buf(outbuf) + 1; /* Allow for alignment */
479 switch (ioctl_code) {
480 case IOCTL_QUERY_JOB_INFO:
482 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
483 if (!fsp) {
484 END_PROFILE(SMBioctl);
485 return(UNIXERROR(ERRDOS,ERRbadfid));
487 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
488 srvstr_push(outbuf, p+2, global_myname(), 15, STR_TERMINATE|STR_ASCII);
489 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
490 break;
494 END_PROFILE(SMBioctl);
495 return outsize;
498 /****************************************************************************
499 Reply to a chkpth.
500 ****************************************************************************/
502 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
504 int outsize = 0;
505 int mode;
506 pstring name;
507 BOOL ok = False;
508 BOOL bad_path = False;
509 SMB_STRUCT_STAT sbuf;
510 NTSTATUS status;
512 START_PROFILE(SMBchkpth);
514 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
515 if (!NT_STATUS_IS_OK(status)) {
516 END_PROFILE(SMBchkpth);
517 return ERROR_NT(status);
520 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
522 unix_convert(name,conn,0,&bad_path,&sbuf);
524 mode = SVAL(inbuf,smb_vwv0);
526 if (check_name(name,conn)) {
527 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,name,&sbuf) == 0)
528 if (!(ok = S_ISDIR(sbuf.st_mode))) {
529 END_PROFILE(SMBchkpth);
530 return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath);
534 if (!ok) {
535 /* We special case this - as when a Windows machine
536 is parsing a path is steps through the components
537 one at a time - if a component fails it expects
538 ERRbadpath, not ERRbadfile.
540 if(errno == ENOENT) {
542 * Windows returns different error codes if
543 * the parent directory is valid but not the
544 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
545 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
546 * if the path is invalid.
548 if (bad_path) {
549 END_PROFILE(SMBchkpth);
550 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
551 } else {
552 END_PROFILE(SMBchkpth);
553 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
555 } else if (errno == ENOTDIR) {
556 END_PROFILE(SMBchkpth);
557 return ERROR_NT(NT_STATUS_NOT_A_DIRECTORY);
560 END_PROFILE(SMBchkpth);
561 return(UNIXERROR(ERRDOS,ERRbadpath));
564 outsize = set_message(outbuf,0,0,True);
566 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
568 END_PROFILE(SMBchkpth);
569 return(outsize);
572 /****************************************************************************
573 Reply to a getatr.
574 ****************************************************************************/
576 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
578 pstring fname;
579 int outsize = 0;
580 SMB_STRUCT_STAT sbuf;
581 BOOL ok = False;
582 int mode=0;
583 SMB_OFF_T size=0;
584 time_t mtime=0;
585 BOOL bad_path = False;
586 char *p;
587 NTSTATUS status;
589 START_PROFILE(SMBgetatr);
591 p = smb_buf(inbuf) + 1;
592 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
593 if (!NT_STATUS_IS_OK(status)) {
594 END_PROFILE(SMBgetatr);
595 return ERROR_NT(status);
598 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
600 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
601 under WfWg - weird! */
602 if (! (*fname)) {
603 mode = aHIDDEN | aDIR;
604 if (!CAN_WRITE(conn))
605 mode |= aRONLY;
606 size = 0;
607 mtime = 0;
608 ok = True;
609 } else {
610 unix_convert(fname,conn,0,&bad_path,&sbuf);
611 if (check_name(fname,conn)) {
612 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,fname,&sbuf) == 0) {
613 mode = dos_mode(conn,fname,&sbuf);
614 size = sbuf.st_size;
615 mtime = sbuf.st_mtime;
616 if (mode & aDIR)
617 size = 0;
618 ok = True;
619 } else {
620 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
625 if (!ok) {
626 END_PROFILE(SMBgetatr);
627 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadfile);
630 outsize = set_message(outbuf,10,0,True);
632 SSVAL(outbuf,smb_vwv0,mode);
633 if(lp_dos_filetime_resolution(SNUM(conn)) )
634 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
635 else
636 put_dos_date3(outbuf,smb_vwv1,mtime);
637 SIVAL(outbuf,smb_vwv3,(uint32)size);
639 if (Protocol >= PROTOCOL_NT1)
640 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
642 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
644 END_PROFILE(SMBgetatr);
645 return(outsize);
648 /****************************************************************************
649 Reply to a setatr.
650 ****************************************************************************/
652 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
654 pstring fname;
655 int outsize = 0;
656 BOOL ok=False;
657 int mode;
658 time_t mtime;
659 SMB_STRUCT_STAT sbuf;
660 BOOL bad_path = False;
661 char *p;
662 NTSTATUS status;
664 START_PROFILE(SMBsetatr);
666 p = smb_buf(inbuf) + 1;
667 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
668 if (!NT_STATUS_IS_OK(status)) {
669 END_PROFILE(SMBsetatr);
670 return ERROR_NT(status);
673 unix_convert(fname,conn,0,&bad_path,&sbuf);
675 mode = SVAL(inbuf,smb_vwv0);
676 mtime = make_unix_date3(inbuf+smb_vwv1);
678 if (mode != FILE_ATTRIBUTE_NORMAL) {
679 if (VALID_STAT_OF_DIR(sbuf))
680 mode |= aDIR;
681 else
682 mode &= ~aDIR;
684 if (check_name(fname,conn))
685 ok = (file_chmod(conn,fname,mode,NULL) == 0);
686 } else {
687 ok = True;
690 if (ok)
691 ok = set_filetime(conn,fname,mtime);
693 if (!ok) {
694 END_PROFILE(SMBsetatr);
695 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
698 outsize = set_message(outbuf,0,0,True);
700 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
702 END_PROFILE(SMBsetatr);
703 return(outsize);
706 /****************************************************************************
707 Reply to a dskattr.
708 ****************************************************************************/
710 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
712 int outsize = 0;
713 SMB_BIG_UINT dfree,dsize,bsize;
714 START_PROFILE(SMBdskattr);
716 SMB_VFS_DISK_FREE(conn,".",True,&bsize,&dfree,&dsize);
718 outsize = set_message(outbuf,5,0,True);
720 if (Protocol <= PROTOCOL_LANMAN2) {
721 double total_space, free_space;
722 /* we need to scale this to a number that DOS6 can handle. We
723 use floating point so we can handle large drives on systems
724 that don't have 64 bit integers
726 we end up displaying a maximum of 2G to DOS systems
728 total_space = dsize * (double)bsize;
729 free_space = dfree * (double)bsize;
731 dsize = (total_space+63*512) / (64*512);
732 dfree = (free_space+63*512) / (64*512);
734 if (dsize > 0xFFFF) dsize = 0xFFFF;
735 if (dfree > 0xFFFF) dfree = 0xFFFF;
737 SSVAL(outbuf,smb_vwv0,dsize);
738 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
739 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
740 SSVAL(outbuf,smb_vwv3,dfree);
741 } else {
742 SSVAL(outbuf,smb_vwv0,dsize);
743 SSVAL(outbuf,smb_vwv1,bsize/512);
744 SSVAL(outbuf,smb_vwv2,512);
745 SSVAL(outbuf,smb_vwv3,dfree);
748 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
750 END_PROFILE(SMBdskattr);
751 return(outsize);
754 /****************************************************************************
755 Reply to a search.
756 Can be called from SMBsearch, SMBffirst or SMBfunique.
757 ****************************************************************************/
759 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
761 pstring mask;
762 pstring directory;
763 pstring fname;
764 SMB_OFF_T size;
765 int mode;
766 time_t date;
767 int dirtype;
768 int outsize = 0;
769 unsigned int numentries = 0;
770 unsigned int maxentries = 0;
771 BOOL finished = False;
772 char *p;
773 BOOL ok = False;
774 int status_len;
775 pstring path;
776 char status[21];
777 int dptr_num= -1;
778 BOOL check_descend = False;
779 BOOL expect_close = False;
780 BOOL can_open = True;
781 BOOL bad_path = False;
782 NTSTATUS nt_status;
783 START_PROFILE(SMBsearch);
785 *mask = *directory = *fname = 0;
787 /* If we were called as SMBffirst then we must expect close. */
788 if(CVAL(inbuf,smb_com) == SMBffirst)
789 expect_close = True;
791 outsize = set_message(outbuf,1,3,True);
792 maxentries = SVAL(inbuf,smb_vwv0);
793 dirtype = SVAL(inbuf,smb_vwv1);
794 p = smb_buf(inbuf) + 1;
795 p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &nt_status);
796 if (!NT_STATUS_IS_OK(nt_status)) {
797 END_PROFILE(SMBsearch);
798 return ERROR_NT(nt_status);
800 p++;
801 status_len = SVAL(p, 0);
802 p += 2;
804 /* dirtype &= ~aDIR; */
806 if (status_len == 0) {
807 SMB_STRUCT_STAT sbuf;
808 pstring dir2;
810 pstrcpy(directory,path);
811 pstrcpy(dir2,path);
812 unix_convert(directory,conn,0,&bad_path,&sbuf);
813 unix_format(dir2);
815 if (!check_name(directory,conn))
816 can_open = False;
818 p = strrchr_m(dir2,'/');
819 if (p == NULL) {
820 pstrcpy(mask,dir2);
821 *dir2 = 0;
822 } else {
823 *p = 0;
824 pstrcpy(mask,p+1);
827 p = strrchr_m(directory,'/');
828 if (!p)
829 *directory = 0;
830 else
831 *p = 0;
833 if (strlen(directory) == 0)
834 pstrcpy(directory,".");
835 memset((char *)status,'\0',21);
836 SCVAL(status,0,(dirtype & 0x1F));
837 } else {
838 int status_dirtype;
840 memcpy(status,p,21);
841 status_dirtype = CVAL(status,0) & 0x1F;
842 if (status_dirtype != (dirtype & 0x1F))
843 dirtype = status_dirtype;
845 conn->dirptr = dptr_fetch(status+12,&dptr_num);
846 if (!conn->dirptr)
847 goto SearchEmpty;
848 string_set(&conn->dirpath,dptr_path(dptr_num));
849 pstrcpy(mask, dptr_wcard(dptr_num));
852 if (can_open) {
853 p = smb_buf(outbuf) + 3;
854 ok = True;
856 if (status_len == 0) {
857 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
858 if (dptr_num < 0) {
859 if(dptr_num == -2) {
860 END_PROFILE(SMBsearch);
861 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnofids);
863 END_PROFILE(SMBsearch);
864 return ERROR_DOS(ERRDOS,ERRnofids);
866 dptr_set_wcard(dptr_num, strdup(mask));
867 dptr_set_attr(dptr_num, dirtype);
868 } else {
869 dirtype = dptr_attr(dptr_num);
872 DEBUG(4,("dptr_num is %d\n",dptr_num));
874 if (ok) {
875 if ((dirtype&0x1F) == aVOLID) {
876 memcpy(p,status,21);
877 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
878 dptr_fill(p+12,dptr_num);
879 if (dptr_zero(p+12) && (status_len==0))
880 numentries = 1;
881 else
882 numentries = 0;
883 p += DIR_STRUCT_SIZE;
884 } else {
885 unsigned int i;
886 maxentries = MIN(maxentries, ((BUFFER_SIZE - (p - outbuf))/DIR_STRUCT_SIZE));
888 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
889 conn->dirpath,lp_dontdescend(SNUM(conn))));
890 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
891 check_descend = True;
893 for (i=numentries;(i<maxentries) && !finished;i++) {
894 finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
895 if (!finished) {
896 memcpy(p,status,21);
897 make_dir_struct(p,mask,fname,size,mode,date);
898 dptr_fill(p+12,dptr_num);
899 numentries++;
901 p += DIR_STRUCT_SIZE;
904 } /* if (ok ) */
908 SearchEmpty:
910 /* If we were called as SMBffirst with smb_search_id == NULL
911 and no entries were found then return error and close dirptr
912 (X/Open spec) */
914 if(ok && expect_close && numentries == 0 && status_len == 0) {
915 if (Protocol < PROTOCOL_NT1) {
916 SCVAL(outbuf,smb_rcls,ERRDOS);
917 SSVAL(outbuf,smb_err,ERRnofiles);
919 /* Also close the dptr - we know it's gone */
920 dptr_close(&dptr_num);
921 } else if (numentries == 0 || !ok) {
922 if (Protocol < PROTOCOL_NT1) {
923 SCVAL(outbuf,smb_rcls,ERRDOS);
924 SSVAL(outbuf,smb_err,ERRnofiles);
926 dptr_close(&dptr_num);
929 /* If we were called as SMBfunique, then we can close the dirptr now ! */
930 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
931 dptr_close(&dptr_num);
933 SSVAL(outbuf,smb_vwv0,numentries);
934 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
935 SCVAL(smb_buf(outbuf),0,5);
936 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
938 if (Protocol >= PROTOCOL_NT1)
939 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
941 outsize += DIR_STRUCT_SIZE*numentries;
942 smb_setlen(outbuf,outsize - 4);
944 if ((! *directory) && dptr_path(dptr_num))
945 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
947 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
948 smb_fn_name(CVAL(inbuf,smb_com)),
949 mask, directory, dirtype, numentries, maxentries ) );
951 END_PROFILE(SMBsearch);
952 return(outsize);
955 /****************************************************************************
956 Reply to a fclose (stop directory search).
957 ****************************************************************************/
959 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
961 int outsize = 0;
962 int status_len;
963 pstring path;
964 char status[21];
965 int dptr_num= -2;
966 char *p;
967 NTSTATUS err;
969 START_PROFILE(SMBfclose);
971 outsize = set_message(outbuf,1,0,True);
972 p = smb_buf(inbuf) + 1;
973 p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err);
974 if (!NT_STATUS_IS_OK(err)) {
975 END_PROFILE(SMBfclose);
976 return ERROR_NT(err);
978 p++;
979 status_len = SVAL(p,0);
980 p += 2;
982 if (status_len == 0) {
983 END_PROFILE(SMBfclose);
984 return ERROR_DOS(ERRSRV,ERRsrverror);
987 memcpy(status,p,21);
989 if(dptr_fetch(status+12,&dptr_num)) {
990 /* Close the dptr - we know it's gone */
991 dptr_close(&dptr_num);
994 SSVAL(outbuf,smb_vwv0,0);
996 DEBUG(3,("search close\n"));
998 END_PROFILE(SMBfclose);
999 return(outsize);
1002 /****************************************************************************
1003 Reply to an open.
1004 ****************************************************************************/
1006 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1008 pstring fname;
1009 int outsize = 0;
1010 int fmode=0;
1011 int share_mode;
1012 SMB_OFF_T size = 0;
1013 time_t mtime=0;
1014 mode_t unixmode;
1015 int rmode=0;
1016 SMB_STRUCT_STAT sbuf;
1017 BOOL bad_path = False;
1018 files_struct *fsp;
1019 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1020 NTSTATUS status;
1021 START_PROFILE(SMBopen);
1023 share_mode = SVAL(inbuf,smb_vwv0);
1025 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
1026 if (!NT_STATUS_IS_OK(status)) {
1027 END_PROFILE(SMBopen);
1028 return ERROR_NT(status);
1031 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1033 unix_convert(fname,conn,0,&bad_path,&sbuf);
1035 unixmode = unix_mode(conn,aARCH,fname);
1037 fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1038 unixmode, oplock_request,&rmode,NULL);
1040 if (!fsp) {
1041 END_PROFILE(SMBopen);
1042 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1045 size = sbuf.st_size;
1046 fmode = dos_mode(conn,fname,&sbuf);
1047 mtime = sbuf.st_mtime;
1049 if (fmode & aDIR) {
1050 DEBUG(3,("attempt to open a directory %s\n",fname));
1051 close_file(fsp,False);
1052 END_PROFILE(SMBopen);
1053 return ERROR_DOS(ERRDOS,ERRnoaccess);
1056 outsize = set_message(outbuf,7,0,True);
1057 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1058 SSVAL(outbuf,smb_vwv1,fmode);
1059 if(lp_dos_filetime_resolution(SNUM(conn)) )
1060 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1061 else
1062 put_dos_date3(outbuf,smb_vwv2,mtime);
1063 SIVAL(outbuf,smb_vwv4,(uint32)size);
1064 SSVAL(outbuf,smb_vwv6,rmode);
1066 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1067 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1069 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1070 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1071 END_PROFILE(SMBopen);
1072 return(outsize);
1075 /****************************************************************************
1076 Reply to an open and X.
1077 ****************************************************************************/
1079 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1081 pstring fname;
1082 int smb_mode = SVAL(inbuf,smb_vwv3);
1083 int smb_attr = SVAL(inbuf,smb_vwv5);
1084 /* Breakout the oplock request bits so we can set the
1085 reply bits separately. */
1086 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1087 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1088 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1089 #if 0
1090 int open_flags = SVAL(inbuf,smb_vwv2);
1091 int smb_sattr = SVAL(inbuf,smb_vwv4);
1092 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1093 #endif
1094 int smb_ofun = SVAL(inbuf,smb_vwv8);
1095 mode_t unixmode;
1096 SMB_OFF_T size=0;
1097 int fmode=0,mtime=0,rmode=0;
1098 SMB_STRUCT_STAT sbuf;
1099 int smb_action = 0;
1100 BOOL bad_path = False;
1101 files_struct *fsp;
1102 NTSTATUS status;
1103 START_PROFILE(SMBopenX);
1105 /* If it's an IPC, pass off the pipe handler. */
1106 if (IS_IPC(conn)) {
1107 if (lp_nt_pipe_support()) {
1108 END_PROFILE(SMBopenX);
1109 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1110 } else {
1111 END_PROFILE(SMBopenX);
1112 return ERROR_DOS(ERRSRV,ERRaccess);
1116 /* XXXX we need to handle passed times, sattr and flags */
1117 srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status);
1118 if (!NT_STATUS_IS_OK(status)) {
1119 END_PROFILE(SMBopenX);
1120 return ERROR_NT(status);
1123 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1125 unix_convert(fname,conn,0,&bad_path,&sbuf);
1127 unixmode = unix_mode(conn,smb_attr | aARCH, fname);
1129 fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,unixmode,
1130 oplock_request, &rmode,&smb_action);
1132 if (!fsp) {
1133 END_PROFILE(SMBopenX);
1134 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1137 size = sbuf.st_size;
1138 fmode = dos_mode(conn,fname,&sbuf);
1139 mtime = sbuf.st_mtime;
1140 if (fmode & aDIR) {
1141 close_file(fsp,False);
1142 END_PROFILE(SMBopenX);
1143 return ERROR_DOS(ERRDOS,ERRnoaccess);
1146 /* If the caller set the extended oplock request bit
1147 and we granted one (by whatever means) - set the
1148 correct bit for extended oplock reply.
1151 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn)))
1152 smb_action |= EXTENDED_OPLOCK_GRANTED;
1154 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1155 smb_action |= EXTENDED_OPLOCK_GRANTED;
1157 /* If the caller set the core oplock request bit
1158 and we granted one (by whatever means) - set the
1159 correct bit for core oplock reply.
1162 if (core_oplock_request && lp_fake_oplocks(SNUM(conn)))
1163 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1165 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1166 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1168 set_message(outbuf,15,0,True);
1169 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1170 SSVAL(outbuf,smb_vwv3,fmode);
1171 if(lp_dos_filetime_resolution(SNUM(conn)) )
1172 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1173 else
1174 put_dos_date3(outbuf,smb_vwv4,mtime);
1175 SIVAL(outbuf,smb_vwv6,(uint32)size);
1176 SSVAL(outbuf,smb_vwv8,rmode);
1177 SSVAL(outbuf,smb_vwv11,smb_action);
1179 END_PROFILE(SMBopenX);
1180 return chain_reply(inbuf,outbuf,length,bufsize);
1183 /****************************************************************************
1184 Reply to a SMBulogoffX.
1185 ****************************************************************************/
1187 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1189 uint16 vuid = SVAL(inbuf,smb_uid);
1190 user_struct *vuser = get_valid_user_struct(vuid);
1191 START_PROFILE(SMBulogoffX);
1193 if(vuser == 0)
1194 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1196 /* in user level security we are supposed to close any files
1197 open by this user */
1198 if ((vuser != 0) && (lp_security() != SEC_SHARE))
1199 file_close_user(vuid);
1201 invalidate_vuid(vuid);
1203 set_message(outbuf,2,0,True);
1205 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1207 END_PROFILE(SMBulogoffX);
1208 return chain_reply(inbuf,outbuf,length,bufsize);
1211 /****************************************************************************
1212 Reply to a mknew or a create.
1213 ****************************************************************************/
1215 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1217 pstring fname;
1218 int com;
1219 int outsize = 0;
1220 int createmode;
1221 mode_t unixmode;
1222 int ofun = 0;
1223 BOOL bad_path = False;
1224 files_struct *fsp;
1225 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1226 SMB_STRUCT_STAT sbuf;
1227 NTSTATUS status;
1228 START_PROFILE(SMBcreate);
1230 com = SVAL(inbuf,smb_com);
1232 createmode = SVAL(inbuf,smb_vwv0);
1233 srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status);
1234 if (!NT_STATUS_IS_OK(status)) {
1235 END_PROFILE(SMBcreate);
1236 return ERROR_NT(status);
1239 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1241 unix_convert(fname,conn,0,&bad_path,&sbuf);
1243 if (createmode & aVOLID)
1244 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1246 unixmode = unix_mode(conn,createmode,fname);
1248 if(com == SMBmknew) {
1249 /* We should fail if file exists. */
1250 ofun = FILE_CREATE_IF_NOT_EXIST;
1251 } else {
1252 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1253 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1256 /* Open file in dos compatibility share mode. */
1257 fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1258 ofun, unixmode, oplock_request, NULL, NULL);
1260 if (!fsp) {
1261 END_PROFILE(SMBcreate);
1262 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1265 outsize = set_message(outbuf,1,0,True);
1266 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1268 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1269 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1271 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1272 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1274 DEBUG( 2, ( "new file %s\n", fname ) );
1275 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n", fname, fsp->fd, createmode, (int)unixmode ) );
1277 END_PROFILE(SMBcreate);
1278 return(outsize);
1281 /****************************************************************************
1282 Reply to a create temporary file.
1283 ****************************************************************************/
1285 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1287 pstring fname;
1288 int outsize = 0;
1289 int createmode;
1290 mode_t unixmode;
1291 BOOL bad_path = False;
1292 files_struct *fsp;
1293 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1294 int tmpfd;
1295 SMB_STRUCT_STAT sbuf;
1296 char *p, *s;
1297 NTSTATUS status;
1299 START_PROFILE(SMBctemp);
1301 createmode = SVAL(inbuf,smb_vwv0);
1302 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
1303 if (!NT_STATUS_IS_OK(status)) {
1304 END_PROFILE(SMBctemp);
1305 return ERROR_NT(status);
1307 pstrcat(fname,"\\TMXXXXXX");
1309 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1311 unix_convert(fname,conn,0,&bad_path,&sbuf);
1313 unixmode = unix_mode(conn,createmode,fname);
1315 tmpfd = smb_mkstemp(fname);
1316 if (tmpfd == -1) {
1317 END_PROFILE(SMBctemp);
1318 return(UNIXERROR(ERRDOS,ERRnoaccess));
1321 SMB_VFS_STAT(conn,fname,&sbuf);
1323 /* Open file in dos compatibility share mode. */
1324 /* We should fail if file does not exist. */
1325 fsp = open_file_shared(conn,fname,&sbuf,
1326 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1327 FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
1328 unixmode, oplock_request, NULL, NULL);
1330 /* close fd from smb_mkstemp() */
1331 close(tmpfd);
1333 if (!fsp) {
1334 END_PROFILE(SMBctemp);
1335 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1338 outsize = set_message(outbuf,1,0,True);
1339 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1341 /* the returned filename is relative to the directory */
1342 s = strrchr_m(fname, '/');
1343 if (!s)
1344 s = fname;
1345 else
1346 s++;
1348 p = smb_buf(outbuf);
1349 SSVALS(p, 0, -1); /* what is this? not in spec */
1350 SSVAL(p, 2, strlen(s));
1351 p += 4;
1352 p += srvstr_push(outbuf, p, s, -1, STR_ASCII);
1353 outsize = set_message_end(outbuf, p);
1355 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1356 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1358 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1359 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1361 DEBUG( 2, ( "created temp file %s\n", fname ) );
1362 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1363 fname, fsp->fd, createmode, (int)unixmode ) );
1365 END_PROFILE(SMBctemp);
1366 return(outsize);
1369 /*******************************************************************
1370 Check if a user is allowed to rename a file.
1371 ********************************************************************/
1373 static NTSTATUS can_rename(char *fname,connection_struct *conn, SMB_STRUCT_STAT *pst)
1375 int smb_action;
1376 int access_mode;
1377 files_struct *fsp;
1379 if (!CAN_WRITE(conn))
1380 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1382 if (S_ISDIR(pst->st_mode))
1383 return NT_STATUS_OK;
1385 /* We need a better way to return NT status codes from open... */
1386 unix_ERR_class = 0;
1387 unix_ERR_code = 0;
1389 fsp = open_file_shared1(conn, fname, pst, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1390 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
1392 if (!fsp) {
1393 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1394 if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1395 ret = NT_STATUS_SHARING_VIOLATION;
1396 unix_ERR_class = 0;
1397 unix_ERR_code = 0;
1398 unix_ERR_ntstatus = NT_STATUS_OK;
1399 return ret;
1401 close_file(fsp,False);
1402 return NT_STATUS_OK;
1405 /*******************************************************************
1406 Check if a user is allowed to delete a file.
1407 ********************************************************************/
1409 static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype, BOOL bad_path)
1411 SMB_STRUCT_STAT sbuf;
1412 int fmode;
1413 int smb_action;
1414 int access_mode;
1415 files_struct *fsp;
1417 DEBUG(10,("can_delete: %s, dirtype = %d\n",
1418 fname, dirtype ));
1420 if (!CAN_WRITE(conn))
1421 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1423 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
1424 if(errno == ENOENT) {
1425 if (bad_path)
1426 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1427 else
1428 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1430 return map_nt_error_from_unix(errno);
1433 fmode = dos_mode(conn,fname,&sbuf);
1435 /* Can't delete a directory. */
1436 if (fmode & aDIR)
1437 return NT_STATUS_FILE_IS_A_DIRECTORY;
1438 #if 0 /* JRATEST */
1439 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
1440 return NT_STATUS_OBJECT_NAME_INVALID;
1441 #endif /* JRATEST */
1443 if (!lp_delete_readonly(SNUM(conn))) {
1444 if (fmode & aRONLY)
1445 return NT_STATUS_CANNOT_DELETE;
1447 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1448 return NT_STATUS_NO_SUCH_FILE;
1450 /* We need a better way to return NT status codes from open... */
1451 unix_ERR_class = 0;
1452 unix_ERR_code = 0;
1454 fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1455 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
1457 if (!fsp) {
1458 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1459 if (!NT_STATUS_IS_OK(unix_ERR_ntstatus))
1460 ret = unix_ERR_ntstatus;
1461 else if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1462 ret = NT_STATUS_SHARING_VIOLATION;
1463 unix_ERR_class = 0;
1464 unix_ERR_code = 0;
1465 unix_ERR_ntstatus = NT_STATUS_OK;
1466 return ret;
1468 close_file(fsp,False);
1469 return NT_STATUS_OK;
1472 /****************************************************************************
1473 The guts of the unlink command, split out so it may be called by the NT SMB
1474 code.
1475 ****************************************************************************/
1477 NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
1479 pstring directory;
1480 pstring mask;
1481 char *p;
1482 int count=0;
1483 NTSTATUS error = NT_STATUS_OK;
1484 BOOL has_wild;
1485 BOOL bad_path = False;
1486 BOOL rc = True;
1487 SMB_STRUCT_STAT sbuf;
1489 *directory = *mask = 0;
1491 /* We must check for wildcards in the name given
1492 * directly by the client - before any unmangling.
1493 * This prevents an unmangling of a UNIX name containing
1494 * a DOS wildcard like '*' or '?' from unmangling into
1495 * a wildcard delete which was not intended.
1496 * FIX for #226. JRA.
1499 has_wild = ms_has_wild(name);
1501 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1503 p = strrchr_m(name,'/');
1504 if (!p) {
1505 pstrcpy(directory,".");
1506 pstrcpy(mask,name);
1507 } else {
1508 *p = 0;
1509 pstrcpy(directory,name);
1510 pstrcpy(mask,p+1);
1514 * We should only check the mangled cache
1515 * here if unix_convert failed. This means
1516 * that the path in 'mask' doesn't exist
1517 * on the file system and so we need to look
1518 * for a possible mangle. This patch from
1519 * Tine Smukavec <valentin.smukavec@hermes.si>.
1522 if (!rc && mangle_is_mangled(mask))
1523 mangle_check_cache( mask );
1525 if (!has_wild) {
1526 pstrcat(directory,"/");
1527 pstrcat(directory,mask);
1528 error = can_delete(directory,conn,dirtype,bad_path);
1529 if (!NT_STATUS_IS_OK(error))
1530 return error;
1532 if (SMB_VFS_UNLINK(conn,directory) == 0) {
1533 count++;
1535 } else {
1536 void *dirptr = NULL;
1537 const char *dname;
1539 if (check_name(directory,conn))
1540 dirptr = OpenDir(conn, directory, True);
1542 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1543 the pattern matches against the long name, otherwise the short name
1544 We don't implement this yet XXXX
1547 if (dirptr) {
1548 error = NT_STATUS_NO_SUCH_FILE;
1550 if (strequal(mask,"????????.???"))
1551 pstrcpy(mask,"*");
1553 while ((dname = ReadDirName(dirptr))) {
1554 pstring fname;
1555 BOOL sys_direntry = False;
1556 pstrcpy(fname,dname);
1558 /* Quick check for "." and ".." */
1559 if (fname[0] == '.') {
1560 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
1561 if ((dirtype & aDIR)) {
1562 sys_direntry = True;
1563 } else {
1564 continue;
1569 if(!mask_match(fname, mask, case_sensitive))
1570 continue;
1572 if (sys_direntry) {
1573 error = NT_STATUS_OBJECT_NAME_INVALID;
1574 continue;
1577 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1578 error = can_delete(fname,conn,dirtype,bad_path);
1579 if (!NT_STATUS_IS_OK(error))
1580 continue;
1581 if (SMB_VFS_UNLINK(conn,fname) == 0)
1582 count++;
1583 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
1585 CloseDir(dirptr);
1589 if (count == 0 && NT_STATUS_IS_OK(error)) {
1590 error = map_nt_error_from_unix(errno);
1593 return error;
1596 /****************************************************************************
1597 Reply to a unlink
1598 ****************************************************************************/
1600 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
1601 int dum_buffsize)
1603 int outsize = 0;
1604 pstring name;
1605 int dirtype;
1606 NTSTATUS status;
1607 START_PROFILE(SMBunlink);
1609 dirtype = SVAL(inbuf,smb_vwv0);
1611 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
1612 if (!NT_STATUS_IS_OK(status)) {
1613 END_PROFILE(SMBunlink);
1614 return ERROR_NT(status);
1617 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1619 DEBUG(3,("reply_unlink : %s\n",name));
1621 status = unlink_internals(conn, dirtype, name);
1622 if (!NT_STATUS_IS_OK(status))
1623 return ERROR_NT(status);
1626 * Win2k needs a changenotify request response before it will
1627 * update after a rename..
1629 process_pending_change_notify_queue((time_t)0);
1631 outsize = set_message(outbuf,0,0,True);
1633 END_PROFILE(SMBunlink);
1634 return outsize;
1637 /****************************************************************************
1638 Fail for readbraw.
1639 ****************************************************************************/
1641 void fail_readraw(void)
1643 pstring errstr;
1644 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
1645 strerror(errno) );
1646 exit_server(errstr);
1649 /****************************************************************************
1650 Use sendfile in readbraw.
1651 ****************************************************************************/
1653 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
1654 ssize_t mincount, char *outbuf)
1656 ssize_t ret=0;
1658 #if defined(WITH_SENDFILE)
1660 * We can only use sendfile on a non-chained packet and on a file
1661 * that is exclusively oplocked. reply_readbraw has already checked the length.
1664 if ((nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) &&
1665 EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && lp_use_sendfile(SNUM(conn)) ) {
1666 DATA_BLOB header;
1668 _smb_setlen(outbuf,nread);
1669 header.data = outbuf;
1670 header.length = 4;
1671 header.free = NULL;
1673 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) {
1675 * Special hack for broken Linux with no 64 bit clean sendfile. If we
1676 * return ENOSYS then pretend we just got a normal read.
1678 if (errno == ENOSYS)
1679 goto normal_read;
1681 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
1682 fsp->fsp_name, strerror(errno) ));
1683 exit_server("send_file_readbraw sendfile failed");
1688 normal_read:
1689 #endif
1691 if (nread > 0) {
1692 ret = read_file(fsp,outbuf+4,startpos,nread);
1693 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1694 if (ret < mincount)
1695 ret = 0;
1696 #else
1697 if (ret < nread)
1698 ret = 0;
1699 #endif
1702 _smb_setlen(outbuf,ret);
1703 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
1704 fail_readraw();
1707 /****************************************************************************
1708 Reply to a readbraw (core+ protocol).
1709 ****************************************************************************/
1711 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
1713 extern struct current_user current_user;
1714 ssize_t maxcount,mincount;
1715 size_t nread = 0;
1716 SMB_OFF_T startpos;
1717 char *header = outbuf;
1718 files_struct *fsp;
1719 START_PROFILE(SMBreadbraw);
1721 if (srv_is_signing_active()) {
1722 exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
1726 * Special check if an oplock break has been issued
1727 * and the readraw request croses on the wire, we must
1728 * return a zero length response here.
1731 if(global_oplock_break) {
1732 _smb_setlen(header,0);
1733 if (write_data(smbd_server_fd(),header,4) != 4)
1734 fail_readraw();
1735 DEBUG(5,("readbraw - oplock break finished\n"));
1736 END_PROFILE(SMBreadbraw);
1737 return -1;
1740 fsp = file_fsp(inbuf,smb_vwv0);
1742 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1744 * fsp could be NULL here so use the value from the packet. JRA.
1746 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
1747 _smb_setlen(header,0);
1748 if (write_data(smbd_server_fd(),header,4) != 4)
1749 fail_readraw();
1750 END_PROFILE(SMBreadbraw);
1751 return(-1);
1754 CHECK_FSP(fsp,conn);
1756 flush_write_cache(fsp, READRAW_FLUSH);
1758 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
1759 if(CVAL(inbuf,smb_wct) == 10) {
1761 * This is a large offset (64 bit) read.
1763 #ifdef LARGE_SMB_OFF_T
1765 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
1767 #else /* !LARGE_SMB_OFF_T */
1770 * Ensure we haven't been sent a >32 bit offset.
1773 if(IVAL(inbuf,smb_vwv8) != 0) {
1774 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
1775 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
1776 _smb_setlen(header,0);
1777 if (write_data(smbd_server_fd(),header,4) != 4)
1778 fail_readraw();
1779 END_PROFILE(SMBreadbraw);
1780 return(-1);
1783 #endif /* LARGE_SMB_OFF_T */
1785 if(startpos < 0) {
1786 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
1787 _smb_setlen(header,0);
1788 if (write_data(smbd_server_fd(),header,4) != 4)
1789 fail_readraw();
1790 END_PROFILE(SMBreadbraw);
1791 return(-1);
1794 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
1795 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
1797 /* ensure we don't overrun the packet size */
1798 maxcount = MIN(65535,maxcount);
1800 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1801 SMB_OFF_T size = fsp->size;
1802 SMB_OFF_T sizeneeded = startpos + maxcount;
1804 if (size < sizeneeded) {
1805 SMB_STRUCT_STAT st;
1806 if (SMB_VFS_FSTAT(fsp,fsp->fd,&st) == 0)
1807 size = st.st_size;
1808 if (!fsp->can_write)
1809 fsp->size = size;
1812 if (startpos >= size)
1813 nread = 0;
1814 else
1815 nread = MIN(maxcount,(size - startpos));
1818 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1819 if (nread < mincount)
1820 nread = 0;
1821 #endif
1823 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
1824 (int)maxcount, (int)mincount, (int)nread ) );
1826 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf);
1828 DEBUG(5,("readbraw finished\n"));
1829 END_PROFILE(SMBreadbraw);
1830 return -1;
1833 /****************************************************************************
1834 Reply to a lockread (core+ protocol).
1835 ****************************************************************************/
1837 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
1839 ssize_t nread = -1;
1840 char *data;
1841 int outsize = 0;
1842 SMB_OFF_T startpos;
1843 size_t numtoread;
1844 NTSTATUS status;
1845 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1846 BOOL my_lock_ctx = False;
1847 START_PROFILE(SMBlockread);
1849 CHECK_FSP(fsp,conn);
1850 CHECK_READ(fsp);
1852 release_level_2_oplocks_on_change(fsp);
1854 numtoread = SVAL(inbuf,smb_vwv1);
1855 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
1857 outsize = set_message(outbuf,5,3,True);
1858 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1859 data = smb_buf(outbuf) + 3;
1862 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
1863 * protocol request that predates the read/write lock concept.
1864 * Thus instead of asking for a read lock here we need to ask
1865 * for a write lock. JRA.
1866 * Note that the requested lock size is unaffected by max_recv.
1869 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid),
1870 (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, &my_lock_ctx);
1872 if (NT_STATUS_V(status)) {
1873 #if 0
1875 * We used to make lockread a blocking lock. It turns out
1876 * that this isn't on W2k. Found by the Samba 4 RAW-READ torture
1877 * tester. JRA.
1880 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
1882 * A blocking lock was requested. Package up
1883 * this smb into a queued request and push it
1884 * onto the blocking lock queue.
1886 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)startpos,
1887 (SMB_BIG_UINT)numtoread)) {
1888 END_PROFILE(SMBlockread);
1889 return -1;
1892 #endif
1893 END_PROFILE(SMBlockread);
1894 return ERROR_NT(status);
1898 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
1901 if (numtoread > max_recv) {
1902 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
1903 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
1904 (unsigned int)numtoread, (unsigned int)max_recv ));
1905 numtoread = MIN(numtoread,max_recv);
1907 nread = read_file(fsp,data,startpos,numtoread);
1909 if (nread < 0) {
1910 END_PROFILE(SMBlockread);
1911 return(UNIXERROR(ERRDOS,ERRnoaccess));
1914 outsize += nread;
1915 SSVAL(outbuf,smb_vwv0,nread);
1916 SSVAL(outbuf,smb_vwv5,nread+3);
1917 SSVAL(smb_buf(outbuf),1,nread);
1919 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
1920 fsp->fnum, (int)numtoread, (int)nread));
1922 END_PROFILE(SMBlockread);
1923 return(outsize);
1926 /****************************************************************************
1927 Reply to a read.
1928 ****************************************************************************/
1930 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
1932 size_t numtoread;
1933 ssize_t nread = 0;
1934 char *data;
1935 SMB_OFF_T startpos;
1936 int outsize = 0;
1937 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1938 START_PROFILE(SMBread);
1940 CHECK_FSP(fsp,conn);
1941 CHECK_READ(fsp);
1943 numtoread = SVAL(inbuf,smb_vwv1);
1944 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
1946 outsize = set_message(outbuf,5,3,True);
1947 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1949 * The requested read size cannot be greater than max_recv. JRA.
1951 if (numtoread > max_recv) {
1952 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
1953 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
1954 (unsigned int)numtoread, (unsigned int)max_recv ));
1955 numtoread = MIN(numtoread,max_recv);
1958 data = smb_buf(outbuf) + 3;
1960 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1961 END_PROFILE(SMBread);
1962 return ERROR_DOS(ERRDOS,ERRlock);
1965 if (numtoread > 0)
1966 nread = read_file(fsp,data,startpos,numtoread);
1968 if (nread < 0) {
1969 END_PROFILE(SMBread);
1970 return(UNIXERROR(ERRDOS,ERRnoaccess));
1973 outsize += nread;
1974 SSVAL(outbuf,smb_vwv0,nread);
1975 SSVAL(outbuf,smb_vwv5,nread+3);
1976 SCVAL(smb_buf(outbuf),0,1);
1977 SSVAL(smb_buf(outbuf),1,nread);
1979 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
1980 fsp->fnum, (int)numtoread, (int)nread ) );
1982 END_PROFILE(SMBread);
1983 return(outsize);
1986 /****************************************************************************
1987 Reply to a read and X - possibly using sendfile.
1988 ****************************************************************************/
1990 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length,
1991 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
1993 ssize_t nread = -1;
1994 char *data = smb_buf(outbuf);
1996 #if defined(WITH_SENDFILE)
1998 * We can only use sendfile on a non-chained packet and on a file
1999 * that is exclusively oplocked.
2002 if ((CVAL(inbuf,smb_vwv0) == 0xFF) && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) &&
2003 lp_use_sendfile(SNUM(conn)) && (lp_write_cache_size(SNUM(conn)) == 0) ) {
2004 SMB_STRUCT_STAT sbuf;
2005 DATA_BLOB header;
2007 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1)
2008 return(UNIXERROR(ERRDOS,ERRnoaccess));
2010 if (startpos > sbuf.st_size)
2011 goto normal_read;
2013 if (smb_maxcnt > (sbuf.st_size - startpos))
2014 smb_maxcnt = (sbuf.st_size - startpos);
2016 if (smb_maxcnt == 0)
2017 goto normal_read;
2020 * Set up the packet header before send. We
2021 * assume here the sendfile will work (get the
2022 * correct amount of data).
2025 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2026 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
2027 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2028 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
2029 SCVAL(outbuf,smb_vwv0,0xFF);
2030 set_message(outbuf,12,smb_maxcnt,False);
2031 header.data = outbuf;
2032 header.length = data - outbuf;
2033 header.free = NULL;
2035 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt) == -1) {
2037 * Special hack for broken Linux with no 64 bit clean sendfile. If we
2038 * return ENOSYS then pretend we just got a normal read.
2040 if (errno == ENOSYS)
2041 goto normal_read;
2043 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2044 fsp->fsp_name, strerror(errno) ));
2045 exit_server("send_file_readX sendfile failed");
2048 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2049 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2050 return -1;
2053 normal_read:
2055 #endif
2057 nread = read_file(fsp,data,startpos,smb_maxcnt);
2059 if (nread < 0) {
2060 END_PROFILE(SMBreadX);
2061 return(UNIXERROR(ERRDOS,ERRnoaccess));
2064 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2065 SSVAL(outbuf,smb_vwv5,nread);
2066 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2067 SSVAL(smb_buf(outbuf),-2,nread);
2069 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2070 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2072 return nread;
2075 /****************************************************************************
2076 Reply to a read and X.
2077 ****************************************************************************/
2079 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2081 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2082 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2083 ssize_t nread = -1;
2084 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2085 #if 0
2086 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2087 #endif
2089 START_PROFILE(SMBreadX);
2091 /* If it's an IPC, pass off the pipe handler. */
2092 if (IS_IPC(conn)) {
2093 END_PROFILE(SMBreadX);
2094 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2097 CHECK_FSP(fsp,conn);
2098 CHECK_READ(fsp);
2100 set_message(outbuf,12,0,True);
2102 if(CVAL(inbuf,smb_wct) == 12) {
2103 #ifdef LARGE_SMB_OFF_T
2105 * This is a large offset (64 bit) read.
2107 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2109 #else /* !LARGE_SMB_OFF_T */
2112 * Ensure we haven't been sent a >32 bit offset.
2115 if(IVAL(inbuf,smb_vwv10) != 0) {
2116 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2117 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2118 END_PROFILE(SMBreadX);
2119 return ERROR_DOS(ERRDOS,ERRbadaccess);
2122 #endif /* LARGE_SMB_OFF_T */
2126 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
2127 END_PROFILE(SMBreadX);
2128 return ERROR_DOS(ERRDOS,ERRlock);
2131 nread = send_file_readX(conn, inbuf, outbuf, length, fsp, startpos, smb_maxcnt);
2132 if (nread != -1)
2133 nread = chain_reply(inbuf,outbuf,length,bufsize);
2135 END_PROFILE(SMBreadX);
2136 return nread;
2139 /****************************************************************************
2140 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2141 ****************************************************************************/
2143 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2145 ssize_t nwritten=0;
2146 ssize_t total_written=0;
2147 size_t numtowrite=0;
2148 size_t tcount;
2149 SMB_OFF_T startpos;
2150 char *data=NULL;
2151 BOOL write_through;
2152 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2153 int outsize = 0;
2154 START_PROFILE(SMBwritebraw);
2156 if (srv_is_signing_active()) {
2157 exit_server("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2160 CHECK_FSP(fsp,conn);
2161 CHECK_WRITE(fsp);
2163 tcount = IVAL(inbuf,smb_vwv1);
2164 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2165 write_through = BITSETW(inbuf+smb_vwv7,0);
2167 /* We have to deal with slightly different formats depending
2168 on whether we are using the core+ or lanman1.0 protocol */
2170 if(Protocol <= PROTOCOL_COREPLUS) {
2171 numtowrite = SVAL(smb_buf(inbuf),-2);
2172 data = smb_buf(inbuf);
2173 } else {
2174 numtowrite = SVAL(inbuf,smb_vwv10);
2175 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2178 /* force the error type */
2179 SCVAL(inbuf,smb_com,SMBwritec);
2180 SCVAL(outbuf,smb_com,SMBwritec);
2182 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2183 END_PROFILE(SMBwritebraw);
2184 return(ERROR_DOS(ERRDOS,ERRlock));
2187 if (numtowrite>0)
2188 nwritten = write_file(fsp,data,startpos,numtowrite);
2190 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2191 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2193 if (nwritten < (ssize_t)numtowrite) {
2194 END_PROFILE(SMBwritebraw);
2195 return(UNIXERROR(ERRHRD,ERRdiskfull));
2198 total_written = nwritten;
2200 /* Return a message to the redirector to tell it to send more bytes */
2201 SCVAL(outbuf,smb_com,SMBwritebraw);
2202 SSVALS(outbuf,smb_vwv0,-1);
2203 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2204 if (!send_smb(smbd_server_fd(),outbuf))
2205 exit_server("reply_writebraw: send_smb failed.");
2207 /* Now read the raw data into the buffer and write it */
2208 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2209 exit_server("secondary writebraw failed");
2212 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2213 numtowrite = smb_len(inbuf);
2215 /* Set up outbuf to return the correct return */
2216 outsize = set_message(outbuf,1,0,True);
2217 SCVAL(outbuf,smb_com,SMBwritec);
2218 SSVAL(outbuf,smb_vwv0,total_written);
2220 if (numtowrite != 0) {
2222 if (numtowrite > BUFFER_SIZE) {
2223 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2224 (unsigned int)numtowrite ));
2225 exit_server("secondary writebraw failed");
2228 if (tcount > nwritten+numtowrite) {
2229 DEBUG(3,("Client overestimated the write %d %d %d\n",
2230 (int)tcount,(int)nwritten,(int)numtowrite));
2233 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2234 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2235 strerror(errno) ));
2236 exit_server("secondary writebraw failed");
2239 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2241 if (nwritten < (ssize_t)numtowrite) {
2242 SCVAL(outbuf,smb_rcls,ERRHRD);
2243 SSVAL(outbuf,smb_err,ERRdiskfull);
2246 if (nwritten > 0)
2247 total_written += nwritten;
2250 if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn)))
2251 sync_file(conn,fsp);
2253 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2254 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2256 /* we won't return a status if write through is not selected - this follows what WfWg does */
2257 END_PROFILE(SMBwritebraw);
2258 if (!write_through && total_written==tcount) {
2260 #if RABBIT_PELLET_FIX
2262 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2263 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2265 if (!send_keepalive(smbd_server_fd()))
2266 exit_server("reply_writebraw: send of keepalive failed");
2267 #endif
2268 return(-1);
2271 return(outsize);
2274 /****************************************************************************
2275 Reply to a writeunlock (core+).
2276 ****************************************************************************/
2278 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
2279 int size, int dum_buffsize)
2281 ssize_t nwritten = -1;
2282 size_t numtowrite;
2283 SMB_OFF_T startpos;
2284 char *data;
2285 NTSTATUS status = NT_STATUS_OK;
2286 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2287 int outsize = 0;
2288 START_PROFILE(SMBwriteunlock);
2290 CHECK_FSP(fsp,conn);
2291 CHECK_WRITE(fsp);
2293 numtowrite = SVAL(inbuf,smb_vwv1);
2294 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2295 data = smb_buf(inbuf) + 3;
2297 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos,
2298 WRITE_LOCK,False)) {
2299 END_PROFILE(SMBwriteunlock);
2300 return ERROR_DOS(ERRDOS,ERRlock);
2303 /* The special X/Open SMB protocol handling of
2304 zero length writes is *NOT* done for
2305 this call */
2306 if(numtowrite == 0)
2307 nwritten = 0;
2308 else
2309 nwritten = write_file(fsp,data,startpos,numtowrite);
2311 if (lp_syncalways(SNUM(conn)))
2312 sync_file(conn,fsp);
2314 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2315 END_PROFILE(SMBwriteunlock);
2316 return(UNIXERROR(ERRHRD,ERRdiskfull));
2319 if (numtowrite) {
2320 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite,
2321 (SMB_BIG_UINT)startpos);
2322 if (NT_STATUS_V(status)) {
2323 END_PROFILE(SMBwriteunlock);
2324 return ERROR_NT(status);
2328 outsize = set_message(outbuf,1,0,True);
2330 SSVAL(outbuf,smb_vwv0,nwritten);
2332 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2333 fsp->fnum, (int)numtowrite, (int)nwritten));
2335 END_PROFILE(SMBwriteunlock);
2336 return outsize;
2339 /****************************************************************************
2340 Reply to a write.
2341 ****************************************************************************/
2343 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2345 size_t numtowrite;
2346 ssize_t nwritten = -1;
2347 SMB_OFF_T startpos;
2348 char *data;
2349 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2350 int outsize = 0;
2351 START_PROFILE(SMBwrite);
2353 /* If it's an IPC, pass off the pipe handler. */
2354 if (IS_IPC(conn)) {
2355 END_PROFILE(SMBwrite);
2356 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2359 CHECK_FSP(fsp,conn);
2360 CHECK_WRITE(fsp);
2362 numtowrite = SVAL(inbuf,smb_vwv1);
2363 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2364 data = smb_buf(inbuf) + 3;
2366 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2367 END_PROFILE(SMBwrite);
2368 return ERROR_DOS(ERRDOS,ERRlock);
2372 * X/Open SMB protocol says that if smb_vwv1 is
2373 * zero then the file size should be extended or
2374 * truncated to the size given in smb_vwv[2-3].
2377 if(numtowrite == 0) {
2379 * This is actually an allocate call, and set EOF. JRA.
2381 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2382 if (nwritten < 0) {
2383 END_PROFILE(SMBwrite);
2384 return ERROR_NT(NT_STATUS_DISK_FULL);
2386 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2387 if (nwritten < 0) {
2388 END_PROFILE(SMBwrite);
2389 return ERROR_NT(NT_STATUS_DISK_FULL);
2391 } else
2392 nwritten = write_file(fsp,data,startpos,numtowrite);
2394 if (lp_syncalways(SNUM(conn)))
2395 sync_file(conn,fsp);
2397 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2398 END_PROFILE(SMBwrite);
2399 return(UNIXERROR(ERRHRD,ERRdiskfull));
2402 outsize = set_message(outbuf,1,0,True);
2404 SSVAL(outbuf,smb_vwv0,nwritten);
2406 if (nwritten < (ssize_t)numtowrite) {
2407 SCVAL(outbuf,smb_rcls,ERRHRD);
2408 SSVAL(outbuf,smb_err,ERRdiskfull);
2411 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2413 END_PROFILE(SMBwrite);
2414 return(outsize);
2417 /****************************************************************************
2418 Reply to a write and X.
2419 ****************************************************************************/
2421 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2423 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2424 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2425 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2426 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2427 ssize_t nwritten = -1;
2428 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2429 unsigned int smblen = smb_len(inbuf);
2430 char *data;
2431 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2432 START_PROFILE(SMBwriteX);
2434 /* If it's an IPC, pass off the pipe handler. */
2435 if (IS_IPC(conn)) {
2436 END_PROFILE(SMBwriteX);
2437 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2440 CHECK_FSP(fsp,conn);
2441 CHECK_WRITE(fsp);
2443 /* Deal with possible LARGE_WRITEX */
2444 if (large_writeX)
2445 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2447 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2448 END_PROFILE(SMBwriteX);
2449 return ERROR_DOS(ERRDOS,ERRbadmem);
2452 data = smb_base(inbuf) + smb_doff;
2454 if(CVAL(inbuf,smb_wct) == 14) {
2455 #ifdef LARGE_SMB_OFF_T
2457 * This is a large offset (64 bit) write.
2459 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2461 #else /* !LARGE_SMB_OFF_T */
2464 * Ensure we haven't been sent a >32 bit offset.
2467 if(IVAL(inbuf,smb_vwv12) != 0) {
2468 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2469 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2470 END_PROFILE(SMBwriteX);
2471 return ERROR_DOS(ERRDOS,ERRbadaccess);
2474 #endif /* LARGE_SMB_OFF_T */
2477 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2478 END_PROFILE(SMBwriteX);
2479 return ERROR_DOS(ERRDOS,ERRlock);
2482 /* X/Open SMB protocol says that, unlike SMBwrite
2483 if the length is zero then NO truncation is
2484 done, just a write of zero. To truncate a file,
2485 use SMBwrite. */
2487 if(numtowrite == 0)
2488 nwritten = 0;
2489 else
2490 nwritten = write_file(fsp,data,startpos,numtowrite);
2492 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2493 END_PROFILE(SMBwriteX);
2494 return(UNIXERROR(ERRHRD,ERRdiskfull));
2497 set_message(outbuf,6,0,True);
2499 SSVAL(outbuf,smb_vwv2,nwritten);
2500 if (large_writeX)
2501 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2503 if (nwritten < (ssize_t)numtowrite) {
2504 SCVAL(outbuf,smb_rcls,ERRHRD);
2505 SSVAL(outbuf,smb_err,ERRdiskfull);
2508 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2509 fsp->fnum, (int)numtowrite, (int)nwritten));
2511 if (lp_syncalways(SNUM(conn)) || write_through)
2512 sync_file(conn,fsp);
2514 END_PROFILE(SMBwriteX);
2515 return chain_reply(inbuf,outbuf,length,bufsize);
2518 /****************************************************************************
2519 Reply to a lseek.
2520 ****************************************************************************/
2522 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2524 SMB_OFF_T startpos;
2525 SMB_OFF_T res= -1;
2526 int mode,umode;
2527 int outsize = 0;
2528 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2529 START_PROFILE(SMBlseek);
2531 CHECK_FSP(fsp,conn);
2533 flush_write_cache(fsp, SEEK_FLUSH);
2535 mode = SVAL(inbuf,smb_vwv1) & 3;
2536 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
2537 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
2539 switch (mode) {
2540 case 0:
2541 umode = SEEK_SET;
2542 res = startpos;
2543 break;
2544 case 1:
2545 umode = SEEK_CUR;
2546 res = fsp->pos + startpos;
2547 break;
2548 case 2:
2549 umode = SEEK_END;
2550 break;
2551 default:
2552 umode = SEEK_SET;
2553 res = startpos;
2554 break;
2557 if (umode == SEEK_END) {
2558 if((res = SMB_VFS_LSEEK(fsp,fsp->fd,startpos,umode)) == -1) {
2559 if(errno == EINVAL) {
2560 SMB_OFF_T current_pos = startpos;
2561 SMB_STRUCT_STAT sbuf;
2563 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) {
2564 END_PROFILE(SMBlseek);
2565 return(UNIXERROR(ERRDOS,ERRnoaccess));
2568 current_pos += sbuf.st_size;
2569 if(current_pos < 0)
2570 res = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_SET);
2574 if(res == -1) {
2575 END_PROFILE(SMBlseek);
2576 return(UNIXERROR(ERRDOS,ERRnoaccess));
2580 fsp->pos = res;
2582 outsize = set_message(outbuf,2,0,True);
2583 SIVAL(outbuf,smb_vwv0,res);
2585 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2586 fsp->fnum, (double)startpos, (double)res, mode));
2588 END_PROFILE(SMBlseek);
2589 return(outsize);
2592 /****************************************************************************
2593 Reply to a flush.
2594 ****************************************************************************/
2596 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2598 int outsize = set_message(outbuf,0,0,True);
2599 uint16 fnum = SVAL(inbuf,smb_vwv0);
2600 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2601 START_PROFILE(SMBflush);
2603 if (fnum != 0xFFFF)
2604 CHECK_FSP(fsp,conn);
2606 if (!fsp) {
2607 file_sync_all(conn);
2608 } else {
2609 sync_file(conn,fsp);
2612 DEBUG(3,("flush\n"));
2613 END_PROFILE(SMBflush);
2614 return(outsize);
2617 /****************************************************************************
2618 Reply to a exit.
2619 ****************************************************************************/
2621 int reply_exit(connection_struct *conn,
2622 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2624 int outsize;
2625 START_PROFILE(SMBexit);
2627 file_close_pid(SVAL(inbuf,smb_pid));
2629 outsize = set_message(outbuf,0,0,True);
2631 DEBUG(3,("exit\n"));
2633 END_PROFILE(SMBexit);
2634 return(outsize);
2637 /****************************************************************************
2638 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2639 ****************************************************************************/
2641 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2642 int dum_buffsize)
2644 extern struct current_user current_user;
2645 int outsize = 0;
2646 time_t mtime;
2647 int32 eclass = 0, err = 0;
2648 files_struct *fsp = NULL;
2649 START_PROFILE(SMBclose);
2651 outsize = set_message(outbuf,0,0,True);
2653 /* If it's an IPC, pass off to the pipe handler. */
2654 if (IS_IPC(conn)) {
2655 END_PROFILE(SMBclose);
2656 return reply_pipe_close(conn, inbuf,outbuf);
2659 fsp = file_fsp(inbuf,smb_vwv0);
2662 * We can only use CHECK_FSP if we know it's not a directory.
2665 if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
2666 END_PROFILE(SMBclose);
2667 return ERROR_DOS(ERRDOS,ERRbadfid);
2670 if(fsp->is_directory) {
2672 * Special case - close NT SMB directory handle.
2674 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2675 close_file(fsp,True);
2676 } else {
2678 * Close ordinary file.
2680 int close_err;
2681 pstring file_name;
2683 /* Save the name for time set in close. */
2684 pstrcpy( file_name, fsp->fsp_name);
2686 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2687 fsp->fd, fsp->fnum,
2688 conn->num_files_open));
2691 * close_file() returns the unix errno if an error
2692 * was detected on close - normally this is due to
2693 * a disk full error. If not then it was probably an I/O error.
2696 if((close_err = close_file(fsp,True)) != 0) {
2697 errno = close_err;
2698 END_PROFILE(SMBclose);
2699 return (UNIXERROR(ERRHRD,ERRgeneral));
2703 * Now take care of any time sent in the close.
2706 mtime = make_unix_date3(inbuf+smb_vwv1);
2708 /* try and set the date */
2709 set_filetime(conn, file_name, mtime);
2713 /* We have a cached error */
2714 if(eclass || err) {
2715 END_PROFILE(SMBclose);
2716 return ERROR_DOS(eclass,err);
2719 END_PROFILE(SMBclose);
2720 return(outsize);
2723 /****************************************************************************
2724 Reply to a writeclose (Core+ protocol).
2725 ****************************************************************************/
2727 int reply_writeclose(connection_struct *conn,
2728 char *inbuf,char *outbuf, int size, int dum_buffsize)
2730 size_t numtowrite;
2731 ssize_t nwritten = -1;
2732 int outsize = 0;
2733 int close_err = 0;
2734 SMB_OFF_T startpos;
2735 char *data;
2736 time_t mtime;
2737 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2738 START_PROFILE(SMBwriteclose);
2740 CHECK_FSP(fsp,conn);
2741 CHECK_WRITE(fsp);
2743 numtowrite = SVAL(inbuf,smb_vwv1);
2744 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2745 mtime = make_unix_date3(inbuf+smb_vwv4);
2746 data = smb_buf(inbuf) + 1;
2748 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2749 END_PROFILE(SMBwriteclose);
2750 return ERROR_DOS(ERRDOS,ERRlock);
2753 nwritten = write_file(fsp,data,startpos,numtowrite);
2755 set_filetime(conn, fsp->fsp_name,mtime);
2758 * More insanity. W2K only closes the file if writelen > 0.
2759 * JRA.
2762 if (numtowrite) {
2763 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
2764 fsp->fsp_name ));
2765 close_err = close_file(fsp,True);
2768 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2769 fsp->fnum, (int)numtowrite, (int)nwritten,
2770 conn->num_files_open));
2772 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2773 END_PROFILE(SMBwriteclose);
2774 return(UNIXERROR(ERRHRD,ERRdiskfull));
2777 if(close_err != 0) {
2778 errno = close_err;
2779 END_PROFILE(SMBwriteclose);
2780 return(UNIXERROR(ERRHRD,ERRgeneral));
2783 outsize = set_message(outbuf,1,0,True);
2785 SSVAL(outbuf,smb_vwv0,nwritten);
2786 END_PROFILE(SMBwriteclose);
2787 return(outsize);
2790 /****************************************************************************
2791 Reply to a lock.
2792 ****************************************************************************/
2794 int reply_lock(connection_struct *conn,
2795 char *inbuf,char *outbuf, int length, int dum_buffsize)
2797 int outsize = set_message(outbuf,0,0,True);
2798 SMB_BIG_UINT count,offset;
2799 NTSTATUS status;
2800 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2801 BOOL my_lock_ctx = False;
2803 START_PROFILE(SMBlock);
2805 CHECK_FSP(fsp,conn);
2807 release_level_2_oplocks_on_change(fsp);
2809 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2810 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2812 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2813 fsp->fd, fsp->fnum, (double)offset, (double)count));
2815 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &my_lock_ctx);
2816 if (NT_STATUS_V(status)) {
2817 #if 0
2818 /* Tests using Samba4 against W2K show this call never creates a blocking lock. */
2819 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
2821 * A blocking lock was requested. Package up
2822 * this smb into a queued request and push it
2823 * onto the blocking lock queue.
2825 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), offset, count)) {
2826 END_PROFILE(SMBlock);
2827 return -1;
2830 #endif
2831 END_PROFILE(SMBlock);
2832 return ERROR_NT(status);
2835 END_PROFILE(SMBlock);
2836 return(outsize);
2839 /****************************************************************************
2840 Reply to a unlock.
2841 ****************************************************************************/
2843 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
2844 int dum_buffsize)
2846 int outsize = set_message(outbuf,0,0,True);
2847 SMB_BIG_UINT count,offset;
2848 NTSTATUS status;
2849 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2850 START_PROFILE(SMBunlock);
2852 CHECK_FSP(fsp,conn);
2854 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2855 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2857 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
2858 if (NT_STATUS_V(status)) {
2859 END_PROFILE(SMBunlock);
2860 return ERROR_NT(status);
2863 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2864 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
2866 END_PROFILE(SMBunlock);
2867 return(outsize);
2870 /****************************************************************************
2871 Reply to a tdis.
2872 ****************************************************************************/
2874 int reply_tdis(connection_struct *conn,
2875 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2877 int outsize = set_message(outbuf,0,0,True);
2878 uint16 vuid;
2879 START_PROFILE(SMBtdis);
2881 vuid = SVAL(inbuf,smb_uid);
2883 if (!conn) {
2884 DEBUG(4,("Invalid connection in tdis\n"));
2885 END_PROFILE(SMBtdis);
2886 return ERROR_DOS(ERRSRV,ERRinvnid);
2889 conn->used = False;
2891 close_cnum(conn,vuid);
2893 END_PROFILE(SMBtdis);
2894 return outsize;
2897 /****************************************************************************
2898 Reply to a echo.
2899 ****************************************************************************/
2901 int reply_echo(connection_struct *conn,
2902 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2904 int smb_reverb = SVAL(inbuf,smb_vwv0);
2905 int seq_num;
2906 unsigned int data_len = smb_buflen(inbuf);
2907 int outsize = set_message(outbuf,1,data_len,True);
2908 START_PROFILE(SMBecho);
2910 if (data_len > BUFFER_SIZE) {
2911 DEBUG(0,("reply_echo: data_len too large.\n"));
2912 END_PROFILE(SMBecho);
2913 return -1;
2916 /* copy any incoming data back out */
2917 if (data_len > 0)
2918 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2920 if (smb_reverb > 100) {
2921 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2922 smb_reverb = 100;
2925 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
2926 SSVAL(outbuf,smb_vwv0,seq_num);
2928 smb_setlen(outbuf,outsize - 4);
2930 if (!send_smb(smbd_server_fd(),outbuf))
2931 exit_server("reply_echo: send_smb failed.");
2934 DEBUG(3,("echo %d times\n", smb_reverb));
2936 smb_echo_count++;
2938 END_PROFILE(SMBecho);
2939 return -1;
2942 /****************************************************************************
2943 Reply to a printopen.
2944 ****************************************************************************/
2946 int reply_printopen(connection_struct *conn,
2947 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2949 int outsize = 0;
2950 files_struct *fsp;
2951 START_PROFILE(SMBsplopen);
2953 if (!CAN_PRINT(conn)) {
2954 END_PROFILE(SMBsplopen);
2955 return ERROR_DOS(ERRDOS,ERRnoaccess);
2958 /* Open for exclusive use, write only. */
2959 fsp = print_fsp_open(conn, NULL);
2961 if (!fsp) {
2962 END_PROFILE(SMBsplopen);
2963 return(UNIXERROR(ERRDOS,ERRnoaccess));
2966 outsize = set_message(outbuf,1,0,True);
2967 SSVAL(outbuf,smb_vwv0,fsp->fnum);
2969 DEBUG(3,("openprint fd=%d fnum=%d\n",
2970 fsp->fd, fsp->fnum));
2972 END_PROFILE(SMBsplopen);
2973 return(outsize);
2976 /****************************************************************************
2977 Reply to a printclose.
2978 ****************************************************************************/
2980 int reply_printclose(connection_struct *conn,
2981 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2983 int outsize = set_message(outbuf,0,0,True);
2984 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2985 int close_err = 0;
2986 START_PROFILE(SMBsplclose);
2988 CHECK_FSP(fsp,conn);
2990 if (!CAN_PRINT(conn)) {
2991 END_PROFILE(SMBsplclose);
2992 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
2995 DEBUG(3,("printclose fd=%d fnum=%d\n",
2996 fsp->fd,fsp->fnum));
2998 close_err = close_file(fsp,True);
3000 if(close_err != 0) {
3001 errno = close_err;
3002 END_PROFILE(SMBsplclose);
3003 return(UNIXERROR(ERRHRD,ERRgeneral));
3006 END_PROFILE(SMBsplclose);
3007 return(outsize);
3010 /****************************************************************************
3011 Reply to a printqueue.
3012 ****************************************************************************/
3014 int reply_printqueue(connection_struct *conn,
3015 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3017 int outsize = set_message(outbuf,2,3,True);
3018 int max_count = SVAL(inbuf,smb_vwv0);
3019 int start_index = SVAL(inbuf,smb_vwv1);
3020 START_PROFILE(SMBsplretq);
3022 /* we used to allow the client to get the cnum wrong, but that
3023 is really quite gross and only worked when there was only
3024 one printer - I think we should now only accept it if they
3025 get it right (tridge) */
3026 if (!CAN_PRINT(conn)) {
3027 END_PROFILE(SMBsplretq);
3028 return ERROR_DOS(ERRDOS,ERRnoaccess);
3031 SSVAL(outbuf,smb_vwv0,0);
3032 SSVAL(outbuf,smb_vwv1,0);
3033 SCVAL(smb_buf(outbuf),0,1);
3034 SSVAL(smb_buf(outbuf),1,0);
3036 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3037 start_index, max_count));
3040 print_queue_struct *queue = NULL;
3041 print_status_struct status;
3042 char *p = smb_buf(outbuf) + 3;
3043 int count = print_queue_status(SNUM(conn), &queue, &status);
3044 int num_to_get = ABS(max_count);
3045 int first = (max_count>0?start_index:start_index+max_count+1);
3046 int i;
3048 if (first >= count)
3049 num_to_get = 0;
3050 else
3051 num_to_get = MIN(num_to_get,count-first);
3054 for (i=first;i<first+num_to_get;i++) {
3055 put_dos_date2(p,0,queue[i].time);
3056 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
3057 SSVAL(p,5, queue[i].job);
3058 SIVAL(p,7,queue[i].size);
3059 SCVAL(p,11,0);
3060 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
3061 p += 28;
3064 if (count > 0) {
3065 outsize = set_message(outbuf,2,28*count+3,False);
3066 SSVAL(outbuf,smb_vwv0,count);
3067 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3068 SCVAL(smb_buf(outbuf),0,1);
3069 SSVAL(smb_buf(outbuf),1,28*count);
3072 SAFE_FREE(queue);
3074 DEBUG(3,("%d entries returned in queue\n",count));
3077 END_PROFILE(SMBsplretq);
3078 return(outsize);
3081 /****************************************************************************
3082 Reply to a printwrite.
3083 ****************************************************************************/
3085 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3087 int numtowrite;
3088 int outsize = set_message(outbuf,0,0,True);
3089 char *data;
3090 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3092 START_PROFILE(SMBsplwr);
3094 if (!CAN_PRINT(conn)) {
3095 END_PROFILE(SMBsplwr);
3096 return ERROR_DOS(ERRDOS,ERRnoaccess);
3099 CHECK_FSP(fsp,conn);
3100 CHECK_WRITE(fsp);
3102 numtowrite = SVAL(smb_buf(inbuf),1);
3103 data = smb_buf(inbuf) + 3;
3105 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3106 END_PROFILE(SMBsplwr);
3107 return(UNIXERROR(ERRHRD,ERRdiskfull));
3110 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3112 END_PROFILE(SMBsplwr);
3113 return(outsize);
3116 /****************************************************************************
3117 The guts of the mkdir command, split out so it may be called by the NT SMB
3118 code.
3119 ****************************************************************************/
3121 NTSTATUS mkdir_internal(connection_struct *conn, pstring directory)
3123 BOOL bad_path = False;
3124 SMB_STRUCT_STAT sbuf;
3125 int ret= -1;
3127 unix_convert(directory,conn,0,&bad_path,&sbuf);
3129 if( strchr_m(directory, ':')) {
3130 return NT_STATUS_NOT_A_DIRECTORY;
3133 if (ms_has_wild(directory)) {
3134 return NT_STATUS_OBJECT_NAME_INVALID;
3137 if (check_name(directory, conn))
3138 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory));
3140 if (ret == -1) {
3141 if(errno == ENOENT) {
3142 if (bad_path)
3143 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3144 else
3145 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3147 return map_nt_error_from_unix(errno);
3150 return NT_STATUS_OK;
3153 /****************************************************************************
3154 Reply to a mkdir.
3155 ****************************************************************************/
3157 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3159 pstring directory;
3160 int outsize;
3161 NTSTATUS status;
3162 START_PROFILE(SMBmkdir);
3164 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
3165 if (!NT_STATUS_IS_OK(status)) {
3166 END_PROFILE(SMBmkdir);
3167 return ERROR_NT(status);
3170 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
3172 status = mkdir_internal(conn, directory);
3173 if (!NT_STATUS_IS_OK(status)) {
3174 END_PROFILE(SMBmkdir);
3175 return ERROR_NT(status);
3178 outsize = set_message(outbuf,0,0,True);
3180 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3182 END_PROFILE(SMBmkdir);
3183 return(outsize);
3186 /****************************************************************************
3187 Static function used by reply_rmdir to delete an entire directory
3188 tree recursively. Return False on ok, True on fail.
3189 ****************************************************************************/
3191 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3193 const char *dname = NULL;
3194 BOOL ret = False;
3195 void *dirptr = OpenDir(conn, directory, False);
3197 if(dirptr == NULL)
3198 return True;
3200 while((dname = ReadDirName(dirptr))) {
3201 pstring fullname;
3202 SMB_STRUCT_STAT st;
3204 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3205 continue;
3207 /* Construct the full name. */
3208 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3209 errno = ENOMEM;
3210 ret = True;
3211 break;
3214 pstrcpy(fullname, directory);
3215 pstrcat(fullname, "/");
3216 pstrcat(fullname, dname);
3218 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
3219 ret = True;
3220 break;
3223 if(st.st_mode & S_IFDIR) {
3224 if(recursive_rmdir(conn, fullname)!=0) {
3225 ret = True;
3226 break;
3228 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
3229 ret = True;
3230 break;
3232 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
3233 ret = True;
3234 break;
3237 CloseDir(dirptr);
3238 return ret;
3241 /****************************************************************************
3242 The internals of the rmdir code - called elsewhere.
3243 ****************************************************************************/
3245 BOOL rmdir_internals(connection_struct *conn, char *directory)
3247 BOOL ok;
3249 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3250 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3252 * Check to see if the only thing in this directory are
3253 * vetoed files/directories. If so then delete them and
3254 * retry. If we fail to delete any of them (and we *don't*
3255 * do a recursive delete) then fail the rmdir.
3257 BOOL all_veto_files = True;
3258 const char *dname;
3259 void *dirptr = OpenDir(conn, directory, False);
3261 if(dirptr != NULL) {
3262 int dirpos = TellDir(dirptr);
3263 while ((dname = ReadDirName(dirptr))) {
3264 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3265 continue;
3266 if(!IS_VETO_PATH(conn, dname)) {
3267 all_veto_files = False;
3268 break;
3272 if(all_veto_files) {
3273 SeekDir(dirptr,dirpos);
3274 while ((dname = ReadDirName(dirptr))) {
3275 pstring fullname;
3276 SMB_STRUCT_STAT st;
3278 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3279 continue;
3281 /* Construct the full name. */
3282 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3283 errno = ENOMEM;
3284 break;
3287 pstrcpy(fullname, directory);
3288 pstrcat(fullname, "/");
3289 pstrcat(fullname, dname);
3291 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
3292 break;
3293 if(st.st_mode & S_IFDIR) {
3294 if(lp_recursive_veto_delete(SNUM(conn))) {
3295 if(recursive_rmdir(conn, fullname) != 0)
3296 break;
3298 if(SMB_VFS_RMDIR(conn,fullname) != 0)
3299 break;
3300 } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
3301 break;
3303 CloseDir(dirptr);
3304 /* Retry the rmdir */
3305 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3306 } else {
3307 CloseDir(dirptr);
3309 } else {
3310 errno = ENOTEMPTY;
3314 if (!ok)
3315 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
3317 return ok;
3320 /****************************************************************************
3321 Reply to a rmdir.
3322 ****************************************************************************/
3324 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3326 pstring directory;
3327 int outsize = 0;
3328 BOOL ok = False;
3329 BOOL bad_path = False;
3330 SMB_STRUCT_STAT sbuf;
3331 NTSTATUS status;
3332 START_PROFILE(SMBrmdir);
3334 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
3335 if (!NT_STATUS_IS_OK(status)) {
3336 END_PROFILE(SMBrmdir);
3337 return ERROR_NT(status);
3340 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3342 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3344 if (check_name(directory,conn)) {
3345 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3346 ok = rmdir_internals(conn, directory);
3349 if (!ok) {
3350 END_PROFILE(SMBrmdir);
3351 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRbadpath);
3354 outsize = set_message(outbuf,0,0,True);
3356 DEBUG( 3, ( "rmdir %s\n", directory ) );
3358 END_PROFILE(SMBrmdir);
3359 return(outsize);
3362 /*******************************************************************
3363 Resolve wildcards in a filename rename.
3364 Note that name is in UNIX charset and thus potentially can be more
3365 than fstring buffer (255 bytes) especially in default UTF-8 case.
3366 Therefore, we use pstring inside and all calls should ensure that
3367 name2 is at least pstring-long (they do already)
3368 ********************************************************************/
3370 static BOOL resolve_wildcards(const char *name1, char *name2)
3372 pstring root1,root2;
3373 pstring ext1,ext2;
3374 char *p,*p2, *pname1, *pname2;
3375 int available_space, actual_space;
3378 pname1 = strrchr_m(name1,'/');
3379 pname2 = strrchr_m(name2,'/');
3381 if (!pname1 || !pname2)
3382 return(False);
3384 pstrcpy(root1,pname1);
3385 pstrcpy(root2,pname2);
3386 p = strrchr_m(root1,'.');
3387 if (p) {
3388 *p = 0;
3389 pstrcpy(ext1,p+1);
3390 } else {
3391 pstrcpy(ext1,"");
3393 p = strrchr_m(root2,'.');
3394 if (p) {
3395 *p = 0;
3396 pstrcpy(ext2,p+1);
3397 } else {
3398 pstrcpy(ext2,"");
3401 p = root1;
3402 p2 = root2;
3403 while (*p2) {
3404 if (*p2 == '?') {
3405 *p2 = *p;
3406 p2++;
3407 } else {
3408 p2++;
3410 if (*p)
3411 p++;
3414 p = ext1;
3415 p2 = ext2;
3416 while (*p2) {
3417 if (*p2 == '?') {
3418 *p2 = *p;
3419 p2++;
3420 } else {
3421 p2++;
3423 if (*p)
3424 p++;
3427 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
3429 if (ext2[0]) {
3430 actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
3431 if (actual_space >= available_space - 1) {
3432 DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
3433 actual_space - available_space));
3435 } else {
3436 pstrcpy_base(pname2, root2, name2);
3439 return(True);
3442 /****************************************************************************
3443 Ensure open files have their names updates.
3444 ****************************************************************************/
3446 static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode, char *newname)
3448 files_struct *fsp;
3449 BOOL did_rename = False;
3451 for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
3452 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
3453 fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
3454 fsp->fsp_name, newname ));
3455 string_set(&fsp->fsp_name, newname);
3456 did_rename = True;
3459 if (!did_rename)
3460 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
3461 (unsigned int)dev, (double)inode, newname ));
3464 /****************************************************************************
3465 Rename an open file - given an fsp.
3466 ****************************************************************************/
3468 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, BOOL replace_if_exists)
3470 SMB_STRUCT_STAT sbuf;
3471 BOOL bad_path = False;
3472 pstring newname_last_component;
3473 NTSTATUS error = NT_STATUS_OK;
3474 BOOL dest_exists;
3475 BOOL rcdest = True;
3477 ZERO_STRUCT(sbuf);
3478 rcdest = unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf);
3480 /* Quick check for "." and ".." */
3481 if (!bad_path && newname_last_component[0] == '.') {
3482 if (!newname_last_component[1] || (newname_last_component[1] == '.' && !newname_last_component[2])) {
3483 return NT_STATUS_ACCESS_DENIED;
3486 if (!rcdest && bad_path) {
3487 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3490 /* Ensure newname contains a '/' */
3491 if(strrchr_m(newname,'/') == 0) {
3492 pstring tmpstr;
3494 pstrcpy(tmpstr, "./");
3495 pstrcat(tmpstr, newname);
3496 pstrcpy(newname, tmpstr);
3500 * Check for special case with case preserving and not
3501 * case sensitive. If the old last component differs from the original
3502 * last component only by case, then we should allow
3503 * the rename (user is trying to change the case of the
3504 * filename).
3507 if((case_sensitive == False) && (case_preserve == True) &&
3508 strequal(newname, fsp->fsp_name)) {
3509 char *p;
3510 pstring newname_modified_last_component;
3513 * Get the last component of the modified name.
3514 * Note that we guarantee that newname contains a '/'
3515 * character above.
3517 p = strrchr_m(newname,'/');
3518 pstrcpy(newname_modified_last_component,p+1);
3520 if(strcsequal(newname_modified_last_component,
3521 newname_last_component) == False) {
3523 * Replace the modified last component with
3524 * the original.
3526 pstrcpy(p+1, newname_last_component);
3531 * If the src and dest names are identical - including case,
3532 * don't do the rename, just return success.
3535 if (strcsequal(fsp->fsp_name, newname)) {
3536 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
3537 newname));
3538 return NT_STATUS_OK;
3541 dest_exists = vfs_object_exist(conn,newname,NULL);
3543 if(!replace_if_exists && dest_exists) {
3544 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
3545 fsp->fsp_name,newname));
3546 return NT_STATUS_OBJECT_NAME_COLLISION;
3549 error = can_rename(newname,conn,&sbuf);
3551 if (dest_exists && !NT_STATUS_IS_OK(error)) {
3552 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3553 nt_errstr(error), fsp->fsp_name,newname));
3554 if (NT_STATUS_EQUAL(error,NT_STATUS_SHARING_VIOLATION))
3555 error = NT_STATUS_ACCESS_DENIED;
3556 return error;
3559 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
3560 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
3561 fsp->fsp_name,newname));
3562 rename_open_files(conn, fsp->dev, fsp->inode, newname);
3563 return NT_STATUS_OK;
3566 if (errno == ENOTDIR || errno == EISDIR)
3567 error = NT_STATUS_OBJECT_NAME_COLLISION;
3568 else
3569 error = map_nt_error_from_unix(errno);
3571 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
3572 nt_errstr(error), fsp->fsp_name,newname));
3574 return error;
3577 /****************************************************************************
3578 The guts of the rename command, split out so it may be called by the NT SMB
3579 code.
3580 ****************************************************************************/
3582 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, uint16 attrs, BOOL replace_if_exists)
3584 pstring directory;
3585 pstring mask;
3586 pstring last_component_src;
3587 pstring last_component_dest;
3588 char *p;
3589 BOOL has_wild;
3590 BOOL bad_path_src = False;
3591 BOOL bad_path_dest = False;
3592 int count=0;
3593 NTSTATUS error = NT_STATUS_OK;
3594 BOOL rc = True;
3595 BOOL rcdest = True;
3596 SMB_STRUCT_STAT sbuf1, sbuf2;
3598 *directory = *mask = 0;
3600 ZERO_STRUCT(sbuf1);
3601 ZERO_STRUCT(sbuf2);
3603 rc = unix_convert(name,conn,last_component_src,&bad_path_src,&sbuf1);
3604 if (!rc && bad_path_src) {
3605 if (ms_has_wild(last_component_src))
3606 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3607 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3610 /* Quick check for "." and ".." */
3611 if (last_component_src[0] == '.') {
3612 if (!last_component_src[1] || (last_component_src[1] == '.' && !last_component_src[2])) {
3613 return NT_STATUS_OBJECT_NAME_INVALID;
3617 rcdest = unix_convert(newname,conn,last_component_dest,&bad_path_dest,&sbuf2);
3619 /* Quick check for "." and ".." */
3620 if (last_component_dest[0] == '.') {
3621 if (!last_component_dest[1] || (last_component_dest[1] == '.' && !last_component_dest[2])) {
3622 return NT_STATUS_OBJECT_NAME_INVALID;
3627 * Split the old name into directory and last component
3628 * strings. Note that unix_convert may have stripped off a
3629 * leading ./ from both name and newname if the rename is
3630 * at the root of the share. We need to make sure either both
3631 * name and newname contain a / character or neither of them do
3632 * as this is checked in resolve_wildcards().
3635 p = strrchr_m(name,'/');
3636 if (!p) {
3637 pstrcpy(directory,".");
3638 pstrcpy(mask,name);
3639 } else {
3640 *p = 0;
3641 pstrcpy(directory,name);
3642 pstrcpy(mask,p+1);
3643 *p = '/'; /* Replace needed for exceptional test below. */
3647 * We should only check the mangled cache
3648 * here if unix_convert failed. This means
3649 * that the path in 'mask' doesn't exist
3650 * on the file system and so we need to look
3651 * for a possible mangle. This patch from
3652 * Tine Smukavec <valentin.smukavec@hermes.si>.
3655 if (!rc && mangle_is_mangled(mask))
3656 mangle_check_cache( mask );
3658 has_wild = ms_has_wild(mask);
3660 if (!has_wild) {
3662 * No wildcards - just process the one file.
3664 BOOL is_short_name = mangle_is_8_3(name, True);
3666 /* Add a terminating '/' to the directory name. */
3667 pstrcat(directory,"/");
3668 pstrcat(directory,mask);
3670 /* Ensure newname contains a '/' also */
3671 if(strrchr_m(newname,'/') == 0) {
3672 pstring tmpstr;
3674 pstrcpy(tmpstr, "./");
3675 pstrcat(tmpstr, newname);
3676 pstrcpy(newname, tmpstr);
3679 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
3680 directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
3681 case_sensitive, case_preserve, short_case_preserve, directory,
3682 newname, last_component_dest, is_short_name));
3685 * Check for special case with case preserving and not
3686 * case sensitive, if directory and newname are identical,
3687 * and the old last component differs from the original
3688 * last component only by case, then we should allow
3689 * the rename (user is trying to change the case of the
3690 * filename).
3692 if((case_sensitive == False) &&
3693 (((case_preserve == True) &&
3694 (is_short_name == False)) ||
3695 ((short_case_preserve == True) &&
3696 (is_short_name == True))) &&
3697 strcsequal(directory, newname)) {
3698 pstring modified_last_component;
3701 * Get the last component of the modified name.
3702 * Note that we guarantee that newname contains a '/'
3703 * character above.
3705 p = strrchr_m(newname,'/');
3706 pstrcpy(modified_last_component,p+1);
3708 if(strcsequal(modified_last_component,
3709 last_component_dest) == False) {
3711 * Replace the modified last component with
3712 * the original.
3714 pstrcpy(p+1, last_component_dest);
3718 resolve_wildcards(directory,newname);
3721 * The source object must exist.
3724 if (!vfs_object_exist(conn, directory, &sbuf1)) {
3725 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
3726 directory,newname));
3728 if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
3730 * Must return different errors depending on whether the parent
3731 * directory existed or not.
3734 p = strrchr_m(directory, '/');
3735 if (!p)
3736 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3737 *p = '\0';
3738 if (vfs_object_exist(conn, directory, NULL))
3739 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3740 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3742 error = map_nt_error_from_unix(errno);
3743 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3744 nt_errstr(error), directory,newname));
3746 return error;
3749 if (!rcdest && bad_path_dest) {
3750 if (ms_has_wild(last_component_dest))
3751 return NT_STATUS_OBJECT_NAME_INVALID;
3752 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3755 error = can_rename(directory,conn,&sbuf1);
3757 if (!NT_STATUS_IS_OK(error)) {
3758 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3759 nt_errstr(error), directory,newname));
3760 return error;
3764 * If the src and dest names are identical - including case,
3765 * don't do the rename, just return success.
3768 if (strcsequal(directory, newname)) {
3769 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3770 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
3771 return NT_STATUS_OK;
3774 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
3775 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
3776 directory,newname));
3777 return NT_STATUS_OBJECT_NAME_COLLISION;
3780 if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
3781 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
3782 directory,newname));
3783 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3784 return NT_STATUS_OK;
3787 if (errno == ENOTDIR || errno == EISDIR)
3788 error = NT_STATUS_OBJECT_NAME_COLLISION;
3789 else
3790 error = map_nt_error_from_unix(errno);
3792 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3793 nt_errstr(error), directory,newname));
3795 return error;
3796 } else {
3798 * Wildcards - process each file that matches.
3800 void *dirptr = NULL;
3801 const char *dname;
3802 pstring destname;
3804 if (check_name(directory,conn))
3805 dirptr = OpenDir(conn, directory, True);
3807 if (dirptr) {
3808 error = NT_STATUS_NO_SUCH_FILE;
3809 /* Was error = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */
3811 if (strequal(mask,"????????.???"))
3812 pstrcpy(mask,"*");
3814 while ((dname = ReadDirName(dirptr))) {
3815 pstring fname;
3816 BOOL sysdir_entry = False;
3818 pstrcpy(fname,dname);
3820 /* Quick check for "." and ".." */
3821 if (fname[0] == '.') {
3822 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
3823 if (attrs & aDIR) {
3824 sysdir_entry = True;
3825 } else {
3826 continue;
3831 if(!mask_match(fname, mask, case_sensitive))
3832 continue;
3834 if (sysdir_entry) {
3835 error = NT_STATUS_OBJECT_NAME_INVALID;
3836 continue;
3839 error = NT_STATUS_ACCESS_DENIED;
3840 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3841 if (!vfs_object_exist(conn, fname, &sbuf1)) {
3842 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3843 DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
3844 continue;
3846 error = can_rename(fname,conn,&sbuf1);
3847 if (!NT_STATUS_IS_OK(error)) {
3848 DEBUG(6,("rename %s refused\n", fname));
3849 continue;
3851 pstrcpy(destname,newname);
3853 if (!resolve_wildcards(fname,destname)) {
3854 DEBUG(6,("resolve_wildcards %s %s failed\n",
3855 fname, destname));
3856 continue;
3859 if (!replace_if_exists &&
3860 vfs_file_exist(conn,destname, NULL)) {
3861 DEBUG(6,("file_exist %s\n", destname));
3862 error = NT_STATUS_OBJECT_NAME_COLLISION;
3863 continue;
3866 if (!SMB_VFS_RENAME(conn,fname,destname)) {
3867 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3868 count++;
3869 error = NT_STATUS_OK;
3871 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3873 CloseDir(dirptr);
3876 if (!NT_STATUS_EQUAL(error,NT_STATUS_NO_SUCH_FILE)) {
3877 if (!rcdest && bad_path_dest) {
3878 if (ms_has_wild(last_component_dest))
3879 return NT_STATUS_OBJECT_NAME_INVALID;
3880 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3885 if (count == 0 && NT_STATUS_IS_OK(error)) {
3886 error = map_nt_error_from_unix(errno);
3889 return error;
3892 /****************************************************************************
3893 Reply to a mv.
3894 ****************************************************************************/
3896 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
3897 int dum_buffsize)
3899 int outsize = 0;
3900 pstring name;
3901 pstring newname;
3902 char *p;
3903 uint16 attrs = SVAL(inbuf,smb_vwv0);
3904 NTSTATUS status;
3906 START_PROFILE(SMBmv);
3908 p = smb_buf(inbuf) + 1;
3909 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status);
3910 if (!NT_STATUS_IS_OK(status)) {
3911 END_PROFILE(SMBmv);
3912 return ERROR_NT(status);
3914 p++;
3915 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status);
3916 if (!NT_STATUS_IS_OK(status)) {
3917 END_PROFILE(SMBmv);
3918 return ERROR_NT(status);
3921 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3922 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3924 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3926 status = rename_internals(conn, name, newname, attrs, False);
3927 if (!NT_STATUS_IS_OK(status)) {
3928 END_PROFILE(SMBmv);
3929 return ERROR_NT(status);
3933 * Win2k needs a changenotify request response before it will
3934 * update after a rename..
3936 process_pending_change_notify_queue((time_t)0);
3937 outsize = set_message(outbuf,0,0,True);
3939 END_PROFILE(SMBmv);
3940 return(outsize);
3943 /*******************************************************************
3944 Copy a file as part of a reply_copy.
3945 ******************************************************************/
3947 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3948 int count,BOOL target_is_directory, int *err_ret)
3950 int Access,action;
3951 SMB_STRUCT_STAT src_sbuf, sbuf2;
3952 SMB_OFF_T ret=-1;
3953 files_struct *fsp1,*fsp2;
3954 pstring dest;
3956 *err_ret = 0;
3958 pstrcpy(dest,dest1);
3959 if (target_is_directory) {
3960 char *p = strrchr_m(src,'/');
3961 if (p)
3962 p++;
3963 else
3964 p = src;
3965 pstrcat(dest,"/");
3966 pstrcat(dest,p);
3969 if (!vfs_file_exist(conn,src,&src_sbuf))
3970 return(False);
3972 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
3973 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
3975 if (!fsp1)
3976 return(False);
3978 if (!target_is_directory && count)
3979 ofun = FILE_EXISTS_OPEN;
3981 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1)
3982 ZERO_STRUCTP(&sbuf2);
3984 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
3985 ofun,src_sbuf.st_mode,0,&Access,&action);
3987 if (!fsp2) {
3988 close_file(fsp1,False);
3989 return(False);
3992 if ((ofun&3) == 1) {
3993 if(SMB_VFS_LSEEK(fsp2,fsp2->fd,0,SEEK_END) == -1) {
3994 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
3996 * Stop the copy from occurring.
3998 ret = -1;
3999 src_sbuf.st_size = 0;
4003 if (src_sbuf.st_size)
4004 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
4006 close_file(fsp1,False);
4008 /* Ensure the modtime is set correctly on the destination file. */
4009 fsp2->pending_modtime = src_sbuf.st_mtime;
4012 * As we are opening fsp1 read-only we only expect
4013 * an error on close on fsp2 if we are out of space.
4014 * Thus we don't look at the error return from the
4015 * close of fsp1.
4017 *err_ret = close_file(fsp2,False);
4019 return(ret == (SMB_OFF_T)src_sbuf.st_size);
4022 /****************************************************************************
4023 Reply to a file copy.
4024 ****************************************************************************/
4026 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4028 int outsize = 0;
4029 pstring name;
4030 pstring directory;
4031 pstring mask,newname;
4032 char *p;
4033 int count=0;
4034 int error = ERRnoaccess;
4035 int err = 0;
4036 BOOL has_wild;
4037 BOOL exists=False;
4038 int tid2 = SVAL(inbuf,smb_vwv0);
4039 int ofun = SVAL(inbuf,smb_vwv1);
4040 int flags = SVAL(inbuf,smb_vwv2);
4041 BOOL target_is_directory=False;
4042 BOOL bad_path1 = False;
4043 BOOL bad_path2 = False;
4044 BOOL rc = True;
4045 SMB_STRUCT_STAT sbuf1, sbuf2;
4046 NTSTATUS status;
4048 START_PROFILE(SMBcopy);
4050 *directory = *mask = 0;
4052 p = smb_buf(inbuf);
4053 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status);
4054 if (!NT_STATUS_IS_OK(status)) {
4055 END_PROFILE(SMBcopy);
4056 return ERROR_NT(status);
4058 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status);
4059 if (!NT_STATUS_IS_OK(status)) {
4060 END_PROFILE(SMBcopy);
4061 return ERROR_NT(status);
4064 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
4066 if (tid2 != conn->cnum) {
4067 /* can't currently handle inter share copies XXXX */
4068 DEBUG(3,("Rejecting inter-share copy\n"));
4069 END_PROFILE(SMBcopy);
4070 return ERROR_DOS(ERRSRV,ERRinvdevice);
4073 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
4074 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4076 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
4077 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
4079 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
4081 if ((flags&1) && target_is_directory) {
4082 END_PROFILE(SMBcopy);
4083 return ERROR_DOS(ERRDOS,ERRbadfile);
4086 if ((flags&2) && !target_is_directory) {
4087 END_PROFILE(SMBcopy);
4088 return ERROR_DOS(ERRDOS,ERRbadpath);
4091 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
4092 /* wants a tree copy! XXXX */
4093 DEBUG(3,("Rejecting tree copy\n"));
4094 END_PROFILE(SMBcopy);
4095 return ERROR_DOS(ERRSRV,ERRerror);
4098 p = strrchr_m(name,'/');
4099 if (!p) {
4100 pstrcpy(directory,"./");
4101 pstrcpy(mask,name);
4102 } else {
4103 *p = 0;
4104 pstrcpy(directory,name);
4105 pstrcpy(mask,p+1);
4109 * We should only check the mangled cache
4110 * here if unix_convert failed. This means
4111 * that the path in 'mask' doesn't exist
4112 * on the file system and so we need to look
4113 * for a possible mangle. This patch from
4114 * Tine Smukavec <valentin.smukavec@hermes.si>.
4117 if (!rc && mangle_is_mangled(mask))
4118 mangle_check_cache( mask );
4120 has_wild = ms_has_wild(mask);
4122 if (!has_wild) {
4123 pstrcat(directory,"/");
4124 pstrcat(directory,mask);
4125 if (resolve_wildcards(directory,newname) &&
4126 copy_file(directory,newname,conn,ofun, count,target_is_directory,&err))
4127 count++;
4128 if(!count && err) {
4129 errno = err;
4130 END_PROFILE(SMBcopy);
4131 return(UNIXERROR(ERRHRD,ERRgeneral));
4133 if (!count) {
4134 exists = vfs_file_exist(conn,directory,NULL);
4136 } else {
4137 void *dirptr = NULL;
4138 const char *dname;
4139 pstring destname;
4141 if (check_name(directory,conn))
4142 dirptr = OpenDir(conn, directory, True);
4144 if (dirptr) {
4145 error = ERRbadfile;
4147 if (strequal(mask,"????????.???"))
4148 pstrcpy(mask,"*");
4150 while ((dname = ReadDirName(dirptr))) {
4151 pstring fname;
4152 pstrcpy(fname,dname);
4154 if(!mask_match(fname, mask, case_sensitive))
4155 continue;
4157 error = ERRnoaccess;
4158 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
4159 pstrcpy(destname,newname);
4160 if (resolve_wildcards(fname,destname) &&
4161 copy_file(fname,destname,conn,ofun,
4162 count,target_is_directory,&err))
4163 count++;
4164 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
4166 CloseDir(dirptr);
4170 if (count == 0) {
4171 if(err) {
4172 /* Error on close... */
4173 errno = err;
4174 END_PROFILE(SMBcopy);
4175 return(UNIXERROR(ERRHRD,ERRgeneral));
4178 if (exists) {
4179 END_PROFILE(SMBcopy);
4180 return ERROR_DOS(ERRDOS,error);
4181 } else {
4182 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
4183 unix_ERR_class = ERRDOS;
4184 unix_ERR_code = ERRbadpath;
4186 END_PROFILE(SMBcopy);
4187 return(UNIXERROR(ERRDOS,error));
4191 outsize = set_message(outbuf,1,0,True);
4192 SSVAL(outbuf,smb_vwv0,count);
4194 END_PROFILE(SMBcopy);
4195 return(outsize);
4198 /****************************************************************************
4199 Reply to a setdir.
4200 ****************************************************************************/
4202 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4204 int snum;
4205 int outsize = 0;
4206 BOOL ok = False;
4207 pstring newdir;
4208 NTSTATUS status;
4210 START_PROFILE(pathworks_setdir);
4212 snum = SNUM(conn);
4213 if (!CAN_SETDIR(snum)) {
4214 END_PROFILE(pathworks_setdir);
4215 return ERROR_DOS(ERRDOS,ERRnoaccess);
4218 srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status);
4219 if (!NT_STATUS_IS_OK(status)) {
4220 END_PROFILE(pathworks_setdir);
4221 return ERROR_NT(status);
4224 if (strlen(newdir) == 0) {
4225 ok = True;
4226 } else {
4227 ok = vfs_directory_exist(conn,newdir,NULL);
4228 if (ok)
4229 string_set(&conn->connectpath,newdir);
4232 if (!ok) {
4233 END_PROFILE(pathworks_setdir);
4234 return ERROR_DOS(ERRDOS,ERRbadpath);
4237 outsize = set_message(outbuf,0,0,True);
4238 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
4240 DEBUG(3,("setdir %s\n", newdir));
4242 END_PROFILE(pathworks_setdir);
4243 return(outsize);
4246 /****************************************************************************
4247 Get a lock pid, dealing with large count requests.
4248 ****************************************************************************/
4250 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
4252 if(!large_file_format)
4253 return SVAL(data,SMB_LPID_OFFSET(data_offset));
4254 else
4255 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
4258 /****************************************************************************
4259 Get a lock count, dealing with large count requests.
4260 ****************************************************************************/
4262 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4264 SMB_BIG_UINT count = 0;
4266 if(!large_file_format) {
4267 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4268 } else {
4270 #if defined(HAVE_LONGLONG)
4271 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4272 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4273 #else /* HAVE_LONGLONG */
4276 * NT4.x seems to be broken in that it sends large file (64 bit)
4277 * lockingX calls even if the CAP_LARGE_FILES was *not*
4278 * negotiated. For boxes without large unsigned ints truncate the
4279 * lock count by dropping the top 32 bits.
4282 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4283 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4284 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4285 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4286 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4289 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4290 #endif /* HAVE_LONGLONG */
4293 return count;
4296 #if !defined(HAVE_LONGLONG)
4297 /****************************************************************************
4298 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
4299 ****************************************************************************/
4301 static uint32 map_lock_offset(uint32 high, uint32 low)
4303 unsigned int i;
4304 uint32 mask = 0;
4305 uint32 highcopy = high;
4308 * Try and find out how many significant bits there are in high.
4311 for(i = 0; highcopy; i++)
4312 highcopy >>= 1;
4315 * We use 31 bits not 32 here as POSIX
4316 * lock offsets may not be negative.
4319 mask = (~0) << (31 - i);
4321 if(low & mask)
4322 return 0; /* Fail. */
4324 high <<= (31 - i);
4326 return (high|low);
4328 #endif /* !defined(HAVE_LONGLONG) */
4330 /****************************************************************************
4331 Get a lock offset, dealing with large offset requests.
4332 ****************************************************************************/
4334 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4336 SMB_BIG_UINT offset = 0;
4338 *err = False;
4340 if(!large_file_format) {
4341 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4342 } else {
4344 #if defined(HAVE_LONGLONG)
4345 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4346 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4347 #else /* HAVE_LONGLONG */
4350 * NT4.x seems to be broken in that it sends large file (64 bit)
4351 * lockingX calls even if the CAP_LARGE_FILES was *not*
4352 * negotiated. For boxes without large unsigned ints mangle the
4353 * lock offset by mapping the top 32 bits onto the lower 32.
4356 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4357 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4358 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4359 uint32 new_low = 0;
4361 if((new_low = map_lock_offset(high, low)) == 0) {
4362 *err = True;
4363 return (SMB_BIG_UINT)-1;
4366 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4367 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4368 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4369 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4372 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4373 #endif /* HAVE_LONGLONG */
4376 return offset;
4379 /****************************************************************************
4380 Reply to a lockingX request.
4381 ****************************************************************************/
4383 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4385 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4386 unsigned char locktype = CVAL(inbuf,smb_vwv3);
4387 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4388 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4389 uint16 num_locks = SVAL(inbuf,smb_vwv7);
4390 SMB_BIG_UINT count = 0, offset = 0;
4391 uint16 lock_pid;
4392 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4393 int i;
4394 char *data;
4395 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4396 BOOL err;
4397 BOOL my_lock_ctx = False;
4398 NTSTATUS status;
4400 START_PROFILE(SMBlockingX);
4402 CHECK_FSP(fsp,conn);
4404 data = smb_buf(inbuf);
4406 if (locktype & (LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_CHANGE_LOCKTYPE)) {
4407 /* we don't support these - and CANCEL_LOCK makes w2k
4408 and XP reboot so I don't really want to be
4409 compatible! (tridge) */
4410 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
4413 /* Check if this is an oplock break on a file
4414 we have granted an oplock on.
4416 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
4417 /* Client can insist on breaking to none. */
4418 BOOL break_to_none = (oplocklevel == 0);
4420 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4421 (unsigned int)oplocklevel, fsp->fnum ));
4424 * Make sure we have granted an exclusive or batch oplock on this file.
4427 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
4428 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4429 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4431 /* if this is a pure oplock break request then don't send a reply */
4432 if (num_locks == 0 && num_ulocks == 0) {
4433 END_PROFILE(SMBlockingX);
4434 return -1;
4435 } else {
4436 END_PROFILE(SMBlockingX);
4437 return ERROR_DOS(ERRDOS,ERRlock);
4441 if (remove_oplock(fsp, break_to_none) == False) {
4442 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4443 fsp->fsp_name ));
4446 /* if this is a pure oplock break request then don't send a reply */
4447 if (num_locks == 0 && num_ulocks == 0) {
4448 /* Sanity check - ensure a pure oplock break is not a
4449 chained request. */
4450 if(CVAL(inbuf,smb_vwv0) != 0xff)
4451 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4452 (unsigned int)CVAL(inbuf,smb_vwv0) ));
4453 END_PROFILE(SMBlockingX);
4454 return -1;
4459 * We do this check *after* we have checked this is not a oplock break
4460 * response message. JRA.
4463 release_level_2_oplocks_on_change(fsp);
4465 /* Data now points at the beginning of the list
4466 of smb_unlkrng structs */
4467 for(i = 0; i < (int)num_ulocks; i++) {
4468 lock_pid = get_lock_pid( data, i, large_file_format);
4469 count = get_lock_count( data, i, large_file_format);
4470 offset = get_lock_offset( data, i, large_file_format, &err);
4473 * There is no error code marked "stupid client bug".... :-).
4475 if(err) {
4476 END_PROFILE(SMBlockingX);
4477 return ERROR_DOS(ERRDOS,ERRnoaccess);
4480 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4481 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4483 status = do_unlock(fsp,conn,lock_pid,count,offset);
4484 if (NT_STATUS_V(status)) {
4485 END_PROFILE(SMBlockingX);
4486 return ERROR_NT(status);
4490 /* Setup the timeout in seconds. */
4492 lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000);
4494 /* Now do any requested locks */
4495 data += ((large_file_format ? 20 : 10)*num_ulocks);
4497 /* Data now points at the beginning of the list
4498 of smb_lkrng structs */
4500 for(i = 0; i < (int)num_locks; i++) {
4501 lock_pid = get_lock_pid( data, i, large_file_format);
4502 count = get_lock_count( data, i, large_file_format);
4503 offset = get_lock_offset( data, i, large_file_format, &err);
4506 * There is no error code marked "stupid client bug".... :-).
4508 if(err) {
4509 END_PROFILE(SMBlockingX);
4510 return ERROR_DOS(ERRDOS,ERRnoaccess);
4513 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
4514 (double)offset, (double)count, (unsigned int)lock_pid,
4515 fsp->fsp_name, (int)lock_timeout ));
4517 status = do_lock_spin(fsp,conn,lock_pid, count,offset,
4518 ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &my_lock_ctx);
4519 if (NT_STATUS_V(status)) {
4521 * Interesting fact found by IFSTEST /t LockOverlappedTest...
4522 * Even if it's our own lock context, we need to wait here as
4523 * there may be an unlock on the way.
4524 * So I removed a "&& !my_lock_ctx" from the following
4525 * if statement. JRA.
4527 if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
4529 * A blocking lock was requested. Package up
4530 * this smb into a queued request and push it
4531 * onto the blocking lock queue.
4533 if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) {
4534 END_PROFILE(SMBlockingX);
4535 return -1;
4538 break;
4542 /* If any of the above locks failed, then we must unlock
4543 all of the previous locks (X/Open spec). */
4544 if (i != num_locks && num_locks != 0) {
4546 * Ensure we don't do a remove on the lock that just failed,
4547 * as under POSIX rules, if we have a lock already there, we
4548 * will delete it (and we shouldn't) .....
4550 for(i--; i >= 0; i--) {
4551 lock_pid = get_lock_pid( data, i, large_file_format);
4552 count = get_lock_count( data, i, large_file_format);
4553 offset = get_lock_offset( data, i, large_file_format, &err);
4556 * There is no error code marked "stupid client bug".... :-).
4558 if(err) {
4559 END_PROFILE(SMBlockingX);
4560 return ERROR_DOS(ERRDOS,ERRnoaccess);
4563 do_unlock(fsp,conn,lock_pid,count,offset);
4565 END_PROFILE(SMBlockingX);
4566 return ERROR_NT(status);
4569 set_message(outbuf,2,0,True);
4571 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4572 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4574 END_PROFILE(SMBlockingX);
4575 return chain_reply(inbuf,outbuf,length,bufsize);
4578 /****************************************************************************
4579 Reply to a SMBreadbmpx (read block multiplex) request.
4580 ****************************************************************************/
4582 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4584 ssize_t nread = -1;
4585 ssize_t total_read;
4586 char *data;
4587 SMB_OFF_T startpos;
4588 int outsize;
4589 size_t maxcount;
4590 int max_per_packet;
4591 size_t tcount;
4592 int pad;
4593 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4594 START_PROFILE(SMBreadBmpx);
4596 /* this function doesn't seem to work - disable by default */
4597 if (!lp_readbmpx()) {
4598 END_PROFILE(SMBreadBmpx);
4599 return ERROR_DOS(ERRSRV,ERRuseSTD);
4602 outsize = set_message(outbuf,8,0,True);
4604 CHECK_FSP(fsp,conn);
4605 CHECK_READ(fsp);
4607 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
4608 maxcount = SVAL(inbuf,smb_vwv3);
4610 data = smb_buf(outbuf);
4611 pad = ((long)data)%4;
4612 if (pad)
4613 pad = 4 - pad;
4614 data += pad;
4616 max_per_packet = bufsize-(outsize+pad);
4617 tcount = maxcount;
4618 total_read = 0;
4620 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
4621 END_PROFILE(SMBreadBmpx);
4622 return ERROR_DOS(ERRDOS,ERRlock);
4625 do {
4626 size_t N = MIN(max_per_packet,tcount-total_read);
4628 nread = read_file(fsp,data,startpos,N);
4630 if (nread <= 0)
4631 nread = 0;
4633 if (nread < (ssize_t)N)
4634 tcount = total_read + nread;
4636 set_message(outbuf,8,nread,False);
4637 SIVAL(outbuf,smb_vwv0,startpos);
4638 SSVAL(outbuf,smb_vwv2,tcount);
4639 SSVAL(outbuf,smb_vwv6,nread);
4640 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4642 if (!send_smb(smbd_server_fd(),outbuf))
4643 exit_server("reply_readbmpx: send_smb failed.");
4645 total_read += nread;
4646 startpos += nread;
4647 } while (total_read < (ssize_t)tcount);
4649 END_PROFILE(SMBreadBmpx);
4650 return(-1);
4653 /****************************************************************************
4654 Reply to a SMBsetattrE.
4655 ****************************************************************************/
4657 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4659 struct utimbuf unix_times;
4660 int outsize = 0;
4661 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4662 START_PROFILE(SMBsetattrE);
4664 outsize = set_message(outbuf,0,0,True);
4666 if(!fsp || (fsp->conn != conn)) {
4667 END_PROFILE(SMBgetattrE);
4668 return ERROR_DOS(ERRDOS,ERRbadfid);
4672 * Convert the DOS times into unix times. Ignore create
4673 * time as UNIX can't set this.
4676 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4677 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4680 * Patch from Ray Frush <frush@engr.colostate.edu>
4681 * Sometimes times are sent as zero - ignore them.
4684 if ((unix_times.actime == 0) && (unix_times.modtime == 0)) {
4685 /* Ignore request */
4686 if( DEBUGLVL( 3 ) ) {
4687 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4688 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4690 END_PROFILE(SMBsetattrE);
4691 return(outsize);
4692 } else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) {
4693 /* set modify time = to access time if modify time was 0 */
4694 unix_times.modtime = unix_times.actime;
4697 /* Set the date on this file */
4698 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4699 END_PROFILE(SMBsetattrE);
4700 return ERROR_DOS(ERRDOS,ERRnoaccess);
4703 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4704 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4706 END_PROFILE(SMBsetattrE);
4707 return(outsize);
4711 /* Back from the dead for OS/2..... JRA. */
4713 /****************************************************************************
4714 Reply to a SMBwritebmpx (write block multiplex primary) request.
4715 ****************************************************************************/
4717 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4719 size_t numtowrite;
4720 ssize_t nwritten = -1;
4721 int outsize = 0;
4722 SMB_OFF_T startpos;
4723 size_t tcount;
4724 BOOL write_through;
4725 int smb_doff;
4726 char *data;
4727 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4728 START_PROFILE(SMBwriteBmpx);
4730 CHECK_FSP(fsp,conn);
4731 CHECK_WRITE(fsp);
4732 CHECK_ERROR(fsp);
4734 tcount = SVAL(inbuf,smb_vwv1);
4735 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
4736 write_through = BITSETW(inbuf+smb_vwv7,0);
4737 numtowrite = SVAL(inbuf,smb_vwv10);
4738 smb_doff = SVAL(inbuf,smb_vwv11);
4740 data = smb_base(inbuf) + smb_doff;
4742 /* If this fails we need to send an SMBwriteC response,
4743 not an SMBwritebmpx - set this up now so we don't forget */
4744 SCVAL(outbuf,smb_com,SMBwritec);
4746 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK,False)) {
4747 END_PROFILE(SMBwriteBmpx);
4748 return(ERROR_DOS(ERRDOS,ERRlock));
4751 nwritten = write_file(fsp,data,startpos,numtowrite);
4753 if(lp_syncalways(SNUM(conn)) || write_through)
4754 sync_file(conn,fsp);
4756 if(nwritten < (ssize_t)numtowrite) {
4757 END_PROFILE(SMBwriteBmpx);
4758 return(UNIXERROR(ERRHRD,ERRdiskfull));
4761 /* If the maximum to be written to this file
4762 is greater than what we just wrote then set
4763 up a secondary struct to be attached to this
4764 fd, we will use this to cache error messages etc. */
4766 if((ssize_t)tcount > nwritten) {
4767 write_bmpx_struct *wbms;
4768 if(fsp->wbmpx_ptr != NULL)
4769 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4770 else
4771 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
4772 if(!wbms) {
4773 DEBUG(0,("Out of memory in reply_readmpx\n"));
4774 END_PROFILE(SMBwriteBmpx);
4775 return(ERROR_DOS(ERRSRV,ERRnoresource));
4777 wbms->wr_mode = write_through;
4778 wbms->wr_discard = False; /* No errors yet */
4779 wbms->wr_total_written = nwritten;
4780 wbms->wr_errclass = 0;
4781 wbms->wr_error = 0;
4782 fsp->wbmpx_ptr = wbms;
4785 /* We are returning successfully, set the message type back to
4786 SMBwritebmpx */
4787 SCVAL(outbuf,smb_com,SMBwriteBmpx);
4789 outsize = set_message(outbuf,1,0,True);
4791 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
4793 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4794 fsp->fnum, (int)numtowrite, (int)nwritten ) );
4796 if (write_through && tcount==nwritten) {
4797 /* We need to send both a primary and a secondary response */
4798 smb_setlen(outbuf,outsize - 4);
4799 if (!send_smb(smbd_server_fd(),outbuf))
4800 exit_server("reply_writebmpx: send_smb failed.");
4802 /* Now the secondary */
4803 outsize = set_message(outbuf,1,0,True);
4804 SCVAL(outbuf,smb_com,SMBwritec);
4805 SSVAL(outbuf,smb_vwv0,nwritten);
4808 END_PROFILE(SMBwriteBmpx);
4809 return(outsize);
4812 /****************************************************************************
4813 Reply to a SMBwritebs (write block multiplex secondary) request.
4814 ****************************************************************************/
4816 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4818 size_t numtowrite;
4819 ssize_t nwritten = -1;
4820 int outsize = 0;
4821 SMB_OFF_T startpos;
4822 size_t tcount;
4823 BOOL write_through;
4824 int smb_doff;
4825 char *data;
4826 write_bmpx_struct *wbms;
4827 BOOL send_response = False;
4828 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4829 START_PROFILE(SMBwriteBs);
4831 CHECK_FSP(fsp,conn);
4832 CHECK_WRITE(fsp);
4834 tcount = SVAL(inbuf,smb_vwv1);
4835 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
4836 numtowrite = SVAL(inbuf,smb_vwv6);
4837 smb_doff = SVAL(inbuf,smb_vwv7);
4839 data = smb_base(inbuf) + smb_doff;
4841 /* We need to send an SMBwriteC response, not an SMBwritebs */
4842 SCVAL(outbuf,smb_com,SMBwritec);
4844 /* This fd should have an auxiliary struct attached,
4845 check that it does */
4846 wbms = fsp->wbmpx_ptr;
4847 if(!wbms) {
4848 END_PROFILE(SMBwriteBs);
4849 return(-1);
4852 /* If write through is set we can return errors, else we must cache them */
4853 write_through = wbms->wr_mode;
4855 /* Check for an earlier error */
4856 if(wbms->wr_discard) {
4857 END_PROFILE(SMBwriteBs);
4858 return -1; /* Just discard the packet */
4861 nwritten = write_file(fsp,data,startpos,numtowrite);
4863 if(lp_syncalways(SNUM(conn)) || write_through)
4864 sync_file(conn,fsp);
4866 if (nwritten < (ssize_t)numtowrite) {
4867 if(write_through) {
4868 /* We are returning an error - we can delete the aux struct */
4869 if (wbms)
4870 free((char *)wbms);
4871 fsp->wbmpx_ptr = NULL;
4872 END_PROFILE(SMBwriteBs);
4873 return(ERROR_DOS(ERRHRD,ERRdiskfull));
4875 END_PROFILE(SMBwriteBs);
4876 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4879 /* Increment the total written, if this matches tcount
4880 we can discard the auxiliary struct (hurrah !) and return a writeC */
4881 wbms->wr_total_written += nwritten;
4882 if(wbms->wr_total_written >= tcount) {
4883 if (write_through) {
4884 outsize = set_message(outbuf,1,0,True);
4885 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
4886 send_response = True;
4889 free((char *)wbms);
4890 fsp->wbmpx_ptr = NULL;
4893 if(send_response) {
4894 END_PROFILE(SMBwriteBs);
4895 return(outsize);
4898 END_PROFILE(SMBwriteBs);
4899 return(-1);
4902 /****************************************************************************
4903 Reply to a SMBgetattrE.
4904 ****************************************************************************/
4906 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4908 SMB_STRUCT_STAT sbuf;
4909 int outsize = 0;
4910 int mode;
4911 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4912 START_PROFILE(SMBgetattrE);
4914 outsize = set_message(outbuf,11,0,True);
4916 if(!fsp || (fsp->conn != conn)) {
4917 END_PROFILE(SMBgetattrE);
4918 return ERROR_DOS(ERRDOS,ERRbadfid);
4921 /* Do an fstat on this file */
4922 if(fsp_stat(fsp, &sbuf)) {
4923 END_PROFILE(SMBgetattrE);
4924 return(UNIXERROR(ERRDOS,ERRnoaccess));
4927 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4930 * Convert the times into dos times. Set create
4931 * date to be last modify date as UNIX doesn't save
4932 * this.
4935 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4936 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4937 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4939 if (mode & aDIR) {
4940 SIVAL(outbuf,smb_vwv6,0);
4941 SIVAL(outbuf,smb_vwv8,0);
4942 } else {
4943 uint32 allocation_size = get_allocation_size(fsp, &sbuf);
4944 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4945 SIVAL(outbuf,smb_vwv8,allocation_size);
4947 SSVAL(outbuf,smb_vwv10, mode);
4949 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
4951 END_PROFILE(SMBgetattrE);
4952 return(outsize);