Fix build farm, older compilers won't let you declare variables
[Samba/gbeck.git] / source / smbd / reply.c
blobc0d5234f472e721f7073b3add26606877ffe0001
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 static 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 2 byte char won't convert then
118 * it's probably a one byte char with a real directory separator
119 * following, so only copy one byte. If it will convert then
120 * copy both bytes.
122 uint16 ucs2_val;
123 if (convert_string(CH_UNIX, CH_UCS2, s, 2, &ucs2_val, 2) == 2) {
124 *d++ = *s++;
127 /* Just copy the char (or the second byte of the mb char). */
128 *d++ = *s++;
131 *d = '\0';
132 return ret;
135 /****************************************************************************
136 Pull a string and check the path - provide for error return.
137 ****************************************************************************/
139 size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags, NTSTATUS *err)
141 pstring tmppath;
142 char *tmppath_ptr = tmppath;
143 #ifdef DEVELOPER
144 SMB_ASSERT(dest_len == sizeof(pstring));
145 #endif
146 size_t ret;
148 if (src_len == 0) {
149 ret = srvstr_pull_buf( inbuf, tmppath_ptr, src, dest_len, flags);
150 } else {
151 ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags);
153 *err = check_path_syntax(dest, tmppath);
154 return ret;
157 /****************************************************************************
158 Reply to a special message.
159 ****************************************************************************/
161 int reply_special(char *inbuf,char *outbuf)
163 int outsize = 4;
164 int msg_type = CVAL(inbuf,0);
165 int msg_flags = CVAL(inbuf,1);
166 pstring name1,name2;
167 char name_type = 0;
169 static BOOL already_got_session = False;
171 *name1 = *name2 = 0;
173 memset(outbuf,'\0',smb_size);
175 smb_setlen(outbuf,0);
177 switch (msg_type) {
178 case 0x81: /* session request */
180 if (already_got_session) {
181 exit_server("multiple session request not permitted");
184 SCVAL(outbuf,0,0x82);
185 SCVAL(outbuf,3,0);
186 if (name_len(inbuf+4) > 50 ||
187 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
188 DEBUG(0,("Invalid name length in session request\n"));
189 return(0);
191 name_extract(inbuf,4,name1);
192 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
193 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
194 name1,name2));
196 set_local_machine_name(name1, True);
197 set_remote_machine_name(name2, True);
199 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
200 get_local_machine_name(), get_remote_machine_name(),
201 name_type));
203 if (name_type == 'R') {
204 /* We are being asked for a pathworks session ---
205 no thanks! */
206 SCVAL(outbuf, 0,0x83);
207 break;
210 /* only add the client's machine name to the list
211 of possibly valid usernames if we are operating
212 in share mode security */
213 if (lp_security() == SEC_SHARE) {
214 add_session_user(get_remote_machine_name());
217 reload_services(True);
218 reopen_logs();
220 claim_connection(NULL,"",0,True,FLAG_MSG_GENERAL|FLAG_MSG_SMBD);
222 already_got_session = True;
223 break;
225 case 0x89: /* session keepalive request
226 (some old clients produce this?) */
227 SCVAL(outbuf,0,SMBkeepalive);
228 SCVAL(outbuf,3,0);
229 break;
231 case 0x82: /* positive session response */
232 case 0x83: /* negative session response */
233 case 0x84: /* retarget session response */
234 DEBUG(0,("Unexpected session response\n"));
235 break;
237 case SMBkeepalive: /* session keepalive */
238 default:
239 return(0);
242 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
243 msg_type, msg_flags));
245 return(outsize);
248 /****************************************************************************
249 Reply to a tcon.
250 ****************************************************************************/
252 int reply_tcon(connection_struct *conn,
253 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
255 const char *service;
256 pstring service_buf;
257 pstring password;
258 pstring dev;
259 int outsize = 0;
260 uint16 vuid = SVAL(inbuf,smb_uid);
261 int pwlen=0;
262 NTSTATUS nt_status;
263 char *p;
264 DATA_BLOB password_blob;
266 START_PROFILE(SMBtcon);
268 *service_buf = *password = *dev = 0;
270 p = smb_buf(inbuf)+1;
271 p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service_buf), STR_TERMINATE) + 1;
272 pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1;
273 p += pwlen;
274 p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1;
276 p = strrchr_m(service_buf,'\\');
277 if (p) {
278 service = p+1;
279 } else {
280 service = service_buf;
283 password_blob = data_blob(password, pwlen+1);
285 conn = make_connection(service,password_blob,dev,vuid,&nt_status);
287 data_blob_clear_free(&password_blob);
289 if (!conn) {
290 END_PROFILE(SMBtcon);
291 return ERROR_NT(nt_status);
294 outsize = set_message(outbuf,2,0,True);
295 SSVAL(outbuf,smb_vwv0,max_recv);
296 SSVAL(outbuf,smb_vwv1,conn->cnum);
297 SSVAL(outbuf,smb_tid,conn->cnum);
299 DEBUG(3,("tcon service=%s cnum=%d\n",
300 service, conn->cnum));
302 END_PROFILE(SMBtcon);
303 return(outsize);
306 /****************************************************************************
307 Reply to a tcon and X.
308 ****************************************************************************/
310 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
312 fstring service;
313 DATA_BLOB password;
315 /* what the cleint thinks the device is */
316 fstring client_devicetype;
317 /* what the server tells the client the share represents */
318 const char *server_devicetype;
319 NTSTATUS nt_status;
320 uint16 vuid = SVAL(inbuf,smb_uid);
321 int passlen = SVAL(inbuf,smb_vwv3);
322 pstring path;
323 char *p, *q;
324 extern BOOL global_encrypted_passwords_negotiated;
326 START_PROFILE(SMBtconX);
328 *service = *client_devicetype = 0;
330 /* we might have to close an old one */
331 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
332 close_cnum(conn,vuid);
335 if (passlen > MAX_PASS_LEN) {
336 return ERROR_DOS(ERRDOS,ERRbuftoosmall);
339 if (global_encrypted_passwords_negotiated) {
340 password = data_blob(smb_buf(inbuf),passlen);
341 } else {
342 password = data_blob(smb_buf(inbuf),passlen+1);
343 /* Ensure correct termination */
344 password.data[passlen]=0;
347 p = smb_buf(inbuf) + passlen;
348 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
351 * the service name can be either: \\server\share
352 * or share directly like on the DELL PowerVault 705
354 if (*path=='\\') {
355 q = strchr_m(path+2,'\\');
356 if (!q) {
357 END_PROFILE(SMBtconX);
358 return(ERROR_DOS(ERRDOS,ERRnosuchshare));
360 fstrcpy(service,q+1);
362 else
363 fstrcpy(service,path);
365 p += srvstr_pull(inbuf, client_devicetype, p, sizeof(client_devicetype), 6, STR_ASCII);
367 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
369 conn = make_connection(service,password,client_devicetype,vuid,&nt_status);
371 data_blob_clear_free(&password);
373 if (!conn) {
374 END_PROFILE(SMBtconX);
375 return ERROR_NT(nt_status);
378 if ( IS_IPC(conn) )
379 server_devicetype = "IPC";
380 else if ( IS_PRINT(conn) )
381 server_devicetype = "LPT1:";
382 else
383 server_devicetype = "A:";
385 if (Protocol < PROTOCOL_NT1) {
386 set_message(outbuf,2,0,True);
387 p = smb_buf(outbuf);
388 p += srvstr_push(outbuf, p, server_devicetype, -1,
389 STR_TERMINATE|STR_ASCII);
390 set_message_end(outbuf,p);
391 } else {
392 /* NT sets the fstype of IPC$ to the null string */
393 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
395 set_message(outbuf,3,0,True);
397 p = smb_buf(outbuf);
398 p += srvstr_push(outbuf, p, server_devicetype, -1,
399 STR_TERMINATE|STR_ASCII);
400 p += srvstr_push(outbuf, p, fstype, -1,
401 STR_TERMINATE);
403 set_message_end(outbuf,p);
405 /* what does setting this bit do? It is set by NT4 and
406 may affect the ability to autorun mounted cdroms */
407 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
408 (lp_csc_policy(SNUM(conn)) << 2));
410 init_dfsroot(conn, inbuf, outbuf);
414 DEBUG(3,("tconX service=%s \n",
415 service));
417 /* set the incoming and outgoing tid to the just created one */
418 SSVAL(inbuf,smb_tid,conn->cnum);
419 SSVAL(outbuf,smb_tid,conn->cnum);
421 END_PROFILE(SMBtconX);
422 return chain_reply(inbuf,outbuf,length,bufsize);
425 /****************************************************************************
426 Reply to an unknown type.
427 ****************************************************************************/
429 int reply_unknown(char *inbuf,char *outbuf)
431 int type;
432 type = CVAL(inbuf,smb_com);
434 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
435 smb_fn_name(type), type, type));
437 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
440 /****************************************************************************
441 Reply to an ioctl.
442 ****************************************************************************/
444 int reply_ioctl(connection_struct *conn,
445 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
447 uint16 device = SVAL(inbuf,smb_vwv1);
448 uint16 function = SVAL(inbuf,smb_vwv2);
449 uint32 ioctl_code = (device << 16) + function;
450 int replysize, outsize;
451 char *p;
452 START_PROFILE(SMBioctl);
454 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
456 switch (ioctl_code) {
457 case IOCTL_QUERY_JOB_INFO:
458 replysize = 32;
459 break;
460 default:
461 END_PROFILE(SMBioctl);
462 return(ERROR_DOS(ERRSRV,ERRnosupport));
465 outsize = set_message(outbuf,8,replysize+1,True);
466 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
467 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
468 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
469 p = smb_buf(outbuf) + 1; /* Allow for alignment */
471 switch (ioctl_code) {
472 case IOCTL_QUERY_JOB_INFO:
474 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
475 if (!fsp) {
476 END_PROFILE(SMBioctl);
477 return(UNIXERROR(ERRDOS,ERRbadfid));
479 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
480 srvstr_push(outbuf, p+2, global_myname(), 15, STR_TERMINATE|STR_ASCII);
481 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
482 break;
486 END_PROFILE(SMBioctl);
487 return outsize;
490 /****************************************************************************
491 Reply to a chkpth.
492 ****************************************************************************/
494 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
496 int outsize = 0;
497 int mode;
498 pstring name;
499 BOOL ok = False;
500 BOOL bad_path = False;
501 SMB_STRUCT_STAT sbuf;
502 NTSTATUS status;
504 START_PROFILE(SMBchkpth);
506 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
507 if (!NT_STATUS_IS_OK(status)) {
508 END_PROFILE(SMBchkpth);
509 return ERROR_NT(status);
512 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
514 unix_convert(name,conn,0,&bad_path,&sbuf);
516 mode = SVAL(inbuf,smb_vwv0);
518 if (check_name(name,conn)) {
519 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,name,&sbuf) == 0)
520 if (!(ok = S_ISDIR(sbuf.st_mode))) {
521 END_PROFILE(SMBchkpth);
522 return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath);
526 if (!ok) {
527 /* We special case this - as when a Windows machine
528 is parsing a path is steps through the components
529 one at a time - if a component fails it expects
530 ERRbadpath, not ERRbadfile.
532 if(errno == ENOENT) {
534 * Windows returns different error codes if
535 * the parent directory is valid but not the
536 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
537 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
538 * if the path is invalid.
540 if (bad_path) {
541 END_PROFILE(SMBchkpth);
542 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
543 } else {
544 END_PROFILE(SMBchkpth);
545 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
547 } else if (errno == ENOTDIR) {
548 END_PROFILE(SMBchkpth);
549 return ERROR_NT(NT_STATUS_NOT_A_DIRECTORY);
552 END_PROFILE(SMBchkpth);
553 return(UNIXERROR(ERRDOS,ERRbadpath));
556 outsize = set_message(outbuf,0,0,True);
558 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
560 END_PROFILE(SMBchkpth);
561 return(outsize);
564 /****************************************************************************
565 Reply to a getatr.
566 ****************************************************************************/
568 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
570 pstring fname;
571 int outsize = 0;
572 SMB_STRUCT_STAT sbuf;
573 BOOL ok = False;
574 int mode=0;
575 SMB_OFF_T size=0;
576 time_t mtime=0;
577 BOOL bad_path = False;
578 char *p;
579 NTSTATUS status;
581 START_PROFILE(SMBgetatr);
583 p = smb_buf(inbuf) + 1;
584 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
585 if (!NT_STATUS_IS_OK(status)) {
586 END_PROFILE(SMBgetatr);
587 return ERROR_NT(status);
590 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
592 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
593 under WfWg - weird! */
594 if (! (*fname)) {
595 mode = aHIDDEN | aDIR;
596 if (!CAN_WRITE(conn))
597 mode |= aRONLY;
598 size = 0;
599 mtime = 0;
600 ok = True;
601 } else {
602 unix_convert(fname,conn,0,&bad_path,&sbuf);
603 if (check_name(fname,conn)) {
604 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,fname,&sbuf) == 0) {
605 mode = dos_mode(conn,fname,&sbuf);
606 size = sbuf.st_size;
607 mtime = sbuf.st_mtime;
608 if (mode & aDIR)
609 size = 0;
610 ok = True;
611 } else {
612 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
617 if (!ok) {
618 END_PROFILE(SMBgetatr);
619 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadfile);
622 outsize = set_message(outbuf,10,0,True);
624 SSVAL(outbuf,smb_vwv0,mode);
625 if(lp_dos_filetime_resolution(SNUM(conn)) )
626 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
627 else
628 put_dos_date3(outbuf,smb_vwv1,mtime);
629 SIVAL(outbuf,smb_vwv3,(uint32)size);
631 if (Protocol >= PROTOCOL_NT1)
632 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
634 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
636 END_PROFILE(SMBgetatr);
637 return(outsize);
640 /****************************************************************************
641 Reply to a setatr.
642 ****************************************************************************/
644 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
646 pstring fname;
647 int outsize = 0;
648 BOOL ok=False;
649 int mode;
650 time_t mtime;
651 SMB_STRUCT_STAT sbuf;
652 BOOL bad_path = False;
653 char *p;
654 NTSTATUS status;
656 START_PROFILE(SMBsetatr);
658 p = smb_buf(inbuf) + 1;
659 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
660 if (!NT_STATUS_IS_OK(status)) {
661 END_PROFILE(SMBsetatr);
662 return ERROR_NT(status);
665 unix_convert(fname,conn,0,&bad_path,&sbuf);
667 mode = SVAL(inbuf,smb_vwv0);
668 mtime = make_unix_date3(inbuf+smb_vwv1);
670 if (mode != FILE_ATTRIBUTE_NORMAL) {
671 if (VALID_STAT_OF_DIR(sbuf))
672 mode |= aDIR;
673 else
674 mode &= ~aDIR;
676 if (check_name(fname,conn))
677 ok = (file_chmod(conn,fname,mode,NULL) == 0);
678 } else {
679 ok = True;
682 if (ok)
683 ok = set_filetime(conn,fname,mtime);
685 if (!ok) {
686 END_PROFILE(SMBsetatr);
687 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
690 outsize = set_message(outbuf,0,0,True);
692 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
694 END_PROFILE(SMBsetatr);
695 return(outsize);
698 /****************************************************************************
699 Reply to a dskattr.
700 ****************************************************************************/
702 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
704 int outsize = 0;
705 SMB_BIG_UINT dfree,dsize,bsize;
706 START_PROFILE(SMBdskattr);
708 SMB_VFS_DISK_FREE(conn,".",True,&bsize,&dfree,&dsize);
710 outsize = set_message(outbuf,5,0,True);
712 if (Protocol <= PROTOCOL_LANMAN2) {
713 double total_space, free_space;
714 /* we need to scale this to a number that DOS6 can handle. We
715 use floating point so we can handle large drives on systems
716 that don't have 64 bit integers
718 we end up displaying a maximum of 2G to DOS systems
720 total_space = dsize * (double)bsize;
721 free_space = dfree * (double)bsize;
723 dsize = (total_space+63*512) / (64*512);
724 dfree = (free_space+63*512) / (64*512);
726 if (dsize > 0xFFFF) dsize = 0xFFFF;
727 if (dfree > 0xFFFF) dfree = 0xFFFF;
729 SSVAL(outbuf,smb_vwv0,dsize);
730 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
731 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
732 SSVAL(outbuf,smb_vwv3,dfree);
733 } else {
734 SSVAL(outbuf,smb_vwv0,dsize);
735 SSVAL(outbuf,smb_vwv1,bsize/512);
736 SSVAL(outbuf,smb_vwv2,512);
737 SSVAL(outbuf,smb_vwv3,dfree);
740 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
742 END_PROFILE(SMBdskattr);
743 return(outsize);
746 /****************************************************************************
747 Reply to a search.
748 Can be called from SMBsearch, SMBffirst or SMBfunique.
749 ****************************************************************************/
751 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
753 pstring mask;
754 pstring directory;
755 pstring fname;
756 SMB_OFF_T size;
757 int mode;
758 time_t date;
759 int dirtype;
760 int outsize = 0;
761 unsigned int numentries = 0;
762 unsigned int maxentries = 0;
763 BOOL finished = False;
764 char *p;
765 BOOL ok = False;
766 int status_len;
767 pstring path;
768 char status[21];
769 int dptr_num= -1;
770 BOOL check_descend = False;
771 BOOL expect_close = False;
772 BOOL can_open = True;
773 BOOL bad_path = False;
774 NTSTATUS nt_status;
775 START_PROFILE(SMBsearch);
777 *mask = *directory = *fname = 0;
779 /* If we were called as SMBffirst then we must expect close. */
780 if(CVAL(inbuf,smb_com) == SMBffirst)
781 expect_close = True;
783 outsize = set_message(outbuf,1,3,True);
784 maxentries = SVAL(inbuf,smb_vwv0);
785 dirtype = SVAL(inbuf,smb_vwv1);
786 p = smb_buf(inbuf) + 1;
787 p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &nt_status);
788 if (!NT_STATUS_IS_OK(nt_status)) {
789 END_PROFILE(SMBsearch);
790 return ERROR_NT(nt_status);
792 p++;
793 status_len = SVAL(p, 0);
794 p += 2;
796 /* dirtype &= ~aDIR; */
798 if (status_len == 0) {
799 SMB_STRUCT_STAT sbuf;
800 pstring dir2;
802 pstrcpy(directory,path);
803 pstrcpy(dir2,path);
804 unix_convert(directory,conn,0,&bad_path,&sbuf);
805 unix_format(dir2);
807 if (!check_name(directory,conn))
808 can_open = False;
810 p = strrchr_m(dir2,'/');
811 if (p == NULL) {
812 pstrcpy(mask,dir2);
813 *dir2 = 0;
814 } else {
815 *p = 0;
816 pstrcpy(mask,p+1);
819 p = strrchr_m(directory,'/');
820 if (!p)
821 *directory = 0;
822 else
823 *p = 0;
825 if (strlen(directory) == 0)
826 pstrcpy(directory,".");
827 memset((char *)status,'\0',21);
828 SCVAL(status,0,(dirtype & 0x1F));
829 } else {
830 int status_dirtype;
832 memcpy(status,p,21);
833 status_dirtype = CVAL(status,0) & 0x1F;
834 if (status_dirtype != (dirtype & 0x1F))
835 dirtype = status_dirtype;
837 conn->dirptr = dptr_fetch(status+12,&dptr_num);
838 if (!conn->dirptr)
839 goto SearchEmpty;
840 string_set(&conn->dirpath,dptr_path(dptr_num));
841 pstrcpy(mask, dptr_wcard(dptr_num));
844 if (can_open) {
845 p = smb_buf(outbuf) + 3;
846 ok = True;
848 if (status_len == 0) {
849 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
850 if (dptr_num < 0) {
851 if(dptr_num == -2) {
852 END_PROFILE(SMBsearch);
853 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnofids);
855 END_PROFILE(SMBsearch);
856 return ERROR_DOS(ERRDOS,ERRnofids);
858 dptr_set_wcard(dptr_num, strdup(mask));
859 dptr_set_attr(dptr_num, dirtype);
860 } else {
861 dirtype = dptr_attr(dptr_num);
864 DEBUG(4,("dptr_num is %d\n",dptr_num));
866 if (ok) {
867 if ((dirtype&0x1F) == aVOLID) {
868 memcpy(p,status,21);
869 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
870 dptr_fill(p+12,dptr_num);
871 if (dptr_zero(p+12) && (status_len==0))
872 numentries = 1;
873 else
874 numentries = 0;
875 p += DIR_STRUCT_SIZE;
876 } else {
877 unsigned int i;
878 maxentries = MIN(maxentries, ((BUFFER_SIZE - (p - outbuf))/DIR_STRUCT_SIZE));
880 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
881 conn->dirpath,lp_dontdescend(SNUM(conn))));
882 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
883 check_descend = True;
885 for (i=numentries;(i<maxentries) && !finished;i++) {
886 finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
887 if (!finished) {
888 memcpy(p,status,21);
889 make_dir_struct(p,mask,fname,size,mode,date);
890 dptr_fill(p+12,dptr_num);
891 numentries++;
893 p += DIR_STRUCT_SIZE;
896 } /* if (ok ) */
900 SearchEmpty:
902 /* If we were called as SMBffirst with smb_search_id == NULL
903 and no entries were found then return error and close dirptr
904 (X/Open spec) */
906 if(ok && expect_close && numentries == 0 && status_len == 0) {
907 if (Protocol < PROTOCOL_NT1) {
908 SCVAL(outbuf,smb_rcls,ERRDOS);
909 SSVAL(outbuf,smb_err,ERRnofiles);
911 /* Also close the dptr - we know it's gone */
912 dptr_close(&dptr_num);
913 } else if (numentries == 0 || !ok) {
914 if (Protocol < PROTOCOL_NT1) {
915 SCVAL(outbuf,smb_rcls,ERRDOS);
916 SSVAL(outbuf,smb_err,ERRnofiles);
918 dptr_close(&dptr_num);
921 /* If we were called as SMBfunique, then we can close the dirptr now ! */
922 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
923 dptr_close(&dptr_num);
925 SSVAL(outbuf,smb_vwv0,numentries);
926 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
927 SCVAL(smb_buf(outbuf),0,5);
928 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
930 if (Protocol >= PROTOCOL_NT1)
931 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
933 outsize += DIR_STRUCT_SIZE*numentries;
934 smb_setlen(outbuf,outsize - 4);
936 if ((! *directory) && dptr_path(dptr_num))
937 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
939 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
940 smb_fn_name(CVAL(inbuf,smb_com)),
941 mask, directory, dirtype, numentries, maxentries ) );
943 END_PROFILE(SMBsearch);
944 return(outsize);
947 /****************************************************************************
948 Reply to a fclose (stop directory search).
949 ****************************************************************************/
951 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
953 int outsize = 0;
954 int status_len;
955 pstring path;
956 char status[21];
957 int dptr_num= -2;
958 char *p;
959 NTSTATUS err;
961 START_PROFILE(SMBfclose);
963 outsize = set_message(outbuf,1,0,True);
964 p = smb_buf(inbuf) + 1;
965 p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err);
966 if (!NT_STATUS_IS_OK(err)) {
967 END_PROFILE(SMBfclose);
968 return ERROR_NT(err);
970 p++;
971 status_len = SVAL(p,0);
972 p += 2;
974 if (status_len == 0) {
975 END_PROFILE(SMBfclose);
976 return ERROR_DOS(ERRSRV,ERRsrverror);
979 memcpy(status,p,21);
981 if(dptr_fetch(status+12,&dptr_num)) {
982 /* Close the dptr - we know it's gone */
983 dptr_close(&dptr_num);
986 SSVAL(outbuf,smb_vwv0,0);
988 DEBUG(3,("search close\n"));
990 END_PROFILE(SMBfclose);
991 return(outsize);
994 /****************************************************************************
995 Reply to an open.
996 ****************************************************************************/
998 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1000 pstring fname;
1001 int outsize = 0;
1002 int fmode=0;
1003 int share_mode;
1004 SMB_OFF_T size = 0;
1005 time_t mtime=0;
1006 mode_t unixmode;
1007 int rmode=0;
1008 SMB_STRUCT_STAT sbuf;
1009 BOOL bad_path = False;
1010 files_struct *fsp;
1011 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1012 NTSTATUS status;
1013 START_PROFILE(SMBopen);
1015 share_mode = SVAL(inbuf,smb_vwv0);
1017 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
1018 if (!NT_STATUS_IS_OK(status)) {
1019 END_PROFILE(SMBopen);
1020 return ERROR_NT(status);
1023 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1025 unix_convert(fname,conn,0,&bad_path,&sbuf);
1027 unixmode = unix_mode(conn,aARCH,fname);
1029 fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1030 unixmode, oplock_request,&rmode,NULL);
1032 if (!fsp) {
1033 END_PROFILE(SMBopen);
1034 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1037 size = sbuf.st_size;
1038 fmode = dos_mode(conn,fname,&sbuf);
1039 mtime = sbuf.st_mtime;
1041 if (fmode & aDIR) {
1042 DEBUG(3,("attempt to open a directory %s\n",fname));
1043 close_file(fsp,False);
1044 END_PROFILE(SMBopen);
1045 return ERROR_DOS(ERRDOS,ERRnoaccess);
1048 outsize = set_message(outbuf,7,0,True);
1049 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1050 SSVAL(outbuf,smb_vwv1,fmode);
1051 if(lp_dos_filetime_resolution(SNUM(conn)) )
1052 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1053 else
1054 put_dos_date3(outbuf,smb_vwv2,mtime);
1055 SIVAL(outbuf,smb_vwv4,(uint32)size);
1056 SSVAL(outbuf,smb_vwv6,rmode);
1058 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1059 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1061 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1062 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1063 END_PROFILE(SMBopen);
1064 return(outsize);
1067 /****************************************************************************
1068 Reply to an open and X.
1069 ****************************************************************************/
1071 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1073 pstring fname;
1074 int smb_mode = SVAL(inbuf,smb_vwv3);
1075 int smb_attr = SVAL(inbuf,smb_vwv5);
1076 /* Breakout the oplock request bits so we can set the
1077 reply bits separately. */
1078 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1079 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1080 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1081 #if 0
1082 int open_flags = SVAL(inbuf,smb_vwv2);
1083 int smb_sattr = SVAL(inbuf,smb_vwv4);
1084 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1085 #endif
1086 int smb_ofun = SVAL(inbuf,smb_vwv8);
1087 mode_t unixmode;
1088 SMB_OFF_T size=0;
1089 int fmode=0,mtime=0,rmode=0;
1090 SMB_STRUCT_STAT sbuf;
1091 int smb_action = 0;
1092 BOOL bad_path = False;
1093 files_struct *fsp;
1094 NTSTATUS status;
1095 START_PROFILE(SMBopenX);
1097 /* If it's an IPC, pass off the pipe handler. */
1098 if (IS_IPC(conn)) {
1099 if (lp_nt_pipe_support()) {
1100 END_PROFILE(SMBopenX);
1101 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1102 } else {
1103 END_PROFILE(SMBopenX);
1104 return ERROR_DOS(ERRSRV,ERRaccess);
1108 /* XXXX we need to handle passed times, sattr and flags */
1109 srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status);
1110 if (!NT_STATUS_IS_OK(status)) {
1111 END_PROFILE(SMBopenX);
1112 return ERROR_NT(status);
1115 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1117 unix_convert(fname,conn,0,&bad_path,&sbuf);
1119 unixmode = unix_mode(conn,smb_attr | aARCH, fname);
1121 fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,unixmode,
1122 oplock_request, &rmode,&smb_action);
1124 if (!fsp) {
1125 END_PROFILE(SMBopenX);
1126 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1129 size = sbuf.st_size;
1130 fmode = dos_mode(conn,fname,&sbuf);
1131 mtime = sbuf.st_mtime;
1132 if (fmode & aDIR) {
1133 close_file(fsp,False);
1134 END_PROFILE(SMBopenX);
1135 return ERROR_DOS(ERRDOS,ERRnoaccess);
1138 /* If the caller set the extended oplock request bit
1139 and we granted one (by whatever means) - set the
1140 correct bit for extended oplock reply.
1143 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn)))
1144 smb_action |= EXTENDED_OPLOCK_GRANTED;
1146 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1147 smb_action |= EXTENDED_OPLOCK_GRANTED;
1149 /* If the caller set the core oplock request bit
1150 and we granted one (by whatever means) - set the
1151 correct bit for core oplock reply.
1154 if (core_oplock_request && lp_fake_oplocks(SNUM(conn)))
1155 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1157 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1158 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1160 set_message(outbuf,15,0,True);
1161 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1162 SSVAL(outbuf,smb_vwv3,fmode);
1163 if(lp_dos_filetime_resolution(SNUM(conn)) )
1164 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1165 else
1166 put_dos_date3(outbuf,smb_vwv4,mtime);
1167 SIVAL(outbuf,smb_vwv6,(uint32)size);
1168 SSVAL(outbuf,smb_vwv8,rmode);
1169 SSVAL(outbuf,smb_vwv11,smb_action);
1171 END_PROFILE(SMBopenX);
1172 return chain_reply(inbuf,outbuf,length,bufsize);
1175 /****************************************************************************
1176 Reply to a SMBulogoffX.
1177 ****************************************************************************/
1179 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1181 uint16 vuid = SVAL(inbuf,smb_uid);
1182 user_struct *vuser = get_valid_user_struct(vuid);
1183 START_PROFILE(SMBulogoffX);
1185 if(vuser == 0)
1186 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1188 /* in user level security we are supposed to close any files
1189 open by this user */
1190 if ((vuser != 0) && (lp_security() != SEC_SHARE))
1191 file_close_user(vuid);
1193 invalidate_vuid(vuid);
1195 set_message(outbuf,2,0,True);
1197 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1199 END_PROFILE(SMBulogoffX);
1200 return chain_reply(inbuf,outbuf,length,bufsize);
1203 /****************************************************************************
1204 Reply to a mknew or a create.
1205 ****************************************************************************/
1207 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1209 pstring fname;
1210 int com;
1211 int outsize = 0;
1212 int createmode;
1213 mode_t unixmode;
1214 int ofun = 0;
1215 BOOL bad_path = False;
1216 files_struct *fsp;
1217 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1218 SMB_STRUCT_STAT sbuf;
1219 NTSTATUS status;
1220 START_PROFILE(SMBcreate);
1222 com = SVAL(inbuf,smb_com);
1224 createmode = SVAL(inbuf,smb_vwv0);
1225 srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status);
1226 if (!NT_STATUS_IS_OK(status)) {
1227 END_PROFILE(SMBcreate);
1228 return ERROR_NT(status);
1231 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1233 unix_convert(fname,conn,0,&bad_path,&sbuf);
1235 if (createmode & aVOLID)
1236 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1238 unixmode = unix_mode(conn,createmode,fname);
1240 if(com == SMBmknew) {
1241 /* We should fail if file exists. */
1242 ofun = FILE_CREATE_IF_NOT_EXIST;
1243 } else {
1244 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1245 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1248 /* Open file in dos compatibility share mode. */
1249 fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1250 ofun, unixmode, oplock_request, NULL, NULL);
1252 if (!fsp) {
1253 END_PROFILE(SMBcreate);
1254 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1257 outsize = set_message(outbuf,1,0,True);
1258 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1260 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1261 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1263 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1264 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1266 DEBUG( 2, ( "new file %s\n", fname ) );
1267 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n", fname, fsp->fd, createmode, (int)unixmode ) );
1269 END_PROFILE(SMBcreate);
1270 return(outsize);
1273 /****************************************************************************
1274 Reply to a create temporary file.
1275 ****************************************************************************/
1277 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1279 pstring fname;
1280 int outsize = 0;
1281 int createmode;
1282 mode_t unixmode;
1283 BOOL bad_path = False;
1284 files_struct *fsp;
1285 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1286 int tmpfd;
1287 SMB_STRUCT_STAT sbuf;
1288 char *p, *s;
1289 NTSTATUS status;
1291 START_PROFILE(SMBctemp);
1293 createmode = SVAL(inbuf,smb_vwv0);
1294 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
1295 if (!NT_STATUS_IS_OK(status)) {
1296 END_PROFILE(SMBctemp);
1297 return ERROR_NT(status);
1299 pstrcat(fname,"\\TMXXXXXX");
1301 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1303 unix_convert(fname,conn,0,&bad_path,&sbuf);
1305 unixmode = unix_mode(conn,createmode,fname);
1307 tmpfd = smb_mkstemp(fname);
1308 if (tmpfd == -1) {
1309 END_PROFILE(SMBctemp);
1310 return(UNIXERROR(ERRDOS,ERRnoaccess));
1313 SMB_VFS_STAT(conn,fname,&sbuf);
1315 /* Open file in dos compatibility share mode. */
1316 /* We should fail if file does not exist. */
1317 fsp = open_file_shared(conn,fname,&sbuf,
1318 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1319 FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
1320 unixmode, oplock_request, NULL, NULL);
1322 /* close fd from smb_mkstemp() */
1323 close(tmpfd);
1325 if (!fsp) {
1326 END_PROFILE(SMBctemp);
1327 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1330 outsize = set_message(outbuf,1,0,True);
1331 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1333 /* the returned filename is relative to the directory */
1334 s = strrchr_m(fname, '/');
1335 if (!s)
1336 s = fname;
1337 else
1338 s++;
1340 p = smb_buf(outbuf);
1341 SSVALS(p, 0, -1); /* what is this? not in spec */
1342 SSVAL(p, 2, strlen(s));
1343 p += 4;
1344 p += srvstr_push(outbuf, p, s, -1, STR_ASCII);
1345 outsize = set_message_end(outbuf, p);
1347 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1348 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1350 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1351 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1353 DEBUG( 2, ( "created temp file %s\n", fname ) );
1354 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1355 fname, fsp->fd, createmode, (int)unixmode ) );
1357 END_PROFILE(SMBctemp);
1358 return(outsize);
1361 /*******************************************************************
1362 Check if a user is allowed to rename a file.
1363 ********************************************************************/
1365 static NTSTATUS can_rename(char *fname,connection_struct *conn, SMB_STRUCT_STAT *pst)
1367 int smb_action;
1368 int access_mode;
1369 files_struct *fsp;
1371 if (!CAN_WRITE(conn))
1372 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1374 if (S_ISDIR(pst->st_mode))
1375 return NT_STATUS_OK;
1377 /* We need a better way to return NT status codes from open... */
1378 unix_ERR_class = 0;
1379 unix_ERR_code = 0;
1381 fsp = open_file_shared1(conn, fname, pst, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1382 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
1384 if (!fsp) {
1385 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1386 if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1387 ret = NT_STATUS_SHARING_VIOLATION;
1388 unix_ERR_class = 0;
1389 unix_ERR_code = 0;
1390 unix_ERR_ntstatus = NT_STATUS_OK;
1391 return ret;
1393 close_file(fsp,False);
1394 return NT_STATUS_OK;
1397 /*******************************************************************
1398 Check if a user is allowed to delete a file.
1399 ********************************************************************/
1401 static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype, BOOL bad_path)
1403 SMB_STRUCT_STAT sbuf;
1404 int fmode;
1405 int smb_action;
1406 int access_mode;
1407 files_struct *fsp;
1409 DEBUG(10,("can_delete: %s, dirtype = %d\n",
1410 fname, dirtype ));
1412 if (!CAN_WRITE(conn))
1413 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1415 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
1416 if(errno == ENOENT) {
1417 if (bad_path)
1418 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1419 else
1420 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1422 return map_nt_error_from_unix(errno);
1425 fmode = dos_mode(conn,fname,&sbuf);
1427 /* Can't delete a directory. */
1428 if (fmode & aDIR)
1429 return NT_STATUS_FILE_IS_A_DIRECTORY;
1430 #if 0 /* JRATEST */
1431 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
1432 return NT_STATUS_OBJECT_NAME_INVALID;
1433 #endif /* JRATEST */
1435 if (!lp_delete_readonly(SNUM(conn))) {
1436 if (fmode & aRONLY)
1437 return NT_STATUS_CANNOT_DELETE;
1439 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1440 return NT_STATUS_NO_SUCH_FILE;
1442 /* We need a better way to return NT status codes from open... */
1443 unix_ERR_class = 0;
1444 unix_ERR_code = 0;
1446 fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1447 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
1449 if (!fsp) {
1450 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1451 if (!NT_STATUS_IS_OK(unix_ERR_ntstatus))
1452 ret = unix_ERR_ntstatus;
1453 else if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1454 ret = NT_STATUS_SHARING_VIOLATION;
1455 unix_ERR_class = 0;
1456 unix_ERR_code = 0;
1457 unix_ERR_ntstatus = NT_STATUS_OK;
1458 return ret;
1460 close_file(fsp,False);
1461 return NT_STATUS_OK;
1464 /****************************************************************************
1465 The guts of the unlink command, split out so it may be called by the NT SMB
1466 code.
1467 ****************************************************************************/
1469 NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
1471 pstring directory;
1472 pstring mask;
1473 char *p;
1474 int count=0;
1475 NTSTATUS error = NT_STATUS_OK;
1476 BOOL has_wild;
1477 BOOL bad_path = False;
1478 BOOL rc = True;
1479 SMB_STRUCT_STAT sbuf;
1481 *directory = *mask = 0;
1483 /* We must check for wildcards in the name given
1484 * directly by the client - before any unmangling.
1485 * This prevents an unmangling of a UNIX name containing
1486 * a DOS wildcard like '*' or '?' from unmangling into
1487 * a wildcard delete which was not intended.
1488 * FIX for #226. JRA.
1491 has_wild = ms_has_wild(name);
1493 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1495 p = strrchr_m(name,'/');
1496 if (!p) {
1497 pstrcpy(directory,".");
1498 pstrcpy(mask,name);
1499 } else {
1500 *p = 0;
1501 pstrcpy(directory,name);
1502 pstrcpy(mask,p+1);
1506 * We should only check the mangled cache
1507 * here if unix_convert failed. This means
1508 * that the path in 'mask' doesn't exist
1509 * on the file system and so we need to look
1510 * for a possible mangle. This patch from
1511 * Tine Smukavec <valentin.smukavec@hermes.si>.
1514 if (!rc && mangle_is_mangled(mask))
1515 mangle_check_cache( mask );
1517 if (!has_wild) {
1518 pstrcat(directory,"/");
1519 pstrcat(directory,mask);
1520 error = can_delete(directory,conn,dirtype,bad_path);
1521 if (!NT_STATUS_IS_OK(error))
1522 return error;
1524 if (SMB_VFS_UNLINK(conn,directory) == 0) {
1525 count++;
1527 } else {
1528 void *dirptr = NULL;
1529 const char *dname;
1531 if (check_name(directory,conn))
1532 dirptr = OpenDir(conn, directory, True);
1534 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1535 the pattern matches against the long name, otherwise the short name
1536 We don't implement this yet XXXX
1539 if (dirptr) {
1540 error = NT_STATUS_NO_SUCH_FILE;
1542 if (strequal(mask,"????????.???"))
1543 pstrcpy(mask,"*");
1545 while ((dname = ReadDirName(dirptr))) {
1546 pstring fname;
1547 BOOL sys_direntry = False;
1548 pstrcpy(fname,dname);
1550 /* Quick check for "." and ".." */
1551 if (fname[0] == '.') {
1552 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
1553 if ((dirtype & aDIR)) {
1554 sys_direntry = True;
1555 } else {
1556 continue;
1561 if(!mask_match(fname, mask, case_sensitive))
1562 continue;
1564 if (sys_direntry) {
1565 error = NT_STATUS_OBJECT_NAME_INVALID;
1566 continue;
1569 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1570 error = can_delete(fname,conn,dirtype,bad_path);
1571 if (!NT_STATUS_IS_OK(error))
1572 continue;
1573 if (SMB_VFS_UNLINK(conn,fname) == 0)
1574 count++;
1575 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
1577 CloseDir(dirptr);
1581 if (count == 0 && NT_STATUS_IS_OK(error)) {
1582 error = map_nt_error_from_unix(errno);
1585 return error;
1588 /****************************************************************************
1589 Reply to a unlink
1590 ****************************************************************************/
1592 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
1593 int dum_buffsize)
1595 int outsize = 0;
1596 pstring name;
1597 int dirtype;
1598 NTSTATUS status;
1599 START_PROFILE(SMBunlink);
1601 dirtype = SVAL(inbuf,smb_vwv0);
1603 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
1604 if (!NT_STATUS_IS_OK(status)) {
1605 END_PROFILE(SMBunlink);
1606 return ERROR_NT(status);
1609 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1611 DEBUG(3,("reply_unlink : %s\n",name));
1613 status = unlink_internals(conn, dirtype, name);
1614 if (!NT_STATUS_IS_OK(status))
1615 return ERROR_NT(status);
1618 * Win2k needs a changenotify request response before it will
1619 * update after a rename..
1621 process_pending_change_notify_queue((time_t)0);
1623 outsize = set_message(outbuf,0,0,True);
1625 END_PROFILE(SMBunlink);
1626 return outsize;
1629 /****************************************************************************
1630 Fail for readbraw.
1631 ****************************************************************************/
1633 void fail_readraw(void)
1635 pstring errstr;
1636 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
1637 strerror(errno) );
1638 exit_server(errstr);
1641 /****************************************************************************
1642 Use sendfile in readbraw.
1643 ****************************************************************************/
1645 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
1646 ssize_t mincount, char *outbuf)
1648 ssize_t ret=0;
1650 #if defined(WITH_SENDFILE)
1652 * We can only use sendfile on a non-chained packet and on a file
1653 * that is exclusively oplocked. reply_readbraw has already checked the length.
1656 if ((nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) &&
1657 EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && lp_use_sendfile(SNUM(conn)) ) {
1658 DATA_BLOB header;
1660 _smb_setlen(outbuf,nread);
1661 header.data = outbuf;
1662 header.length = 4;
1663 header.free = NULL;
1665 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) {
1667 * Special hack for broken Linux with no 64 bit clean sendfile. If we
1668 * return ENOSYS then pretend we just got a normal read.
1670 if (errno == ENOSYS)
1671 goto normal_read;
1673 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
1674 fsp->fsp_name, strerror(errno) ));
1675 exit_server("send_file_readbraw sendfile failed");
1680 normal_read:
1681 #endif
1683 if (nread > 0) {
1684 ret = read_file(fsp,outbuf+4,startpos,nread);
1685 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1686 if (ret < mincount)
1687 ret = 0;
1688 #else
1689 if (ret < nread)
1690 ret = 0;
1691 #endif
1694 _smb_setlen(outbuf,ret);
1695 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
1696 fail_readraw();
1699 /****************************************************************************
1700 Reply to a readbraw (core+ protocol).
1701 ****************************************************************************/
1703 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
1705 extern struct current_user current_user;
1706 ssize_t maxcount,mincount;
1707 size_t nread = 0;
1708 SMB_OFF_T startpos;
1709 char *header = outbuf;
1710 files_struct *fsp;
1711 START_PROFILE(SMBreadbraw);
1713 if (srv_is_signing_active()) {
1714 exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
1718 * Special check if an oplock break has been issued
1719 * and the readraw request croses on the wire, we must
1720 * return a zero length response here.
1723 if(global_oplock_break) {
1724 _smb_setlen(header,0);
1725 if (write_data(smbd_server_fd(),header,4) != 4)
1726 fail_readraw();
1727 DEBUG(5,("readbraw - oplock break finished\n"));
1728 END_PROFILE(SMBreadbraw);
1729 return -1;
1732 fsp = file_fsp(inbuf,smb_vwv0);
1734 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1736 * fsp could be NULL here so use the value from the packet. JRA.
1738 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
1739 _smb_setlen(header,0);
1740 if (write_data(smbd_server_fd(),header,4) != 4)
1741 fail_readraw();
1742 END_PROFILE(SMBreadbraw);
1743 return(-1);
1746 CHECK_FSP(fsp,conn);
1748 flush_write_cache(fsp, READRAW_FLUSH);
1750 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
1751 if(CVAL(inbuf,smb_wct) == 10) {
1753 * This is a large offset (64 bit) read.
1755 #ifdef LARGE_SMB_OFF_T
1757 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
1759 #else /* !LARGE_SMB_OFF_T */
1762 * Ensure we haven't been sent a >32 bit offset.
1765 if(IVAL(inbuf,smb_vwv8) != 0) {
1766 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
1767 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
1768 _smb_setlen(header,0);
1769 if (write_data(smbd_server_fd(),header,4) != 4)
1770 fail_readraw();
1771 END_PROFILE(SMBreadbraw);
1772 return(-1);
1775 #endif /* LARGE_SMB_OFF_T */
1777 if(startpos < 0) {
1778 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
1779 _smb_setlen(header,0);
1780 if (write_data(smbd_server_fd(),header,4) != 4)
1781 fail_readraw();
1782 END_PROFILE(SMBreadbraw);
1783 return(-1);
1786 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
1787 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
1789 /* ensure we don't overrun the packet size */
1790 maxcount = MIN(65535,maxcount);
1792 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1793 SMB_OFF_T size = fsp->size;
1794 SMB_OFF_T sizeneeded = startpos + maxcount;
1796 if (size < sizeneeded) {
1797 SMB_STRUCT_STAT st;
1798 if (SMB_VFS_FSTAT(fsp,fsp->fd,&st) == 0)
1799 size = st.st_size;
1800 if (!fsp->can_write)
1801 fsp->size = size;
1804 if (startpos >= size)
1805 nread = 0;
1806 else
1807 nread = MIN(maxcount,(size - startpos));
1810 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1811 if (nread < mincount)
1812 nread = 0;
1813 #endif
1815 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
1816 (int)maxcount, (int)mincount, (int)nread ) );
1818 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf);
1820 DEBUG(5,("readbraw finished\n"));
1821 END_PROFILE(SMBreadbraw);
1822 return -1;
1825 /****************************************************************************
1826 Reply to a lockread (core+ protocol).
1827 ****************************************************************************/
1829 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
1831 ssize_t nread = -1;
1832 char *data;
1833 int outsize = 0;
1834 SMB_OFF_T startpos;
1835 size_t numtoread;
1836 NTSTATUS status;
1837 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1838 BOOL my_lock_ctx = False;
1839 START_PROFILE(SMBlockread);
1841 CHECK_FSP(fsp,conn);
1842 CHECK_READ(fsp);
1844 release_level_2_oplocks_on_change(fsp);
1846 numtoread = SVAL(inbuf,smb_vwv1);
1847 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
1849 outsize = set_message(outbuf,5,3,True);
1850 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1851 data = smb_buf(outbuf) + 3;
1854 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
1855 * protocol request that predates the read/write lock concept.
1856 * Thus instead of asking for a read lock here we need to ask
1857 * for a write lock. JRA.
1858 * Note that the requested lock size is unaffected by max_recv.
1861 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid),
1862 (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, &my_lock_ctx);
1864 if (NT_STATUS_V(status)) {
1865 #if 0
1867 * We used to make lockread a blocking lock. It turns out
1868 * that this isn't on W2k. Found by the Samba 4 RAW-READ torture
1869 * tester. JRA.
1872 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
1874 * A blocking lock was requested. Package up
1875 * this smb into a queued request and push it
1876 * onto the blocking lock queue.
1878 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)startpos,
1879 (SMB_BIG_UINT)numtoread)) {
1880 END_PROFILE(SMBlockread);
1881 return -1;
1884 #endif
1885 END_PROFILE(SMBlockread);
1886 return ERROR_NT(status);
1890 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
1893 if (numtoread > max_recv) {
1894 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
1895 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
1896 (unsigned int)numtoread, (unsigned int)max_recv ));
1897 numtoread = MIN(numtoread,max_recv);
1899 nread = read_file(fsp,data,startpos,numtoread);
1901 if (nread < 0) {
1902 END_PROFILE(SMBlockread);
1903 return(UNIXERROR(ERRDOS,ERRnoaccess));
1906 outsize += nread;
1907 SSVAL(outbuf,smb_vwv0,nread);
1908 SSVAL(outbuf,smb_vwv5,nread+3);
1909 SSVAL(smb_buf(outbuf),1,nread);
1911 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
1912 fsp->fnum, (int)numtoread, (int)nread));
1914 END_PROFILE(SMBlockread);
1915 return(outsize);
1918 /****************************************************************************
1919 Reply to a read.
1920 ****************************************************************************/
1922 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
1924 size_t numtoread;
1925 ssize_t nread = 0;
1926 char *data;
1927 SMB_OFF_T startpos;
1928 int outsize = 0;
1929 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1930 START_PROFILE(SMBread);
1932 CHECK_FSP(fsp,conn);
1933 CHECK_READ(fsp);
1935 numtoread = SVAL(inbuf,smb_vwv1);
1936 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
1938 outsize = set_message(outbuf,5,3,True);
1939 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1941 * The requested read size cannot be greater than max_recv. JRA.
1943 if (numtoread > max_recv) {
1944 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
1945 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
1946 (unsigned int)numtoread, (unsigned int)max_recv ));
1947 numtoread = MIN(numtoread,max_recv);
1950 data = smb_buf(outbuf) + 3;
1952 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1953 END_PROFILE(SMBread);
1954 return ERROR_DOS(ERRDOS,ERRlock);
1957 if (numtoread > 0)
1958 nread = read_file(fsp,data,startpos,numtoread);
1960 if (nread < 0) {
1961 END_PROFILE(SMBread);
1962 return(UNIXERROR(ERRDOS,ERRnoaccess));
1965 outsize += nread;
1966 SSVAL(outbuf,smb_vwv0,nread);
1967 SSVAL(outbuf,smb_vwv5,nread+3);
1968 SCVAL(smb_buf(outbuf),0,1);
1969 SSVAL(smb_buf(outbuf),1,nread);
1971 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
1972 fsp->fnum, (int)numtoread, (int)nread ) );
1974 END_PROFILE(SMBread);
1975 return(outsize);
1978 /****************************************************************************
1979 Reply to a read and X - possibly using sendfile.
1980 ****************************************************************************/
1982 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length,
1983 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
1985 ssize_t nread = -1;
1986 char *data = smb_buf(outbuf);
1988 #if defined(WITH_SENDFILE)
1990 * We can only use sendfile on a non-chained packet and on a file
1991 * that is exclusively oplocked.
1994 if ((CVAL(inbuf,smb_vwv0) == 0xFF) && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) &&
1995 lp_use_sendfile(SNUM(conn)) && (lp_write_cache_size(SNUM(conn)) == 0) ) {
1996 SMB_STRUCT_STAT sbuf;
1997 DATA_BLOB header;
1999 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1)
2000 return(UNIXERROR(ERRDOS,ERRnoaccess));
2002 if (startpos > sbuf.st_size)
2003 goto normal_read;
2005 if (smb_maxcnt > (sbuf.st_size - startpos))
2006 smb_maxcnt = (sbuf.st_size - startpos);
2008 if (smb_maxcnt == 0)
2009 goto normal_read;
2012 * Set up the packet header before send. We
2013 * assume here the sendfile will work (get the
2014 * correct amount of data).
2017 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2018 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
2019 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2020 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
2021 SCVAL(outbuf,smb_vwv0,0xFF);
2022 set_message(outbuf,12,smb_maxcnt,False);
2023 header.data = outbuf;
2024 header.length = data - outbuf;
2025 header.free = NULL;
2027 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt) == -1) {
2029 * Special hack for broken Linux with no 64 bit clean sendfile. If we
2030 * return ENOSYS then pretend we just got a normal read.
2032 if (errno == ENOSYS)
2033 goto normal_read;
2035 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2036 fsp->fsp_name, strerror(errno) ));
2037 exit_server("send_file_readX sendfile failed");
2040 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2041 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2042 return -1;
2045 normal_read:
2047 #endif
2049 nread = read_file(fsp,data,startpos,smb_maxcnt);
2051 if (nread < 0) {
2052 END_PROFILE(SMBreadX);
2053 return(UNIXERROR(ERRDOS,ERRnoaccess));
2056 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2057 SSVAL(outbuf,smb_vwv5,nread);
2058 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2059 SSVAL(smb_buf(outbuf),-2,nread);
2061 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2062 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2064 return nread;
2067 /****************************************************************************
2068 Reply to a read and X.
2069 ****************************************************************************/
2071 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2073 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2074 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2075 ssize_t nread = -1;
2076 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2077 #if 0
2078 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2079 #endif
2081 START_PROFILE(SMBreadX);
2083 /* If it's an IPC, pass off the pipe handler. */
2084 if (IS_IPC(conn)) {
2085 END_PROFILE(SMBreadX);
2086 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2089 CHECK_FSP(fsp,conn);
2090 CHECK_READ(fsp);
2092 set_message(outbuf,12,0,True);
2094 if(CVAL(inbuf,smb_wct) == 12) {
2095 #ifdef LARGE_SMB_OFF_T
2097 * This is a large offset (64 bit) read.
2099 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2101 #else /* !LARGE_SMB_OFF_T */
2104 * Ensure we haven't been sent a >32 bit offset.
2107 if(IVAL(inbuf,smb_vwv10) != 0) {
2108 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2109 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2110 END_PROFILE(SMBreadX);
2111 return ERROR_DOS(ERRDOS,ERRbadaccess);
2114 #endif /* LARGE_SMB_OFF_T */
2118 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
2119 END_PROFILE(SMBreadX);
2120 return ERROR_DOS(ERRDOS,ERRlock);
2123 nread = send_file_readX(conn, inbuf, outbuf, length, fsp, startpos, smb_maxcnt);
2124 if (nread != -1)
2125 nread = chain_reply(inbuf,outbuf,length,bufsize);
2127 END_PROFILE(SMBreadX);
2128 return nread;
2131 /****************************************************************************
2132 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2133 ****************************************************************************/
2135 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2137 ssize_t nwritten=0;
2138 ssize_t total_written=0;
2139 size_t numtowrite=0;
2140 size_t tcount;
2141 SMB_OFF_T startpos;
2142 char *data=NULL;
2143 BOOL write_through;
2144 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2145 int outsize = 0;
2146 START_PROFILE(SMBwritebraw);
2148 if (srv_is_signing_active()) {
2149 exit_server("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2152 CHECK_FSP(fsp,conn);
2153 CHECK_WRITE(fsp);
2155 tcount = IVAL(inbuf,smb_vwv1);
2156 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2157 write_through = BITSETW(inbuf+smb_vwv7,0);
2159 /* We have to deal with slightly different formats depending
2160 on whether we are using the core+ or lanman1.0 protocol */
2162 if(Protocol <= PROTOCOL_COREPLUS) {
2163 numtowrite = SVAL(smb_buf(inbuf),-2);
2164 data = smb_buf(inbuf);
2165 } else {
2166 numtowrite = SVAL(inbuf,smb_vwv10);
2167 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2170 /* force the error type */
2171 SCVAL(inbuf,smb_com,SMBwritec);
2172 SCVAL(outbuf,smb_com,SMBwritec);
2174 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2175 END_PROFILE(SMBwritebraw);
2176 return(ERROR_DOS(ERRDOS,ERRlock));
2179 if (numtowrite>0)
2180 nwritten = write_file(fsp,data,startpos,numtowrite);
2182 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2183 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2185 if (nwritten < (ssize_t)numtowrite) {
2186 END_PROFILE(SMBwritebraw);
2187 return(UNIXERROR(ERRHRD,ERRdiskfull));
2190 total_written = nwritten;
2192 /* Return a message to the redirector to tell it to send more bytes */
2193 SCVAL(outbuf,smb_com,SMBwritebraw);
2194 SSVALS(outbuf,smb_vwv0,-1);
2195 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2196 if (!send_smb(smbd_server_fd(),outbuf))
2197 exit_server("reply_writebraw: send_smb failed.");
2199 /* Now read the raw data into the buffer and write it */
2200 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2201 exit_server("secondary writebraw failed");
2204 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2205 numtowrite = smb_len(inbuf);
2207 /* Set up outbuf to return the correct return */
2208 outsize = set_message(outbuf,1,0,True);
2209 SCVAL(outbuf,smb_com,SMBwritec);
2210 SSVAL(outbuf,smb_vwv0,total_written);
2212 if (numtowrite != 0) {
2214 if (numtowrite > BUFFER_SIZE) {
2215 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2216 (unsigned int)numtowrite ));
2217 exit_server("secondary writebraw failed");
2220 if (tcount > nwritten+numtowrite) {
2221 DEBUG(3,("Client overestimated the write %d %d %d\n",
2222 (int)tcount,(int)nwritten,(int)numtowrite));
2225 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2226 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2227 strerror(errno) ));
2228 exit_server("secondary writebraw failed");
2231 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2233 if (nwritten < (ssize_t)numtowrite) {
2234 SCVAL(outbuf,smb_rcls,ERRHRD);
2235 SSVAL(outbuf,smb_err,ERRdiskfull);
2238 if (nwritten > 0)
2239 total_written += nwritten;
2242 if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn)))
2243 sync_file(conn,fsp);
2245 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2246 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2248 /* we won't return a status if write through is not selected - this follows what WfWg does */
2249 END_PROFILE(SMBwritebraw);
2250 if (!write_through && total_written==tcount) {
2252 #if RABBIT_PELLET_FIX
2254 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2255 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2257 if (!send_keepalive(smbd_server_fd()))
2258 exit_server("reply_writebraw: send of keepalive failed");
2259 #endif
2260 return(-1);
2263 return(outsize);
2266 /****************************************************************************
2267 Reply to a writeunlock (core+).
2268 ****************************************************************************/
2270 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
2271 int size, int dum_buffsize)
2273 ssize_t nwritten = -1;
2274 size_t numtowrite;
2275 SMB_OFF_T startpos;
2276 char *data;
2277 NTSTATUS status = NT_STATUS_OK;
2278 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2279 int outsize = 0;
2280 START_PROFILE(SMBwriteunlock);
2282 CHECK_FSP(fsp,conn);
2283 CHECK_WRITE(fsp);
2285 numtowrite = SVAL(inbuf,smb_vwv1);
2286 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2287 data = smb_buf(inbuf) + 3;
2289 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos,
2290 WRITE_LOCK,False)) {
2291 END_PROFILE(SMBwriteunlock);
2292 return ERROR_DOS(ERRDOS,ERRlock);
2295 /* The special X/Open SMB protocol handling of
2296 zero length writes is *NOT* done for
2297 this call */
2298 if(numtowrite == 0)
2299 nwritten = 0;
2300 else
2301 nwritten = write_file(fsp,data,startpos,numtowrite);
2303 if (lp_syncalways(SNUM(conn)))
2304 sync_file(conn,fsp);
2306 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2307 END_PROFILE(SMBwriteunlock);
2308 return(UNIXERROR(ERRHRD,ERRdiskfull));
2311 if (numtowrite) {
2312 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite,
2313 (SMB_BIG_UINT)startpos);
2314 if (NT_STATUS_V(status)) {
2315 END_PROFILE(SMBwriteunlock);
2316 return ERROR_NT(status);
2320 outsize = set_message(outbuf,1,0,True);
2322 SSVAL(outbuf,smb_vwv0,nwritten);
2324 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2325 fsp->fnum, (int)numtowrite, (int)nwritten));
2327 END_PROFILE(SMBwriteunlock);
2328 return outsize;
2331 /****************************************************************************
2332 Reply to a write.
2333 ****************************************************************************/
2335 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2337 size_t numtowrite;
2338 ssize_t nwritten = -1;
2339 SMB_OFF_T startpos;
2340 char *data;
2341 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2342 int outsize = 0;
2343 START_PROFILE(SMBwrite);
2345 /* If it's an IPC, pass off the pipe handler. */
2346 if (IS_IPC(conn)) {
2347 END_PROFILE(SMBwrite);
2348 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2351 CHECK_FSP(fsp,conn);
2352 CHECK_WRITE(fsp);
2354 numtowrite = SVAL(inbuf,smb_vwv1);
2355 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2356 data = smb_buf(inbuf) + 3;
2358 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2359 END_PROFILE(SMBwrite);
2360 return ERROR_DOS(ERRDOS,ERRlock);
2364 * X/Open SMB protocol says that if smb_vwv1 is
2365 * zero then the file size should be extended or
2366 * truncated to the size given in smb_vwv[2-3].
2369 if(numtowrite == 0) {
2371 * This is actually an allocate call, and set EOF. JRA.
2373 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2374 if (nwritten < 0) {
2375 END_PROFILE(SMBwrite);
2376 return ERROR_NT(NT_STATUS_DISK_FULL);
2378 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2379 if (nwritten < 0) {
2380 END_PROFILE(SMBwrite);
2381 return ERROR_NT(NT_STATUS_DISK_FULL);
2383 } else
2384 nwritten = write_file(fsp,data,startpos,numtowrite);
2386 if (lp_syncalways(SNUM(conn)))
2387 sync_file(conn,fsp);
2389 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2390 END_PROFILE(SMBwrite);
2391 return(UNIXERROR(ERRHRD,ERRdiskfull));
2394 outsize = set_message(outbuf,1,0,True);
2396 SSVAL(outbuf,smb_vwv0,nwritten);
2398 if (nwritten < (ssize_t)numtowrite) {
2399 SCVAL(outbuf,smb_rcls,ERRHRD);
2400 SSVAL(outbuf,smb_err,ERRdiskfull);
2403 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2405 END_PROFILE(SMBwrite);
2406 return(outsize);
2409 /****************************************************************************
2410 Reply to a write and X.
2411 ****************************************************************************/
2413 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2415 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2416 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2417 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2418 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2419 ssize_t nwritten = -1;
2420 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2421 unsigned int smblen = smb_len(inbuf);
2422 char *data;
2423 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2424 START_PROFILE(SMBwriteX);
2426 /* If it's an IPC, pass off the pipe handler. */
2427 if (IS_IPC(conn)) {
2428 END_PROFILE(SMBwriteX);
2429 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2432 CHECK_FSP(fsp,conn);
2433 CHECK_WRITE(fsp);
2435 /* Deal with possible LARGE_WRITEX */
2436 if (large_writeX)
2437 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2439 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2440 END_PROFILE(SMBwriteX);
2441 return ERROR_DOS(ERRDOS,ERRbadmem);
2444 data = smb_base(inbuf) + smb_doff;
2446 if(CVAL(inbuf,smb_wct) == 14) {
2447 #ifdef LARGE_SMB_OFF_T
2449 * This is a large offset (64 bit) write.
2451 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2453 #else /* !LARGE_SMB_OFF_T */
2456 * Ensure we haven't been sent a >32 bit offset.
2459 if(IVAL(inbuf,smb_vwv12) != 0) {
2460 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2461 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2462 END_PROFILE(SMBwriteX);
2463 return ERROR_DOS(ERRDOS,ERRbadaccess);
2466 #endif /* LARGE_SMB_OFF_T */
2469 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2470 END_PROFILE(SMBwriteX);
2471 return ERROR_DOS(ERRDOS,ERRlock);
2474 /* X/Open SMB protocol says that, unlike SMBwrite
2475 if the length is zero then NO truncation is
2476 done, just a write of zero. To truncate a file,
2477 use SMBwrite. */
2479 if(numtowrite == 0)
2480 nwritten = 0;
2481 else
2482 nwritten = write_file(fsp,data,startpos,numtowrite);
2484 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2485 END_PROFILE(SMBwriteX);
2486 return(UNIXERROR(ERRHRD,ERRdiskfull));
2489 set_message(outbuf,6,0,True);
2491 SSVAL(outbuf,smb_vwv2,nwritten);
2492 if (large_writeX)
2493 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2495 if (nwritten < (ssize_t)numtowrite) {
2496 SCVAL(outbuf,smb_rcls,ERRHRD);
2497 SSVAL(outbuf,smb_err,ERRdiskfull);
2500 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2501 fsp->fnum, (int)numtowrite, (int)nwritten));
2503 if (lp_syncalways(SNUM(conn)) || write_through)
2504 sync_file(conn,fsp);
2506 END_PROFILE(SMBwriteX);
2507 return chain_reply(inbuf,outbuf,length,bufsize);
2510 /****************************************************************************
2511 Reply to a lseek.
2512 ****************************************************************************/
2514 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2516 SMB_OFF_T startpos;
2517 SMB_OFF_T res= -1;
2518 int mode,umode;
2519 int outsize = 0;
2520 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2521 START_PROFILE(SMBlseek);
2523 CHECK_FSP(fsp,conn);
2525 flush_write_cache(fsp, SEEK_FLUSH);
2527 mode = SVAL(inbuf,smb_vwv1) & 3;
2528 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
2529 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
2531 switch (mode) {
2532 case 0:
2533 umode = SEEK_SET;
2534 res = startpos;
2535 break;
2536 case 1:
2537 umode = SEEK_CUR;
2538 res = fsp->pos + startpos;
2539 break;
2540 case 2:
2541 umode = SEEK_END;
2542 break;
2543 default:
2544 umode = SEEK_SET;
2545 res = startpos;
2546 break;
2549 if (umode == SEEK_END) {
2550 if((res = SMB_VFS_LSEEK(fsp,fsp->fd,startpos,umode)) == -1) {
2551 if(errno == EINVAL) {
2552 SMB_OFF_T current_pos = startpos;
2553 SMB_STRUCT_STAT sbuf;
2555 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) {
2556 END_PROFILE(SMBlseek);
2557 return(UNIXERROR(ERRDOS,ERRnoaccess));
2560 current_pos += sbuf.st_size;
2561 if(current_pos < 0)
2562 res = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_SET);
2566 if(res == -1) {
2567 END_PROFILE(SMBlseek);
2568 return(UNIXERROR(ERRDOS,ERRnoaccess));
2572 fsp->pos = res;
2574 outsize = set_message(outbuf,2,0,True);
2575 SIVAL(outbuf,smb_vwv0,res);
2577 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2578 fsp->fnum, (double)startpos, (double)res, mode));
2580 END_PROFILE(SMBlseek);
2581 return(outsize);
2584 /****************************************************************************
2585 Reply to a flush.
2586 ****************************************************************************/
2588 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2590 int outsize = set_message(outbuf,0,0,True);
2591 uint16 fnum = SVAL(inbuf,smb_vwv0);
2592 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2593 START_PROFILE(SMBflush);
2595 if (fnum != 0xFFFF)
2596 CHECK_FSP(fsp,conn);
2598 if (!fsp) {
2599 file_sync_all(conn);
2600 } else {
2601 sync_file(conn,fsp);
2604 DEBUG(3,("flush\n"));
2605 END_PROFILE(SMBflush);
2606 return(outsize);
2609 /****************************************************************************
2610 Reply to a exit.
2611 ****************************************************************************/
2613 int reply_exit(connection_struct *conn,
2614 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2616 int outsize;
2617 START_PROFILE(SMBexit);
2619 file_close_pid(SVAL(inbuf,smb_pid));
2621 outsize = set_message(outbuf,0,0,True);
2623 DEBUG(3,("exit\n"));
2625 END_PROFILE(SMBexit);
2626 return(outsize);
2629 /****************************************************************************
2630 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2631 ****************************************************************************/
2633 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2634 int dum_buffsize)
2636 extern struct current_user current_user;
2637 int outsize = 0;
2638 time_t mtime;
2639 int32 eclass = 0, err = 0;
2640 files_struct *fsp = NULL;
2641 START_PROFILE(SMBclose);
2643 outsize = set_message(outbuf,0,0,True);
2645 /* If it's an IPC, pass off to the pipe handler. */
2646 if (IS_IPC(conn)) {
2647 END_PROFILE(SMBclose);
2648 return reply_pipe_close(conn, inbuf,outbuf);
2651 fsp = file_fsp(inbuf,smb_vwv0);
2654 * We can only use CHECK_FSP if we know it's not a directory.
2657 if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
2658 END_PROFILE(SMBclose);
2659 return ERROR_DOS(ERRDOS,ERRbadfid);
2662 if(fsp->is_directory) {
2664 * Special case - close NT SMB directory handle.
2666 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2667 close_file(fsp,True);
2668 } else {
2670 * Close ordinary file.
2672 int close_err;
2673 pstring file_name;
2675 /* Save the name for time set in close. */
2676 pstrcpy( file_name, fsp->fsp_name);
2678 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2679 fsp->fd, fsp->fnum,
2680 conn->num_files_open));
2683 * close_file() returns the unix errno if an error
2684 * was detected on close - normally this is due to
2685 * a disk full error. If not then it was probably an I/O error.
2688 if((close_err = close_file(fsp,True)) != 0) {
2689 errno = close_err;
2690 END_PROFILE(SMBclose);
2691 return (UNIXERROR(ERRHRD,ERRgeneral));
2695 * Now take care of any time sent in the close.
2698 mtime = make_unix_date3(inbuf+smb_vwv1);
2700 /* try and set the date */
2701 set_filetime(conn, file_name, mtime);
2705 /* We have a cached error */
2706 if(eclass || err) {
2707 END_PROFILE(SMBclose);
2708 return ERROR_DOS(eclass,err);
2711 END_PROFILE(SMBclose);
2712 return(outsize);
2715 /****************************************************************************
2716 Reply to a writeclose (Core+ protocol).
2717 ****************************************************************************/
2719 int reply_writeclose(connection_struct *conn,
2720 char *inbuf,char *outbuf, int size, int dum_buffsize)
2722 size_t numtowrite;
2723 ssize_t nwritten = -1;
2724 int outsize = 0;
2725 int close_err = 0;
2726 SMB_OFF_T startpos;
2727 char *data;
2728 time_t mtime;
2729 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2730 START_PROFILE(SMBwriteclose);
2732 CHECK_FSP(fsp,conn);
2733 CHECK_WRITE(fsp);
2735 numtowrite = SVAL(inbuf,smb_vwv1);
2736 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2737 mtime = make_unix_date3(inbuf+smb_vwv4);
2738 data = smb_buf(inbuf) + 1;
2740 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2741 END_PROFILE(SMBwriteclose);
2742 return ERROR_DOS(ERRDOS,ERRlock);
2745 nwritten = write_file(fsp,data,startpos,numtowrite);
2747 set_filetime(conn, fsp->fsp_name,mtime);
2750 * More insanity. W2K only closes the file if writelen > 0.
2751 * JRA.
2754 if (numtowrite) {
2755 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
2756 fsp->fsp_name ));
2757 close_err = close_file(fsp,True);
2760 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2761 fsp->fnum, (int)numtowrite, (int)nwritten,
2762 conn->num_files_open));
2764 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2765 END_PROFILE(SMBwriteclose);
2766 return(UNIXERROR(ERRHRD,ERRdiskfull));
2769 if(close_err != 0) {
2770 errno = close_err;
2771 END_PROFILE(SMBwriteclose);
2772 return(UNIXERROR(ERRHRD,ERRgeneral));
2775 outsize = set_message(outbuf,1,0,True);
2777 SSVAL(outbuf,smb_vwv0,nwritten);
2778 END_PROFILE(SMBwriteclose);
2779 return(outsize);
2782 /****************************************************************************
2783 Reply to a lock.
2784 ****************************************************************************/
2786 int reply_lock(connection_struct *conn,
2787 char *inbuf,char *outbuf, int length, int dum_buffsize)
2789 int outsize = set_message(outbuf,0,0,True);
2790 SMB_BIG_UINT count,offset;
2791 NTSTATUS status;
2792 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2793 BOOL my_lock_ctx = False;
2795 START_PROFILE(SMBlock);
2797 CHECK_FSP(fsp,conn);
2799 release_level_2_oplocks_on_change(fsp);
2801 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2802 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2804 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2805 fsp->fd, fsp->fnum, (double)offset, (double)count));
2807 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &my_lock_ctx);
2808 if (NT_STATUS_V(status)) {
2809 #if 0
2810 /* Tests using Samba4 against W2K show this call never creates a blocking lock. */
2811 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
2813 * A blocking lock was requested. Package up
2814 * this smb into a queued request and push it
2815 * onto the blocking lock queue.
2817 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), offset, count)) {
2818 END_PROFILE(SMBlock);
2819 return -1;
2822 #endif
2823 END_PROFILE(SMBlock);
2824 return ERROR_NT(status);
2827 END_PROFILE(SMBlock);
2828 return(outsize);
2831 /****************************************************************************
2832 Reply to a unlock.
2833 ****************************************************************************/
2835 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
2836 int dum_buffsize)
2838 int outsize = set_message(outbuf,0,0,True);
2839 SMB_BIG_UINT count,offset;
2840 NTSTATUS status;
2841 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2842 START_PROFILE(SMBunlock);
2844 CHECK_FSP(fsp,conn);
2846 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2847 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2849 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
2850 if (NT_STATUS_V(status)) {
2851 END_PROFILE(SMBunlock);
2852 return ERROR_NT(status);
2855 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2856 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
2858 END_PROFILE(SMBunlock);
2859 return(outsize);
2862 /****************************************************************************
2863 Reply to a tdis.
2864 ****************************************************************************/
2866 int reply_tdis(connection_struct *conn,
2867 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2869 int outsize = set_message(outbuf,0,0,True);
2870 uint16 vuid;
2871 START_PROFILE(SMBtdis);
2873 vuid = SVAL(inbuf,smb_uid);
2875 if (!conn) {
2876 DEBUG(4,("Invalid connection in tdis\n"));
2877 END_PROFILE(SMBtdis);
2878 return ERROR_DOS(ERRSRV,ERRinvnid);
2881 conn->used = False;
2883 close_cnum(conn,vuid);
2885 END_PROFILE(SMBtdis);
2886 return outsize;
2889 /****************************************************************************
2890 Reply to a echo.
2891 ****************************************************************************/
2893 int reply_echo(connection_struct *conn,
2894 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2896 int smb_reverb = SVAL(inbuf,smb_vwv0);
2897 int seq_num;
2898 unsigned int data_len = smb_buflen(inbuf);
2899 int outsize = set_message(outbuf,1,data_len,True);
2900 START_PROFILE(SMBecho);
2902 if (data_len > BUFFER_SIZE) {
2903 DEBUG(0,("reply_echo: data_len too large.\n"));
2904 END_PROFILE(SMBecho);
2905 return -1;
2908 /* copy any incoming data back out */
2909 if (data_len > 0)
2910 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2912 if (smb_reverb > 100) {
2913 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2914 smb_reverb = 100;
2917 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
2918 SSVAL(outbuf,smb_vwv0,seq_num);
2920 smb_setlen(outbuf,outsize - 4);
2922 if (!send_smb(smbd_server_fd(),outbuf))
2923 exit_server("reply_echo: send_smb failed.");
2926 DEBUG(3,("echo %d times\n", smb_reverb));
2928 smb_echo_count++;
2930 END_PROFILE(SMBecho);
2931 return -1;
2934 /****************************************************************************
2935 Reply to a printopen.
2936 ****************************************************************************/
2938 int reply_printopen(connection_struct *conn,
2939 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2941 int outsize = 0;
2942 files_struct *fsp;
2943 START_PROFILE(SMBsplopen);
2945 if (!CAN_PRINT(conn)) {
2946 END_PROFILE(SMBsplopen);
2947 return ERROR_DOS(ERRDOS,ERRnoaccess);
2950 /* Open for exclusive use, write only. */
2951 fsp = print_fsp_open(conn, NULL);
2953 if (!fsp) {
2954 END_PROFILE(SMBsplopen);
2955 return(UNIXERROR(ERRDOS,ERRnoaccess));
2958 outsize = set_message(outbuf,1,0,True);
2959 SSVAL(outbuf,smb_vwv0,fsp->fnum);
2961 DEBUG(3,("openprint fd=%d fnum=%d\n",
2962 fsp->fd, fsp->fnum));
2964 END_PROFILE(SMBsplopen);
2965 return(outsize);
2968 /****************************************************************************
2969 Reply to a printclose.
2970 ****************************************************************************/
2972 int reply_printclose(connection_struct *conn,
2973 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2975 int outsize = set_message(outbuf,0,0,True);
2976 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2977 int close_err = 0;
2978 START_PROFILE(SMBsplclose);
2980 CHECK_FSP(fsp,conn);
2982 if (!CAN_PRINT(conn)) {
2983 END_PROFILE(SMBsplclose);
2984 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
2987 DEBUG(3,("printclose fd=%d fnum=%d\n",
2988 fsp->fd,fsp->fnum));
2990 close_err = close_file(fsp,True);
2992 if(close_err != 0) {
2993 errno = close_err;
2994 END_PROFILE(SMBsplclose);
2995 return(UNIXERROR(ERRHRD,ERRgeneral));
2998 END_PROFILE(SMBsplclose);
2999 return(outsize);
3002 /****************************************************************************
3003 Reply to a printqueue.
3004 ****************************************************************************/
3006 int reply_printqueue(connection_struct *conn,
3007 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3009 int outsize = set_message(outbuf,2,3,True);
3010 int max_count = SVAL(inbuf,smb_vwv0);
3011 int start_index = SVAL(inbuf,smb_vwv1);
3012 START_PROFILE(SMBsplretq);
3014 /* we used to allow the client to get the cnum wrong, but that
3015 is really quite gross and only worked when there was only
3016 one printer - I think we should now only accept it if they
3017 get it right (tridge) */
3018 if (!CAN_PRINT(conn)) {
3019 END_PROFILE(SMBsplretq);
3020 return ERROR_DOS(ERRDOS,ERRnoaccess);
3023 SSVAL(outbuf,smb_vwv0,0);
3024 SSVAL(outbuf,smb_vwv1,0);
3025 SCVAL(smb_buf(outbuf),0,1);
3026 SSVAL(smb_buf(outbuf),1,0);
3028 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3029 start_index, max_count));
3032 print_queue_struct *queue = NULL;
3033 print_status_struct status;
3034 char *p = smb_buf(outbuf) + 3;
3035 int count = print_queue_status(SNUM(conn), &queue, &status);
3036 int num_to_get = ABS(max_count);
3037 int first = (max_count>0?start_index:start_index+max_count+1);
3038 int i;
3040 if (first >= count)
3041 num_to_get = 0;
3042 else
3043 num_to_get = MIN(num_to_get,count-first);
3046 for (i=first;i<first+num_to_get;i++) {
3047 put_dos_date2(p,0,queue[i].time);
3048 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
3049 SSVAL(p,5, queue[i].job);
3050 SIVAL(p,7,queue[i].size);
3051 SCVAL(p,11,0);
3052 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
3053 p += 28;
3056 if (count > 0) {
3057 outsize = set_message(outbuf,2,28*count+3,False);
3058 SSVAL(outbuf,smb_vwv0,count);
3059 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3060 SCVAL(smb_buf(outbuf),0,1);
3061 SSVAL(smb_buf(outbuf),1,28*count);
3064 SAFE_FREE(queue);
3066 DEBUG(3,("%d entries returned in queue\n",count));
3069 END_PROFILE(SMBsplretq);
3070 return(outsize);
3073 /****************************************************************************
3074 Reply to a printwrite.
3075 ****************************************************************************/
3077 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3079 int numtowrite;
3080 int outsize = set_message(outbuf,0,0,True);
3081 char *data;
3082 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3084 START_PROFILE(SMBsplwr);
3086 if (!CAN_PRINT(conn)) {
3087 END_PROFILE(SMBsplwr);
3088 return ERROR_DOS(ERRDOS,ERRnoaccess);
3091 CHECK_FSP(fsp,conn);
3092 CHECK_WRITE(fsp);
3094 numtowrite = SVAL(smb_buf(inbuf),1);
3095 data = smb_buf(inbuf) + 3;
3097 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3098 END_PROFILE(SMBsplwr);
3099 return(UNIXERROR(ERRHRD,ERRdiskfull));
3102 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3104 END_PROFILE(SMBsplwr);
3105 return(outsize);
3108 /****************************************************************************
3109 The guts of the mkdir command, split out so it may be called by the NT SMB
3110 code.
3111 ****************************************************************************/
3113 NTSTATUS mkdir_internal(connection_struct *conn, pstring directory)
3115 BOOL bad_path = False;
3116 SMB_STRUCT_STAT sbuf;
3117 int ret= -1;
3119 unix_convert(directory,conn,0,&bad_path,&sbuf);
3121 if( strchr_m(directory, ':')) {
3122 return NT_STATUS_NOT_A_DIRECTORY;
3125 if (ms_has_wild(directory)) {
3126 return NT_STATUS_OBJECT_NAME_INVALID;
3129 if (check_name(directory, conn))
3130 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory));
3132 if (ret == -1) {
3133 if(errno == ENOENT) {
3134 if (bad_path)
3135 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3136 else
3137 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3139 return map_nt_error_from_unix(errno);
3142 return NT_STATUS_OK;
3145 /****************************************************************************
3146 Reply to a mkdir.
3147 ****************************************************************************/
3149 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3151 pstring directory;
3152 int outsize;
3153 NTSTATUS status;
3154 START_PROFILE(SMBmkdir);
3156 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
3157 if (!NT_STATUS_IS_OK(status)) {
3158 END_PROFILE(SMBmkdir);
3159 return ERROR_NT(status);
3162 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
3164 status = mkdir_internal(conn, directory);
3165 if (!NT_STATUS_IS_OK(status)) {
3166 END_PROFILE(SMBmkdir);
3167 return ERROR_NT(status);
3170 outsize = set_message(outbuf,0,0,True);
3172 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3174 END_PROFILE(SMBmkdir);
3175 return(outsize);
3178 /****************************************************************************
3179 Static function used by reply_rmdir to delete an entire directory
3180 tree recursively. Return False on ok, True on fail.
3181 ****************************************************************************/
3183 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3185 const char *dname = NULL;
3186 BOOL ret = False;
3187 void *dirptr = OpenDir(conn, directory, False);
3189 if(dirptr == NULL)
3190 return True;
3192 while((dname = ReadDirName(dirptr))) {
3193 pstring fullname;
3194 SMB_STRUCT_STAT st;
3196 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3197 continue;
3199 /* Construct the full name. */
3200 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3201 errno = ENOMEM;
3202 ret = True;
3203 break;
3206 pstrcpy(fullname, directory);
3207 pstrcat(fullname, "/");
3208 pstrcat(fullname, dname);
3210 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
3211 ret = True;
3212 break;
3215 if(st.st_mode & S_IFDIR) {
3216 if(recursive_rmdir(conn, fullname)!=0) {
3217 ret = True;
3218 break;
3220 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
3221 ret = True;
3222 break;
3224 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
3225 ret = True;
3226 break;
3229 CloseDir(dirptr);
3230 return ret;
3233 /****************************************************************************
3234 The internals of the rmdir code - called elsewhere.
3235 ****************************************************************************/
3237 BOOL rmdir_internals(connection_struct *conn, char *directory)
3239 BOOL ok;
3241 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3242 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3244 * Check to see if the only thing in this directory are
3245 * vetoed files/directories. If so then delete them and
3246 * retry. If we fail to delete any of them (and we *don't*
3247 * do a recursive delete) then fail the rmdir.
3249 BOOL all_veto_files = True;
3250 const char *dname;
3251 void *dirptr = OpenDir(conn, directory, False);
3253 if(dirptr != NULL) {
3254 int dirpos = TellDir(dirptr);
3255 while ((dname = ReadDirName(dirptr))) {
3256 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3257 continue;
3258 if(!IS_VETO_PATH(conn, dname)) {
3259 all_veto_files = False;
3260 break;
3264 if(all_veto_files) {
3265 SeekDir(dirptr,dirpos);
3266 while ((dname = ReadDirName(dirptr))) {
3267 pstring fullname;
3268 SMB_STRUCT_STAT st;
3270 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3271 continue;
3273 /* Construct the full name. */
3274 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3275 errno = ENOMEM;
3276 break;
3279 pstrcpy(fullname, directory);
3280 pstrcat(fullname, "/");
3281 pstrcat(fullname, dname);
3283 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
3284 break;
3285 if(st.st_mode & S_IFDIR) {
3286 if(lp_recursive_veto_delete(SNUM(conn))) {
3287 if(recursive_rmdir(conn, fullname) != 0)
3288 break;
3290 if(SMB_VFS_RMDIR(conn,fullname) != 0)
3291 break;
3292 } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
3293 break;
3295 CloseDir(dirptr);
3296 /* Retry the rmdir */
3297 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3298 } else {
3299 CloseDir(dirptr);
3301 } else {
3302 errno = ENOTEMPTY;
3306 if (!ok)
3307 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
3309 return ok;
3312 /****************************************************************************
3313 Reply to a rmdir.
3314 ****************************************************************************/
3316 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3318 pstring directory;
3319 int outsize = 0;
3320 BOOL ok = False;
3321 BOOL bad_path = False;
3322 SMB_STRUCT_STAT sbuf;
3323 NTSTATUS status;
3324 START_PROFILE(SMBrmdir);
3326 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
3327 if (!NT_STATUS_IS_OK(status)) {
3328 END_PROFILE(SMBrmdir);
3329 return ERROR_NT(status);
3332 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3334 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3336 if (check_name(directory,conn)) {
3337 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3338 ok = rmdir_internals(conn, directory);
3341 if (!ok) {
3342 END_PROFILE(SMBrmdir);
3343 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRbadpath);
3346 outsize = set_message(outbuf,0,0,True);
3348 DEBUG( 3, ( "rmdir %s\n", directory ) );
3350 END_PROFILE(SMBrmdir);
3351 return(outsize);
3354 /*******************************************************************
3355 Resolve wildcards in a filename rename.
3356 ********************************************************************/
3358 static BOOL resolve_wildcards(const char *name1, char *name2)
3360 fstring root1,root2;
3361 fstring ext1,ext2;
3362 char *p,*p2, *pname1, *pname2;
3363 int available_space;
3366 pname1 = strrchr_m(name1,'/');
3367 pname2 = strrchr_m(name2,'/');
3369 if (!pname1 || !pname2)
3370 return(False);
3372 fstrcpy(root1,pname1);
3373 fstrcpy(root2,pname2);
3374 p = strrchr_m(root1,'.');
3375 if (p) {
3376 *p = 0;
3377 fstrcpy(ext1,p+1);
3378 } else {
3379 fstrcpy(ext1,"");
3381 p = strrchr_m(root2,'.');
3382 if (p) {
3383 *p = 0;
3384 fstrcpy(ext2,p+1);
3385 } else {
3386 fstrcpy(ext2,"");
3389 p = root1;
3390 p2 = root2;
3391 while (*p2) {
3392 if (*p2 == '?') {
3393 *p2 = *p;
3394 p2++;
3395 } else {
3396 p2++;
3398 if (*p)
3399 p++;
3402 p = ext1;
3403 p2 = ext2;
3404 while (*p2) {
3405 if (*p2 == '?') {
3406 *p2 = *p;
3407 p2++;
3408 } else {
3409 p2++;
3411 if (*p)
3412 p++;
3415 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
3417 if (ext2[0]) {
3418 snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
3419 } else {
3420 pstrcpy_base(pname2, root2, name2);
3423 return(True);
3426 /****************************************************************************
3427 Ensure open files have their names updates.
3428 ****************************************************************************/
3430 static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode, char *newname)
3432 files_struct *fsp;
3433 BOOL did_rename = False;
3435 for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
3436 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
3437 fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
3438 fsp->fsp_name, newname ));
3439 string_set(&fsp->fsp_name, newname);
3440 did_rename = True;
3443 if (!did_rename)
3444 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
3445 (unsigned int)dev, (double)inode, newname ));
3448 /****************************************************************************
3449 Rename an open file - given an fsp.
3450 ****************************************************************************/
3452 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, BOOL replace_if_exists)
3454 SMB_STRUCT_STAT sbuf;
3455 BOOL bad_path = False;
3456 pstring newname_last_component;
3457 NTSTATUS error = NT_STATUS_OK;
3458 BOOL dest_exists;
3459 BOOL rcdest = True;
3461 ZERO_STRUCT(sbuf);
3462 rcdest = unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf);
3464 /* Quick check for "." and ".." */
3465 if (!bad_path && newname_last_component[0] == '.') {
3466 if (!newname_last_component[1] || (newname_last_component[1] == '.' && !newname_last_component[2])) {
3467 return NT_STATUS_ACCESS_DENIED;
3470 if (!rcdest && bad_path) {
3471 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3474 /* Ensure newname contains a '/' */
3475 if(strrchr_m(newname,'/') == 0) {
3476 pstring tmpstr;
3478 pstrcpy(tmpstr, "./");
3479 pstrcat(tmpstr, newname);
3480 pstrcpy(newname, tmpstr);
3484 * Check for special case with case preserving and not
3485 * case sensitive. If the old last component differs from the original
3486 * last component only by case, then we should allow
3487 * the rename (user is trying to change the case of the
3488 * filename).
3491 if((case_sensitive == False) && (case_preserve == True) &&
3492 strequal(newname, fsp->fsp_name)) {
3493 char *p;
3494 pstring newname_modified_last_component;
3497 * Get the last component of the modified name.
3498 * Note that we guarantee that newname contains a '/'
3499 * character above.
3501 p = strrchr_m(newname,'/');
3502 pstrcpy(newname_modified_last_component,p+1);
3504 if(strcsequal(newname_modified_last_component,
3505 newname_last_component) == False) {
3507 * Replace the modified last component with
3508 * the original.
3510 pstrcpy(p+1, newname_last_component);
3515 * If the src and dest names are identical - including case,
3516 * don't do the rename, just return success.
3519 if (strcsequal(fsp->fsp_name, newname)) {
3520 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
3521 newname));
3522 return NT_STATUS_OK;
3525 dest_exists = vfs_object_exist(conn,newname,NULL);
3527 if(!replace_if_exists && dest_exists) {
3528 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
3529 fsp->fsp_name,newname));
3530 return NT_STATUS_OBJECT_NAME_COLLISION;
3533 error = can_rename(newname,conn,&sbuf);
3535 if (dest_exists && !NT_STATUS_IS_OK(error)) {
3536 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3537 nt_errstr(error), fsp->fsp_name,newname));
3538 if (NT_STATUS_EQUAL(error,NT_STATUS_SHARING_VIOLATION))
3539 error = NT_STATUS_ACCESS_DENIED;
3540 return error;
3543 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
3544 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
3545 fsp->fsp_name,newname));
3546 rename_open_files(conn, fsp->dev, fsp->inode, newname);
3547 return NT_STATUS_OK;
3550 if (errno == ENOTDIR || errno == EISDIR)
3551 error = NT_STATUS_OBJECT_NAME_COLLISION;
3552 else
3553 error = map_nt_error_from_unix(errno);
3555 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
3556 nt_errstr(error), fsp->fsp_name,newname));
3558 return error;
3561 /****************************************************************************
3562 The guts of the rename command, split out so it may be called by the NT SMB
3563 code.
3564 ****************************************************************************/
3566 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, uint16 attrs, BOOL replace_if_exists)
3568 pstring directory;
3569 pstring mask;
3570 pstring last_component_src;
3571 pstring last_component_dest;
3572 char *p;
3573 BOOL has_wild;
3574 BOOL bad_path_src = False;
3575 BOOL bad_path_dest = False;
3576 int count=0;
3577 NTSTATUS error = NT_STATUS_OK;
3578 BOOL rc = True;
3579 BOOL rcdest = True;
3580 SMB_STRUCT_STAT sbuf1, sbuf2;
3582 *directory = *mask = 0;
3584 ZERO_STRUCT(sbuf1);
3585 ZERO_STRUCT(sbuf2);
3587 rc = unix_convert(name,conn,last_component_src,&bad_path_src,&sbuf1);
3588 if (!rc && bad_path_src) {
3589 if (ms_has_wild(last_component_src))
3590 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3591 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3594 /* Quick check for "." and ".." */
3595 if (last_component_src[0] == '.') {
3596 if (!last_component_src[1] || (last_component_src[1] == '.' && !last_component_src[2])) {
3597 return NT_STATUS_OBJECT_NAME_INVALID;
3601 rcdest = unix_convert(newname,conn,last_component_dest,&bad_path_dest,&sbuf2);
3603 /* Quick check for "." and ".." */
3604 if (last_component_dest[0] == '.') {
3605 if (!last_component_dest[1] || (last_component_dest[1] == '.' && !last_component_dest[2])) {
3606 return NT_STATUS_OBJECT_NAME_INVALID;
3611 * Split the old name into directory and last component
3612 * strings. Note that unix_convert may have stripped off a
3613 * leading ./ from both name and newname if the rename is
3614 * at the root of the share. We need to make sure either both
3615 * name and newname contain a / character or neither of them do
3616 * as this is checked in resolve_wildcards().
3619 p = strrchr_m(name,'/');
3620 if (!p) {
3621 pstrcpy(directory,".");
3622 pstrcpy(mask,name);
3623 } else {
3624 *p = 0;
3625 pstrcpy(directory,name);
3626 pstrcpy(mask,p+1);
3627 *p = '/'; /* Replace needed for exceptional test below. */
3631 * We should only check the mangled cache
3632 * here if unix_convert failed. This means
3633 * that the path in 'mask' doesn't exist
3634 * on the file system and so we need to look
3635 * for a possible mangle. This patch from
3636 * Tine Smukavec <valentin.smukavec@hermes.si>.
3639 if (!rc && mangle_is_mangled(mask))
3640 mangle_check_cache( mask );
3642 has_wild = ms_has_wild(mask);
3644 if (!has_wild) {
3646 * No wildcards - just process the one file.
3648 BOOL is_short_name = mangle_is_8_3(name, True);
3650 /* Add a terminating '/' to the directory name. */
3651 pstrcat(directory,"/");
3652 pstrcat(directory,mask);
3654 /* Ensure newname contains a '/' also */
3655 if(strrchr_m(newname,'/') == 0) {
3656 pstring tmpstr;
3658 pstrcpy(tmpstr, "./");
3659 pstrcat(tmpstr, newname);
3660 pstrcpy(newname, tmpstr);
3663 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
3664 directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
3665 case_sensitive, case_preserve, short_case_preserve, directory,
3666 newname, last_component_dest, is_short_name));
3669 * Check for special case with case preserving and not
3670 * case sensitive, if directory and newname are identical,
3671 * and the old last component differs from the original
3672 * last component only by case, then we should allow
3673 * the rename (user is trying to change the case of the
3674 * filename).
3676 if((case_sensitive == False) &&
3677 (((case_preserve == True) &&
3678 (is_short_name == False)) ||
3679 ((short_case_preserve == True) &&
3680 (is_short_name == True))) &&
3681 strcsequal(directory, newname)) {
3682 pstring modified_last_component;
3685 * Get the last component of the modified name.
3686 * Note that we guarantee that newname contains a '/'
3687 * character above.
3689 p = strrchr_m(newname,'/');
3690 pstrcpy(modified_last_component,p+1);
3692 if(strcsequal(modified_last_component,
3693 last_component_dest) == False) {
3695 * Replace the modified last component with
3696 * the original.
3698 pstrcpy(p+1, last_component_dest);
3702 resolve_wildcards(directory,newname);
3705 * The source object must exist.
3708 if (!vfs_object_exist(conn, directory, &sbuf1)) {
3709 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
3710 directory,newname));
3712 if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
3714 * Must return different errors depending on whether the parent
3715 * directory existed or not.
3718 p = strrchr_m(directory, '/');
3719 if (!p)
3720 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3721 *p = '\0';
3722 if (vfs_object_exist(conn, directory, NULL))
3723 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3724 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3726 error = map_nt_error_from_unix(errno);
3727 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3728 nt_errstr(error), directory,newname));
3730 return error;
3733 if (!rcdest && bad_path_dest) {
3734 if (ms_has_wild(last_component_dest))
3735 return NT_STATUS_OBJECT_NAME_INVALID;
3736 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3739 error = can_rename(directory,conn,&sbuf1);
3741 if (!NT_STATUS_IS_OK(error)) {
3742 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3743 nt_errstr(error), directory,newname));
3744 return error;
3748 * If the src and dest names are identical - including case,
3749 * don't do the rename, just return success.
3752 if (strcsequal(directory, newname)) {
3753 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3754 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
3755 return NT_STATUS_OK;
3758 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
3759 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
3760 directory,newname));
3761 return NT_STATUS_OBJECT_NAME_COLLISION;
3764 if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
3765 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
3766 directory,newname));
3767 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3768 return NT_STATUS_OK;
3771 if (errno == ENOTDIR || errno == EISDIR)
3772 error = NT_STATUS_OBJECT_NAME_COLLISION;
3773 else
3774 error = map_nt_error_from_unix(errno);
3776 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3777 nt_errstr(error), directory,newname));
3779 return error;
3780 } else {
3782 * Wildcards - process each file that matches.
3784 void *dirptr = NULL;
3785 const char *dname;
3786 pstring destname;
3788 if (check_name(directory,conn))
3789 dirptr = OpenDir(conn, directory, True);
3791 if (dirptr) {
3792 error = NT_STATUS_NO_SUCH_FILE;
3793 /* Was error = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */
3795 if (strequal(mask,"????????.???"))
3796 pstrcpy(mask,"*");
3798 while ((dname = ReadDirName(dirptr))) {
3799 pstring fname;
3800 BOOL sysdir_entry = False;
3802 pstrcpy(fname,dname);
3804 /* Quick check for "." and ".." */
3805 if (fname[0] == '.') {
3806 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
3807 if (attrs & aDIR) {
3808 sysdir_entry = True;
3809 } else {
3810 continue;
3815 if(!mask_match(fname, mask, case_sensitive))
3816 continue;
3818 if (sysdir_entry) {
3819 error = NT_STATUS_OBJECT_NAME_INVALID;
3820 continue;
3823 error = NT_STATUS_ACCESS_DENIED;
3824 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3825 if (!vfs_object_exist(conn, fname, &sbuf1)) {
3826 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3827 DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
3828 continue;
3830 error = can_rename(fname,conn,&sbuf1);
3831 if (!NT_STATUS_IS_OK(error)) {
3832 DEBUG(6,("rename %s refused\n", fname));
3833 continue;
3835 pstrcpy(destname,newname);
3837 if (!resolve_wildcards(fname,destname)) {
3838 DEBUG(6,("resolve_wildcards %s %s failed\n",
3839 fname, destname));
3840 continue;
3843 if (!replace_if_exists &&
3844 vfs_file_exist(conn,destname, NULL)) {
3845 DEBUG(6,("file_exist %s\n", destname));
3846 error = NT_STATUS_OBJECT_NAME_COLLISION;
3847 continue;
3850 if (!SMB_VFS_RENAME(conn,fname,destname)) {
3851 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3852 count++;
3853 error = NT_STATUS_OK;
3855 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3857 CloseDir(dirptr);
3860 if (!NT_STATUS_EQUAL(error,NT_STATUS_NO_SUCH_FILE)) {
3861 if (!rcdest && bad_path_dest) {
3862 if (ms_has_wild(last_component_dest))
3863 return NT_STATUS_OBJECT_NAME_INVALID;
3864 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3869 if (count == 0 && NT_STATUS_IS_OK(error)) {
3870 error = map_nt_error_from_unix(errno);
3873 return error;
3876 /****************************************************************************
3877 Reply to a mv.
3878 ****************************************************************************/
3880 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
3881 int dum_buffsize)
3883 int outsize = 0;
3884 pstring name;
3885 pstring newname;
3886 char *p;
3887 uint16 attrs = SVAL(inbuf,smb_vwv0);
3888 NTSTATUS status;
3890 START_PROFILE(SMBmv);
3892 p = smb_buf(inbuf) + 1;
3893 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status);
3894 if (!NT_STATUS_IS_OK(status)) {
3895 END_PROFILE(SMBmv);
3896 return ERROR_NT(status);
3898 p++;
3899 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status);
3900 if (!NT_STATUS_IS_OK(status)) {
3901 END_PROFILE(SMBmv);
3902 return ERROR_NT(status);
3905 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3906 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3908 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3910 status = rename_internals(conn, name, newname, attrs, False);
3911 if (!NT_STATUS_IS_OK(status)) {
3912 END_PROFILE(SMBmv);
3913 return ERROR_NT(status);
3917 * Win2k needs a changenotify request response before it will
3918 * update after a rename..
3920 process_pending_change_notify_queue((time_t)0);
3921 outsize = set_message(outbuf,0,0,True);
3923 END_PROFILE(SMBmv);
3924 return(outsize);
3927 /*******************************************************************
3928 Copy a file as part of a reply_copy.
3929 ******************************************************************/
3931 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3932 int count,BOOL target_is_directory, int *err_ret)
3934 int Access,action;
3935 SMB_STRUCT_STAT src_sbuf, sbuf2;
3936 SMB_OFF_T ret=-1;
3937 files_struct *fsp1,*fsp2;
3938 pstring dest;
3940 *err_ret = 0;
3942 pstrcpy(dest,dest1);
3943 if (target_is_directory) {
3944 char *p = strrchr_m(src,'/');
3945 if (p)
3946 p++;
3947 else
3948 p = src;
3949 pstrcat(dest,"/");
3950 pstrcat(dest,p);
3953 if (!vfs_file_exist(conn,src,&src_sbuf))
3954 return(False);
3956 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
3957 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
3959 if (!fsp1)
3960 return(False);
3962 if (!target_is_directory && count)
3963 ofun = FILE_EXISTS_OPEN;
3965 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1)
3966 ZERO_STRUCTP(&sbuf2);
3968 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
3969 ofun,src_sbuf.st_mode,0,&Access,&action);
3971 if (!fsp2) {
3972 close_file(fsp1,False);
3973 return(False);
3976 if ((ofun&3) == 1) {
3977 if(SMB_VFS_LSEEK(fsp2,fsp2->fd,0,SEEK_END) == -1) {
3978 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
3980 * Stop the copy from occurring.
3982 ret = -1;
3983 src_sbuf.st_size = 0;
3987 if (src_sbuf.st_size)
3988 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
3990 close_file(fsp1,False);
3992 /* Ensure the modtime is set correctly on the destination file. */
3993 fsp2->pending_modtime = src_sbuf.st_mtime;
3996 * As we are opening fsp1 read-only we only expect
3997 * an error on close on fsp2 if we are out of space.
3998 * Thus we don't look at the error return from the
3999 * close of fsp1.
4001 *err_ret = close_file(fsp2,False);
4003 return(ret == (SMB_OFF_T)src_sbuf.st_size);
4006 /****************************************************************************
4007 Reply to a file copy.
4008 ****************************************************************************/
4010 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4012 int outsize = 0;
4013 pstring name;
4014 pstring directory;
4015 pstring mask,newname;
4016 char *p;
4017 int count=0;
4018 int error = ERRnoaccess;
4019 int err = 0;
4020 BOOL has_wild;
4021 BOOL exists=False;
4022 int tid2 = SVAL(inbuf,smb_vwv0);
4023 int ofun = SVAL(inbuf,smb_vwv1);
4024 int flags = SVAL(inbuf,smb_vwv2);
4025 BOOL target_is_directory=False;
4026 BOOL bad_path1 = False;
4027 BOOL bad_path2 = False;
4028 BOOL rc = True;
4029 SMB_STRUCT_STAT sbuf1, sbuf2;
4030 NTSTATUS status;
4032 START_PROFILE(SMBcopy);
4034 *directory = *mask = 0;
4036 p = smb_buf(inbuf);
4037 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status);
4038 if (!NT_STATUS_IS_OK(status)) {
4039 END_PROFILE(SMBcopy);
4040 return ERROR_NT(status);
4042 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status);
4043 if (!NT_STATUS_IS_OK(status)) {
4044 END_PROFILE(SMBcopy);
4045 return ERROR_NT(status);
4048 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
4050 if (tid2 != conn->cnum) {
4051 /* can't currently handle inter share copies XXXX */
4052 DEBUG(3,("Rejecting inter-share copy\n"));
4053 END_PROFILE(SMBcopy);
4054 return ERROR_DOS(ERRSRV,ERRinvdevice);
4057 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
4058 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4060 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
4061 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
4063 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
4065 if ((flags&1) && target_is_directory) {
4066 END_PROFILE(SMBcopy);
4067 return ERROR_DOS(ERRDOS,ERRbadfile);
4070 if ((flags&2) && !target_is_directory) {
4071 END_PROFILE(SMBcopy);
4072 return ERROR_DOS(ERRDOS,ERRbadpath);
4075 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
4076 /* wants a tree copy! XXXX */
4077 DEBUG(3,("Rejecting tree copy\n"));
4078 END_PROFILE(SMBcopy);
4079 return ERROR_DOS(ERRSRV,ERRerror);
4082 p = strrchr_m(name,'/');
4083 if (!p) {
4084 pstrcpy(directory,"./");
4085 pstrcpy(mask,name);
4086 } else {
4087 *p = 0;
4088 pstrcpy(directory,name);
4089 pstrcpy(mask,p+1);
4093 * We should only check the mangled cache
4094 * here if unix_convert failed. This means
4095 * that the path in 'mask' doesn't exist
4096 * on the file system and so we need to look
4097 * for a possible mangle. This patch from
4098 * Tine Smukavec <valentin.smukavec@hermes.si>.
4101 if (!rc && mangle_is_mangled(mask))
4102 mangle_check_cache( mask );
4104 has_wild = ms_has_wild(mask);
4106 if (!has_wild) {
4107 pstrcat(directory,"/");
4108 pstrcat(directory,mask);
4109 if (resolve_wildcards(directory,newname) &&
4110 copy_file(directory,newname,conn,ofun, count,target_is_directory,&err))
4111 count++;
4112 if(!count && err) {
4113 errno = err;
4114 END_PROFILE(SMBcopy);
4115 return(UNIXERROR(ERRHRD,ERRgeneral));
4117 if (!count) {
4118 exists = vfs_file_exist(conn,directory,NULL);
4120 } else {
4121 void *dirptr = NULL;
4122 const char *dname;
4123 pstring destname;
4125 if (check_name(directory,conn))
4126 dirptr = OpenDir(conn, directory, True);
4128 if (dirptr) {
4129 error = ERRbadfile;
4131 if (strequal(mask,"????????.???"))
4132 pstrcpy(mask,"*");
4134 while ((dname = ReadDirName(dirptr))) {
4135 pstring fname;
4136 pstrcpy(fname,dname);
4138 if(!mask_match(fname, mask, case_sensitive))
4139 continue;
4141 error = ERRnoaccess;
4142 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
4143 pstrcpy(destname,newname);
4144 if (resolve_wildcards(fname,destname) &&
4145 copy_file(fname,destname,conn,ofun,
4146 count,target_is_directory,&err))
4147 count++;
4148 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
4150 CloseDir(dirptr);
4154 if (count == 0) {
4155 if(err) {
4156 /* Error on close... */
4157 errno = err;
4158 END_PROFILE(SMBcopy);
4159 return(UNIXERROR(ERRHRD,ERRgeneral));
4162 if (exists) {
4163 END_PROFILE(SMBcopy);
4164 return ERROR_DOS(ERRDOS,error);
4165 } else {
4166 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
4167 unix_ERR_class = ERRDOS;
4168 unix_ERR_code = ERRbadpath;
4170 END_PROFILE(SMBcopy);
4171 return(UNIXERROR(ERRDOS,error));
4175 outsize = set_message(outbuf,1,0,True);
4176 SSVAL(outbuf,smb_vwv0,count);
4178 END_PROFILE(SMBcopy);
4179 return(outsize);
4182 /****************************************************************************
4183 Reply to a setdir.
4184 ****************************************************************************/
4186 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4188 int snum;
4189 int outsize = 0;
4190 BOOL ok = False;
4191 pstring newdir;
4192 NTSTATUS status;
4194 START_PROFILE(pathworks_setdir);
4196 snum = SNUM(conn);
4197 if (!CAN_SETDIR(snum)) {
4198 END_PROFILE(pathworks_setdir);
4199 return ERROR_DOS(ERRDOS,ERRnoaccess);
4202 srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status);
4203 if (!NT_STATUS_IS_OK(status)) {
4204 END_PROFILE(pathworks_setdir);
4205 return ERROR_NT(status);
4208 if (strlen(newdir) == 0) {
4209 ok = True;
4210 } else {
4211 ok = vfs_directory_exist(conn,newdir,NULL);
4212 if (ok)
4213 string_set(&conn->connectpath,newdir);
4216 if (!ok) {
4217 END_PROFILE(pathworks_setdir);
4218 return ERROR_DOS(ERRDOS,ERRbadpath);
4221 outsize = set_message(outbuf,0,0,True);
4222 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
4224 DEBUG(3,("setdir %s\n", newdir));
4226 END_PROFILE(pathworks_setdir);
4227 return(outsize);
4230 /****************************************************************************
4231 Get a lock pid, dealing with large count requests.
4232 ****************************************************************************/
4234 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
4236 if(!large_file_format)
4237 return SVAL(data,SMB_LPID_OFFSET(data_offset));
4238 else
4239 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
4242 /****************************************************************************
4243 Get a lock count, dealing with large count requests.
4244 ****************************************************************************/
4246 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4248 SMB_BIG_UINT count = 0;
4250 if(!large_file_format) {
4251 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4252 } else {
4254 #if defined(HAVE_LONGLONG)
4255 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4256 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4257 #else /* HAVE_LONGLONG */
4260 * NT4.x seems to be broken in that it sends large file (64 bit)
4261 * lockingX calls even if the CAP_LARGE_FILES was *not*
4262 * negotiated. For boxes without large unsigned ints truncate the
4263 * lock count by dropping the top 32 bits.
4266 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4267 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4268 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4269 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4270 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4273 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4274 #endif /* HAVE_LONGLONG */
4277 return count;
4280 #if !defined(HAVE_LONGLONG)
4281 /****************************************************************************
4282 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
4283 ****************************************************************************/
4285 static uint32 map_lock_offset(uint32 high, uint32 low)
4287 unsigned int i;
4288 uint32 mask = 0;
4289 uint32 highcopy = high;
4292 * Try and find out how many significant bits there are in high.
4295 for(i = 0; highcopy; i++)
4296 highcopy >>= 1;
4299 * We use 31 bits not 32 here as POSIX
4300 * lock offsets may not be negative.
4303 mask = (~0) << (31 - i);
4305 if(low & mask)
4306 return 0; /* Fail. */
4308 high <<= (31 - i);
4310 return (high|low);
4312 #endif /* !defined(HAVE_LONGLONG) */
4314 /****************************************************************************
4315 Get a lock offset, dealing with large offset requests.
4316 ****************************************************************************/
4318 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4320 SMB_BIG_UINT offset = 0;
4322 *err = False;
4324 if(!large_file_format) {
4325 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4326 } else {
4328 #if defined(HAVE_LONGLONG)
4329 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4330 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4331 #else /* HAVE_LONGLONG */
4334 * NT4.x seems to be broken in that it sends large file (64 bit)
4335 * lockingX calls even if the CAP_LARGE_FILES was *not*
4336 * negotiated. For boxes without large unsigned ints mangle the
4337 * lock offset by mapping the top 32 bits onto the lower 32.
4340 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4341 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4342 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4343 uint32 new_low = 0;
4345 if((new_low = map_lock_offset(high, low)) == 0) {
4346 *err = True;
4347 return (SMB_BIG_UINT)-1;
4350 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4351 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4352 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4353 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4356 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4357 #endif /* HAVE_LONGLONG */
4360 return offset;
4363 /****************************************************************************
4364 Reply to a lockingX request.
4365 ****************************************************************************/
4367 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4369 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4370 unsigned char locktype = CVAL(inbuf,smb_vwv3);
4371 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4372 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4373 uint16 num_locks = SVAL(inbuf,smb_vwv7);
4374 SMB_BIG_UINT count = 0, offset = 0;
4375 uint16 lock_pid;
4376 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4377 int i;
4378 char *data;
4379 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4380 BOOL err;
4381 BOOL my_lock_ctx = False;
4382 NTSTATUS status;
4384 START_PROFILE(SMBlockingX);
4386 CHECK_FSP(fsp,conn);
4388 data = smb_buf(inbuf);
4390 if (locktype & (LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_CHANGE_LOCKTYPE)) {
4391 /* we don't support these - and CANCEL_LOCK makes w2k
4392 and XP reboot so I don't really want to be
4393 compatible! (tridge) */
4394 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
4397 /* Check if this is an oplock break on a file
4398 we have granted an oplock on.
4400 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
4401 /* Client can insist on breaking to none. */
4402 BOOL break_to_none = (oplocklevel == 0);
4404 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4405 (unsigned int)oplocklevel, fsp->fnum ));
4408 * Make sure we have granted an exclusive or batch oplock on this file.
4411 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
4412 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4413 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4415 /* if this is a pure oplock break request then don't send a reply */
4416 if (num_locks == 0 && num_ulocks == 0) {
4417 END_PROFILE(SMBlockingX);
4418 return -1;
4419 } else {
4420 END_PROFILE(SMBlockingX);
4421 return ERROR_DOS(ERRDOS,ERRlock);
4425 if (remove_oplock(fsp, break_to_none) == False) {
4426 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4427 fsp->fsp_name ));
4430 /* if this is a pure oplock break request then don't send a reply */
4431 if (num_locks == 0 && num_ulocks == 0) {
4432 /* Sanity check - ensure a pure oplock break is not a
4433 chained request. */
4434 if(CVAL(inbuf,smb_vwv0) != 0xff)
4435 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4436 (unsigned int)CVAL(inbuf,smb_vwv0) ));
4437 END_PROFILE(SMBlockingX);
4438 return -1;
4443 * We do this check *after* we have checked this is not a oplock break
4444 * response message. JRA.
4447 release_level_2_oplocks_on_change(fsp);
4449 /* Data now points at the beginning of the list
4450 of smb_unlkrng structs */
4451 for(i = 0; i < (int)num_ulocks; i++) {
4452 lock_pid = get_lock_pid( data, i, large_file_format);
4453 count = get_lock_count( data, i, large_file_format);
4454 offset = get_lock_offset( data, i, large_file_format, &err);
4457 * There is no error code marked "stupid client bug".... :-).
4459 if(err) {
4460 END_PROFILE(SMBlockingX);
4461 return ERROR_DOS(ERRDOS,ERRnoaccess);
4464 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4465 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4467 status = do_unlock(fsp,conn,lock_pid,count,offset);
4468 if (NT_STATUS_V(status)) {
4469 END_PROFILE(SMBlockingX);
4470 return ERROR_NT(status);
4474 /* Setup the timeout in seconds. */
4476 lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000);
4478 /* Now do any requested locks */
4479 data += ((large_file_format ? 20 : 10)*num_ulocks);
4481 /* Data now points at the beginning of the list
4482 of smb_lkrng structs */
4484 for(i = 0; i < (int)num_locks; i++) {
4485 lock_pid = get_lock_pid( data, i, large_file_format);
4486 count = get_lock_count( data, i, large_file_format);
4487 offset = get_lock_offset( data, i, large_file_format, &err);
4490 * There is no error code marked "stupid client bug".... :-).
4492 if(err) {
4493 END_PROFILE(SMBlockingX);
4494 return ERROR_DOS(ERRDOS,ERRnoaccess);
4497 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
4498 (double)offset, (double)count, (unsigned int)lock_pid,
4499 fsp->fsp_name, (int)lock_timeout ));
4501 status = do_lock_spin(fsp,conn,lock_pid, count,offset,
4502 ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &my_lock_ctx);
4503 if (NT_STATUS_V(status)) {
4505 * Interesting fact found by IFSTEST /t LockOverlappedTest...
4506 * Even if it's our own lock context, we need to wait here as
4507 * there may be an unlock on the way.
4508 * So I removed a "&& !my_lock_ctx" from the following
4509 * if statement. JRA.
4511 if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
4513 * A blocking lock was requested. Package up
4514 * this smb into a queued request and push it
4515 * onto the blocking lock queue.
4517 if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) {
4518 END_PROFILE(SMBlockingX);
4519 return -1;
4522 break;
4526 /* If any of the above locks failed, then we must unlock
4527 all of the previous locks (X/Open spec). */
4528 if (i != num_locks && num_locks != 0) {
4530 * Ensure we don't do a remove on the lock that just failed,
4531 * as under POSIX rules, if we have a lock already there, we
4532 * will delete it (and we shouldn't) .....
4534 for(i--; i >= 0; i--) {
4535 lock_pid = get_lock_pid( data, i, large_file_format);
4536 count = get_lock_count( data, i, large_file_format);
4537 offset = get_lock_offset( data, i, large_file_format, &err);
4540 * There is no error code marked "stupid client bug".... :-).
4542 if(err) {
4543 END_PROFILE(SMBlockingX);
4544 return ERROR_DOS(ERRDOS,ERRnoaccess);
4547 do_unlock(fsp,conn,lock_pid,count,offset);
4549 END_PROFILE(SMBlockingX);
4550 return ERROR_NT(status);
4553 set_message(outbuf,2,0,True);
4555 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4556 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4558 END_PROFILE(SMBlockingX);
4559 return chain_reply(inbuf,outbuf,length,bufsize);
4562 /****************************************************************************
4563 Reply to a SMBreadbmpx (read block multiplex) request.
4564 ****************************************************************************/
4566 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4568 ssize_t nread = -1;
4569 ssize_t total_read;
4570 char *data;
4571 SMB_OFF_T startpos;
4572 int outsize;
4573 size_t maxcount;
4574 int max_per_packet;
4575 size_t tcount;
4576 int pad;
4577 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4578 START_PROFILE(SMBreadBmpx);
4580 /* this function doesn't seem to work - disable by default */
4581 if (!lp_readbmpx()) {
4582 END_PROFILE(SMBreadBmpx);
4583 return ERROR_DOS(ERRSRV,ERRuseSTD);
4586 outsize = set_message(outbuf,8,0,True);
4588 CHECK_FSP(fsp,conn);
4589 CHECK_READ(fsp);
4591 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
4592 maxcount = SVAL(inbuf,smb_vwv3);
4594 data = smb_buf(outbuf);
4595 pad = ((long)data)%4;
4596 if (pad)
4597 pad = 4 - pad;
4598 data += pad;
4600 max_per_packet = bufsize-(outsize+pad);
4601 tcount = maxcount;
4602 total_read = 0;
4604 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
4605 END_PROFILE(SMBreadBmpx);
4606 return ERROR_DOS(ERRDOS,ERRlock);
4609 do {
4610 size_t N = MIN(max_per_packet,tcount-total_read);
4612 nread = read_file(fsp,data,startpos,N);
4614 if (nread <= 0)
4615 nread = 0;
4617 if (nread < (ssize_t)N)
4618 tcount = total_read + nread;
4620 set_message(outbuf,8,nread,False);
4621 SIVAL(outbuf,smb_vwv0,startpos);
4622 SSVAL(outbuf,smb_vwv2,tcount);
4623 SSVAL(outbuf,smb_vwv6,nread);
4624 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4626 if (!send_smb(smbd_server_fd(),outbuf))
4627 exit_server("reply_readbmpx: send_smb failed.");
4629 total_read += nread;
4630 startpos += nread;
4631 } while (total_read < (ssize_t)tcount);
4633 END_PROFILE(SMBreadBmpx);
4634 return(-1);
4637 /****************************************************************************
4638 Reply to a SMBsetattrE.
4639 ****************************************************************************/
4641 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4643 struct utimbuf unix_times;
4644 int outsize = 0;
4645 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4646 START_PROFILE(SMBsetattrE);
4648 outsize = set_message(outbuf,0,0,True);
4650 if(!fsp || (fsp->conn != conn)) {
4651 END_PROFILE(SMBgetattrE);
4652 return ERROR_DOS(ERRDOS,ERRbadfid);
4656 * Convert the DOS times into unix times. Ignore create
4657 * time as UNIX can't set this.
4660 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4661 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4664 * Patch from Ray Frush <frush@engr.colostate.edu>
4665 * Sometimes times are sent as zero - ignore them.
4668 if ((unix_times.actime == 0) && (unix_times.modtime == 0)) {
4669 /* Ignore request */
4670 if( DEBUGLVL( 3 ) ) {
4671 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4672 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4674 END_PROFILE(SMBsetattrE);
4675 return(outsize);
4676 } else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) {
4677 /* set modify time = to access time if modify time was 0 */
4678 unix_times.modtime = unix_times.actime;
4681 /* Set the date on this file */
4682 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4683 END_PROFILE(SMBsetattrE);
4684 return ERROR_DOS(ERRDOS,ERRnoaccess);
4687 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4688 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4690 END_PROFILE(SMBsetattrE);
4691 return(outsize);
4695 /* Back from the dead for OS/2..... JRA. */
4697 /****************************************************************************
4698 Reply to a SMBwritebmpx (write block multiplex primary) request.
4699 ****************************************************************************/
4701 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4703 size_t numtowrite;
4704 ssize_t nwritten = -1;
4705 int outsize = 0;
4706 SMB_OFF_T startpos;
4707 size_t tcount;
4708 BOOL write_through;
4709 int smb_doff;
4710 char *data;
4711 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4712 START_PROFILE(SMBwriteBmpx);
4714 CHECK_FSP(fsp,conn);
4715 CHECK_WRITE(fsp);
4716 CHECK_ERROR(fsp);
4718 tcount = SVAL(inbuf,smb_vwv1);
4719 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
4720 write_through = BITSETW(inbuf+smb_vwv7,0);
4721 numtowrite = SVAL(inbuf,smb_vwv10);
4722 smb_doff = SVAL(inbuf,smb_vwv11);
4724 data = smb_base(inbuf) + smb_doff;
4726 /* If this fails we need to send an SMBwriteC response,
4727 not an SMBwritebmpx - set this up now so we don't forget */
4728 SCVAL(outbuf,smb_com,SMBwritec);
4730 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK,False)) {
4731 END_PROFILE(SMBwriteBmpx);
4732 return(ERROR_DOS(ERRDOS,ERRlock));
4735 nwritten = write_file(fsp,data,startpos,numtowrite);
4737 if(lp_syncalways(SNUM(conn)) || write_through)
4738 sync_file(conn,fsp);
4740 if(nwritten < (ssize_t)numtowrite) {
4741 END_PROFILE(SMBwriteBmpx);
4742 return(UNIXERROR(ERRHRD,ERRdiskfull));
4745 /* If the maximum to be written to this file
4746 is greater than what we just wrote then set
4747 up a secondary struct to be attached to this
4748 fd, we will use this to cache error messages etc. */
4750 if((ssize_t)tcount > nwritten) {
4751 write_bmpx_struct *wbms;
4752 if(fsp->wbmpx_ptr != NULL)
4753 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4754 else
4755 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
4756 if(!wbms) {
4757 DEBUG(0,("Out of memory in reply_readmpx\n"));
4758 END_PROFILE(SMBwriteBmpx);
4759 return(ERROR_DOS(ERRSRV,ERRnoresource));
4761 wbms->wr_mode = write_through;
4762 wbms->wr_discard = False; /* No errors yet */
4763 wbms->wr_total_written = nwritten;
4764 wbms->wr_errclass = 0;
4765 wbms->wr_error = 0;
4766 fsp->wbmpx_ptr = wbms;
4769 /* We are returning successfully, set the message type back to
4770 SMBwritebmpx */
4771 SCVAL(outbuf,smb_com,SMBwriteBmpx);
4773 outsize = set_message(outbuf,1,0,True);
4775 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
4777 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4778 fsp->fnum, (int)numtowrite, (int)nwritten ) );
4780 if (write_through && tcount==nwritten) {
4781 /* We need to send both a primary and a secondary response */
4782 smb_setlen(outbuf,outsize - 4);
4783 if (!send_smb(smbd_server_fd(),outbuf))
4784 exit_server("reply_writebmpx: send_smb failed.");
4786 /* Now the secondary */
4787 outsize = set_message(outbuf,1,0,True);
4788 SCVAL(outbuf,smb_com,SMBwritec);
4789 SSVAL(outbuf,smb_vwv0,nwritten);
4792 END_PROFILE(SMBwriteBmpx);
4793 return(outsize);
4796 /****************************************************************************
4797 Reply to a SMBwritebs (write block multiplex secondary) request.
4798 ****************************************************************************/
4800 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4802 size_t numtowrite;
4803 ssize_t nwritten = -1;
4804 int outsize = 0;
4805 SMB_OFF_T startpos;
4806 size_t tcount;
4807 BOOL write_through;
4808 int smb_doff;
4809 char *data;
4810 write_bmpx_struct *wbms;
4811 BOOL send_response = False;
4812 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4813 START_PROFILE(SMBwriteBs);
4815 CHECK_FSP(fsp,conn);
4816 CHECK_WRITE(fsp);
4818 tcount = SVAL(inbuf,smb_vwv1);
4819 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
4820 numtowrite = SVAL(inbuf,smb_vwv6);
4821 smb_doff = SVAL(inbuf,smb_vwv7);
4823 data = smb_base(inbuf) + smb_doff;
4825 /* We need to send an SMBwriteC response, not an SMBwritebs */
4826 SCVAL(outbuf,smb_com,SMBwritec);
4828 /* This fd should have an auxiliary struct attached,
4829 check that it does */
4830 wbms = fsp->wbmpx_ptr;
4831 if(!wbms) {
4832 END_PROFILE(SMBwriteBs);
4833 return(-1);
4836 /* If write through is set we can return errors, else we must cache them */
4837 write_through = wbms->wr_mode;
4839 /* Check for an earlier error */
4840 if(wbms->wr_discard) {
4841 END_PROFILE(SMBwriteBs);
4842 return -1; /* Just discard the packet */
4845 nwritten = write_file(fsp,data,startpos,numtowrite);
4847 if(lp_syncalways(SNUM(conn)) || write_through)
4848 sync_file(conn,fsp);
4850 if (nwritten < (ssize_t)numtowrite) {
4851 if(write_through) {
4852 /* We are returning an error - we can delete the aux struct */
4853 if (wbms)
4854 free((char *)wbms);
4855 fsp->wbmpx_ptr = NULL;
4856 END_PROFILE(SMBwriteBs);
4857 return(ERROR_DOS(ERRHRD,ERRdiskfull));
4859 END_PROFILE(SMBwriteBs);
4860 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4863 /* Increment the total written, if this matches tcount
4864 we can discard the auxiliary struct (hurrah !) and return a writeC */
4865 wbms->wr_total_written += nwritten;
4866 if(wbms->wr_total_written >= tcount) {
4867 if (write_through) {
4868 outsize = set_message(outbuf,1,0,True);
4869 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
4870 send_response = True;
4873 free((char *)wbms);
4874 fsp->wbmpx_ptr = NULL;
4877 if(send_response) {
4878 END_PROFILE(SMBwriteBs);
4879 return(outsize);
4882 END_PROFILE(SMBwriteBs);
4883 return(-1);
4886 /****************************************************************************
4887 Reply to a SMBgetattrE.
4888 ****************************************************************************/
4890 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4892 SMB_STRUCT_STAT sbuf;
4893 int outsize = 0;
4894 int mode;
4895 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4896 START_PROFILE(SMBgetattrE);
4898 outsize = set_message(outbuf,11,0,True);
4900 if(!fsp || (fsp->conn != conn)) {
4901 END_PROFILE(SMBgetattrE);
4902 return ERROR_DOS(ERRDOS,ERRbadfid);
4905 /* Do an fstat on this file */
4906 if(fsp_stat(fsp, &sbuf)) {
4907 END_PROFILE(SMBgetattrE);
4908 return(UNIXERROR(ERRDOS,ERRnoaccess));
4911 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4914 * Convert the times into dos times. Set create
4915 * date to be last modify date as UNIX doesn't save
4916 * this.
4919 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4920 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4921 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4923 if (mode & aDIR) {
4924 SIVAL(outbuf,smb_vwv6,0);
4925 SIVAL(outbuf,smb_vwv8,0);
4926 } else {
4927 uint32 allocation_size = get_allocation_size(fsp, &sbuf);
4928 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4929 SIVAL(outbuf,smb_vwv8,allocation_size);
4931 SSVAL(outbuf,smb_vwv10, mode);
4933 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
4935 END_PROFILE(SMBgetattrE);
4936 return(outsize);