missed one on BUG 1195; make sure to set the private * to NULL
[Samba/gebeck_regimport.git] / source3 / smbd / reply.c
blobf5c4f25e408e46394bdb64f691df0dd5c9e32d9a
1 /*
2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jeremy Allison 1992-2004.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 This file handles most of the reply_ calls that the server
24 makes to handle specific protocols
27 #include "includes.h"
29 /* look in server.c for some explanation of these variables */
30 extern int Protocol;
31 extern int max_send;
32 extern int max_recv;
33 extern char magic_char;
34 extern BOOL case_sensitive;
35 extern BOOL case_preserve;
36 extern BOOL short_case_preserve;
37 extern int global_oplock_break;
38 unsigned int smb_echo_count = 0;
40 extern BOOL global_encrypted_passwords_negotiated;
42 /****************************************************************************
43 Ensure we check the path in *exactly* the same way as W2K.
44 We're assuming here that '/' is not the second byte in any multibyte char
45 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
46 set.
47 ****************************************************************************/
49 NTSTATUS check_path_syntax(pstring destname, const pstring srcname)
51 char *d = destname;
52 const char *s = srcname;
53 NTSTATUS ret = NT_STATUS_OK;
55 while (*s) {
56 if (IS_DIRECTORY_SEP(*s)) {
58 * Safe to assume is not the second part of a mb char as this is handled below.
60 /* Eat multiple '/' or '\\' */
61 while (IS_DIRECTORY_SEP(*s)) {
62 s++;
64 if ((d != destname) && (*s != '\0')) {
65 /* We only care about non-leading or trailing '/' or '\\' */
66 *d++ = '/';
68 } else if ((s[0] == '.') && (s[1] == '.') && (IS_DIRECTORY_SEP(s[2]) || s[2] == '\0')) {
69 /* Uh oh - "../" or "..\\" or "..\0" ! */
72 * No mb char starts with '.' so we're safe checking the directory separator here.
75 /* If we just added a '/', delete it. */
77 if ((d > destname) && (*(d-1) == '/')) {
78 *(d-1) = '\0';
79 if (d == (destname + 1)) {
80 d--;
81 } else {
82 d -= 2;
85 /* Are we at the start ? Can't go back further if so. */
86 if (d == destname) {
87 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
89 /* Go back one level... */
90 /* We know this is safe as '/' cannot be part of a mb sequence. */
91 /* NOTE - if this assumption is invalid we are not in good shape... */
92 while (d > destname) {
93 if (*d == '/')
94 break;
95 d--;
97 s += 3;
98 } else if ((s[0] == '.') && IS_DIRECTORY_SEP(s[1])) {
101 * No mb char starts with '.' so we're safe checking the directory separator here.
104 /* "./" or ".\\" fails with a different error depending on where it is... */
106 if (s == srcname) {
107 ret = NT_STATUS_OBJECT_NAME_INVALID;
108 } else {
109 if (s[2] == '\0') {
110 return NT_STATUS_INVALID_PARAMETER;
112 ret = NT_STATUS_OBJECT_PATH_NOT_FOUND;
114 s++;
115 } else {
116 if (!(*s & 0x80)) {
117 *d++ = *s++;
118 } else {
119 switch(next_mb_char_size(s)) {
120 case 4:
121 *d++ = *s++;
122 case 3:
123 *d++ = *s++;
124 case 2:
125 *d++ = *s++;
126 case 1:
127 *d++ = *s++;
128 break;
129 default:
130 DEBUG(0,("check_path_syntax: character length assumptions invalid !\n"));
131 return NT_STATUS_INVALID_PARAMETER;
136 *d = '\0';
137 return ret;
140 /****************************************************************************
141 Pull a string and check the path - provide for error return.
142 ****************************************************************************/
144 size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags, NTSTATUS *err)
146 pstring tmppath;
147 char *tmppath_ptr = tmppath;
148 size_t ret;
149 #ifdef DEVELOPER
150 SMB_ASSERT(dest_len == sizeof(pstring));
151 #endif
153 if (src_len == 0) {
154 ret = srvstr_pull_buf( inbuf, tmppath_ptr, src, dest_len, flags);
155 } else {
156 ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags);
158 *err = check_path_syntax(dest, tmppath);
159 return ret;
162 /****************************************************************************
163 Reply to a special message.
164 ****************************************************************************/
166 int reply_special(char *inbuf,char *outbuf)
168 int outsize = 4;
169 int msg_type = CVAL(inbuf,0);
170 int msg_flags = CVAL(inbuf,1);
171 fstring name1,name2;
172 char name_type = 0;
174 static BOOL already_got_session = False;
176 *name1 = *name2 = 0;
178 memset(outbuf,'\0',smb_size);
180 smb_setlen(outbuf,0);
182 switch (msg_type) {
183 case 0x81: /* session request */
185 if (already_got_session) {
186 exit_server("multiple session request not permitted");
189 SCVAL(outbuf,0,0x82);
190 SCVAL(outbuf,3,0);
191 if (name_len(inbuf+4) > 50 ||
192 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
193 DEBUG(0,("Invalid name length in session request\n"));
194 return(0);
196 name_extract(inbuf,4,name1);
197 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
198 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
199 name1,name2));
201 set_local_machine_name(name1, True);
202 set_remote_machine_name(name2, True);
204 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
205 get_local_machine_name(), get_remote_machine_name(),
206 name_type));
208 if (name_type == 'R') {
209 /* We are being asked for a pathworks session ---
210 no thanks! */
211 SCVAL(outbuf, 0,0x83);
212 break;
215 /* only add the client's machine name to the list
216 of possibly valid usernames if we are operating
217 in share mode security */
218 if (lp_security() == SEC_SHARE) {
219 add_session_user(get_remote_machine_name());
222 reload_services(True);
223 reopen_logs();
225 claim_connection(NULL,"",0,True,FLAG_MSG_GENERAL|FLAG_MSG_SMBD);
227 already_got_session = True;
228 break;
230 case 0x89: /* session keepalive request
231 (some old clients produce this?) */
232 SCVAL(outbuf,0,SMBkeepalive);
233 SCVAL(outbuf,3,0);
234 break;
236 case 0x82: /* positive session response */
237 case 0x83: /* negative session response */
238 case 0x84: /* retarget session response */
239 DEBUG(0,("Unexpected session response\n"));
240 break;
242 case SMBkeepalive: /* session keepalive */
243 default:
244 return(0);
247 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
248 msg_type, msg_flags));
250 return(outsize);
253 /****************************************************************************
254 Reply to a tcon.
255 ****************************************************************************/
257 int reply_tcon(connection_struct *conn,
258 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
260 const char *service;
261 pstring service_buf;
262 pstring password;
263 pstring dev;
264 int outsize = 0;
265 uint16 vuid = SVAL(inbuf,smb_uid);
266 int pwlen=0;
267 NTSTATUS nt_status;
268 char *p;
269 DATA_BLOB password_blob;
271 START_PROFILE(SMBtcon);
273 *service_buf = *password = *dev = 0;
275 p = smb_buf(inbuf)+1;
276 p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service_buf), STR_TERMINATE) + 1;
277 pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1;
278 p += pwlen;
279 p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1;
281 p = strrchr_m(service_buf,'\\');
282 if (p) {
283 service = p+1;
284 } else {
285 service = service_buf;
288 password_blob = data_blob(password, pwlen+1);
290 conn = make_connection(service,password_blob,dev,vuid,&nt_status);
292 data_blob_clear_free(&password_blob);
294 if (!conn) {
295 END_PROFILE(SMBtcon);
296 return ERROR_NT(nt_status);
299 outsize = set_message(outbuf,2,0,True);
300 SSVAL(outbuf,smb_vwv0,max_recv);
301 SSVAL(outbuf,smb_vwv1,conn->cnum);
302 SSVAL(outbuf,smb_tid,conn->cnum);
304 DEBUG(3,("tcon service=%s cnum=%d\n",
305 service, conn->cnum));
307 END_PROFILE(SMBtcon);
308 return(outsize);
311 /****************************************************************************
312 Reply to a tcon and X.
313 ****************************************************************************/
315 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
317 fstring service;
318 DATA_BLOB password;
320 /* what the cleint thinks the device is */
321 fstring client_devicetype;
322 /* what the server tells the client the share represents */
323 const char *server_devicetype;
324 NTSTATUS nt_status;
325 uint16 vuid = SVAL(inbuf,smb_uid);
326 int passlen = SVAL(inbuf,smb_vwv3);
327 pstring path;
328 char *p, *q;
329 extern BOOL global_encrypted_passwords_negotiated;
331 START_PROFILE(SMBtconX);
333 *service = *client_devicetype = 0;
335 /* we might have to close an old one */
336 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
337 close_cnum(conn,vuid);
340 if (passlen > MAX_PASS_LEN) {
341 return ERROR_DOS(ERRDOS,ERRbuftoosmall);
344 if (global_encrypted_passwords_negotiated) {
345 password = data_blob(smb_buf(inbuf),passlen);
346 } else {
347 password = data_blob(smb_buf(inbuf),passlen+1);
348 /* Ensure correct termination */
349 password.data[passlen]=0;
352 p = smb_buf(inbuf) + passlen;
353 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
356 * the service name can be either: \\server\share
357 * or share directly like on the DELL PowerVault 705
359 if (*path=='\\') {
360 q = strchr_m(path+2,'\\');
361 if (!q) {
362 END_PROFILE(SMBtconX);
363 return(ERROR_DOS(ERRDOS,ERRnosuchshare));
365 fstrcpy(service,q+1);
367 else
368 fstrcpy(service,path);
370 p += srvstr_pull(inbuf, client_devicetype, p, sizeof(client_devicetype), 6, STR_ASCII);
372 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
374 conn = make_connection(service,password,client_devicetype,vuid,&nt_status);
376 data_blob_clear_free(&password);
378 if (!conn) {
379 END_PROFILE(SMBtconX);
380 return ERROR_NT(nt_status);
383 if ( IS_IPC(conn) )
384 server_devicetype = "IPC";
385 else if ( IS_PRINT(conn) )
386 server_devicetype = "LPT1:";
387 else
388 server_devicetype = "A:";
390 if (Protocol < PROTOCOL_NT1) {
391 set_message(outbuf,2,0,True);
392 p = smb_buf(outbuf);
393 p += srvstr_push(outbuf, p, server_devicetype, -1,
394 STR_TERMINATE|STR_ASCII);
395 set_message_end(outbuf,p);
396 } else {
397 /* NT sets the fstype of IPC$ to the null string */
398 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
400 set_message(outbuf,3,0,True);
402 p = smb_buf(outbuf);
403 p += srvstr_push(outbuf, p, server_devicetype, -1,
404 STR_TERMINATE|STR_ASCII);
405 p += srvstr_push(outbuf, p, fstype, -1,
406 STR_TERMINATE);
408 set_message_end(outbuf,p);
410 /* what does setting this bit do? It is set by NT4 and
411 may affect the ability to autorun mounted cdroms */
412 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
413 (lp_csc_policy(SNUM(conn)) << 2));
415 init_dfsroot(conn, inbuf, outbuf);
419 DEBUG(3,("tconX service=%s \n",
420 service));
422 /* set the incoming and outgoing tid to the just created one */
423 SSVAL(inbuf,smb_tid,conn->cnum);
424 SSVAL(outbuf,smb_tid,conn->cnum);
426 END_PROFILE(SMBtconX);
427 return chain_reply(inbuf,outbuf,length,bufsize);
430 /****************************************************************************
431 Reply to an unknown type.
432 ****************************************************************************/
434 int reply_unknown(char *inbuf,char *outbuf)
436 int type;
437 type = CVAL(inbuf,smb_com);
439 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
440 smb_fn_name(type), type, type));
442 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
445 /****************************************************************************
446 Reply to an ioctl.
447 ****************************************************************************/
449 int reply_ioctl(connection_struct *conn,
450 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
452 uint16 device = SVAL(inbuf,smb_vwv1);
453 uint16 function = SVAL(inbuf,smb_vwv2);
454 uint32 ioctl_code = (device << 16) + function;
455 int replysize, outsize;
456 char *p;
457 START_PROFILE(SMBioctl);
459 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
461 switch (ioctl_code) {
462 case IOCTL_QUERY_JOB_INFO:
463 replysize = 32;
464 break;
465 default:
466 END_PROFILE(SMBioctl);
467 return(ERROR_DOS(ERRSRV,ERRnosupport));
470 outsize = set_message(outbuf,8,replysize+1,True);
471 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
472 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
473 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
474 p = smb_buf(outbuf) + 1; /* Allow for alignment */
476 switch (ioctl_code) {
477 case IOCTL_QUERY_JOB_INFO:
479 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
480 if (!fsp) {
481 END_PROFILE(SMBioctl);
482 return(UNIXERROR(ERRDOS,ERRbadfid));
484 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
485 srvstr_push(outbuf, p+2, global_myname(), 15, STR_TERMINATE|STR_ASCII);
486 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
487 break;
491 END_PROFILE(SMBioctl);
492 return outsize;
495 /****************************************************************************
496 Reply to a chkpth.
497 ****************************************************************************/
499 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
501 int outsize = 0;
502 int mode;
503 pstring name;
504 BOOL ok = False;
505 BOOL bad_path = False;
506 SMB_STRUCT_STAT sbuf;
507 NTSTATUS status;
509 START_PROFILE(SMBchkpth);
511 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
512 if (!NT_STATUS_IS_OK(status)) {
513 END_PROFILE(SMBchkpth);
514 return ERROR_NT(status);
517 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
519 unix_convert(name,conn,0,&bad_path,&sbuf);
521 mode = SVAL(inbuf,smb_vwv0);
523 if (check_name(name,conn)) {
524 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,name,&sbuf) == 0)
525 if (!(ok = S_ISDIR(sbuf.st_mode))) {
526 END_PROFILE(SMBchkpth);
527 return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath);
531 if (!ok) {
532 /* We special case this - as when a Windows machine
533 is parsing a path is steps through the components
534 one at a time - if a component fails it expects
535 ERRbadpath, not ERRbadfile.
537 if(errno == ENOENT) {
539 * Windows returns different error codes if
540 * the parent directory is valid but not the
541 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
542 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
543 * if the path is invalid.
545 if (bad_path) {
546 END_PROFILE(SMBchkpth);
547 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
548 } else {
549 END_PROFILE(SMBchkpth);
550 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
552 } else if (errno == ENOTDIR) {
553 END_PROFILE(SMBchkpth);
554 return ERROR_NT(NT_STATUS_NOT_A_DIRECTORY);
557 END_PROFILE(SMBchkpth);
558 return(UNIXERROR(ERRDOS,ERRbadpath));
561 outsize = set_message(outbuf,0,0,True);
563 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
565 END_PROFILE(SMBchkpth);
566 return(outsize);
569 /****************************************************************************
570 Reply to a getatr.
571 ****************************************************************************/
573 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
575 pstring fname;
576 int outsize = 0;
577 SMB_STRUCT_STAT sbuf;
578 BOOL ok = False;
579 int mode=0;
580 SMB_OFF_T size=0;
581 time_t mtime=0;
582 BOOL bad_path = False;
583 char *p;
584 NTSTATUS status;
586 START_PROFILE(SMBgetatr);
588 p = smb_buf(inbuf) + 1;
589 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
590 if (!NT_STATUS_IS_OK(status)) {
591 END_PROFILE(SMBgetatr);
592 return ERROR_NT(status);
595 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
597 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
598 under WfWg - weird! */
599 if (! (*fname)) {
600 mode = aHIDDEN | aDIR;
601 if (!CAN_WRITE(conn))
602 mode |= aRONLY;
603 size = 0;
604 mtime = 0;
605 ok = True;
606 } else {
607 unix_convert(fname,conn,0,&bad_path,&sbuf);
608 if (check_name(fname,conn)) {
609 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,fname,&sbuf) == 0) {
610 mode = dos_mode(conn,fname,&sbuf);
611 size = sbuf.st_size;
612 mtime = sbuf.st_mtime;
613 if (mode & aDIR)
614 size = 0;
615 ok = True;
616 } else {
617 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
622 if (!ok) {
623 END_PROFILE(SMBgetatr);
624 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadfile);
627 outsize = set_message(outbuf,10,0,True);
629 SSVAL(outbuf,smb_vwv0,mode);
630 if(lp_dos_filetime_resolution(SNUM(conn)) )
631 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
632 else
633 put_dos_date3(outbuf,smb_vwv1,mtime);
634 SIVAL(outbuf,smb_vwv3,(uint32)size);
636 if (Protocol >= PROTOCOL_NT1)
637 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
639 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
641 END_PROFILE(SMBgetatr);
642 return(outsize);
645 /****************************************************************************
646 Reply to a setatr.
647 ****************************************************************************/
649 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
651 pstring fname;
652 int outsize = 0;
653 BOOL ok=False;
654 int mode;
655 time_t mtime;
656 SMB_STRUCT_STAT sbuf;
657 BOOL bad_path = False;
658 char *p;
659 NTSTATUS status;
661 START_PROFILE(SMBsetatr);
663 p = smb_buf(inbuf) + 1;
664 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
665 if (!NT_STATUS_IS_OK(status)) {
666 END_PROFILE(SMBsetatr);
667 return ERROR_NT(status);
670 unix_convert(fname,conn,0,&bad_path,&sbuf);
672 mode = SVAL(inbuf,smb_vwv0);
673 mtime = make_unix_date3(inbuf+smb_vwv1);
675 if (mode != FILE_ATTRIBUTE_NORMAL) {
676 if (VALID_STAT_OF_DIR(sbuf))
677 mode |= aDIR;
678 else
679 mode &= ~aDIR;
681 if (check_name(fname,conn))
682 ok = (file_chmod(conn,fname,mode,NULL) == 0);
683 } else {
684 ok = True;
687 if (ok)
688 ok = set_filetime(conn,fname,mtime);
690 if (!ok) {
691 END_PROFILE(SMBsetatr);
692 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
695 outsize = set_message(outbuf,0,0,True);
697 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
699 END_PROFILE(SMBsetatr);
700 return(outsize);
703 /****************************************************************************
704 Reply to a dskattr.
705 ****************************************************************************/
707 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
709 int outsize = 0;
710 SMB_BIG_UINT dfree,dsize,bsize;
711 START_PROFILE(SMBdskattr);
713 SMB_VFS_DISK_FREE(conn,".",True,&bsize,&dfree,&dsize);
715 outsize = set_message(outbuf,5,0,True);
717 if (Protocol <= PROTOCOL_LANMAN2) {
718 double total_space, free_space;
719 /* we need to scale this to a number that DOS6 can handle. We
720 use floating point so we can handle large drives on systems
721 that don't have 64 bit integers
723 we end up displaying a maximum of 2G to DOS systems
725 total_space = dsize * (double)bsize;
726 free_space = dfree * (double)bsize;
728 dsize = (total_space+63*512) / (64*512);
729 dfree = (free_space+63*512) / (64*512);
731 if (dsize > 0xFFFF) dsize = 0xFFFF;
732 if (dfree > 0xFFFF) dfree = 0xFFFF;
734 SSVAL(outbuf,smb_vwv0,dsize);
735 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
736 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
737 SSVAL(outbuf,smb_vwv3,dfree);
738 } else {
739 SSVAL(outbuf,smb_vwv0,dsize);
740 SSVAL(outbuf,smb_vwv1,bsize/512);
741 SSVAL(outbuf,smb_vwv2,512);
742 SSVAL(outbuf,smb_vwv3,dfree);
745 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
747 END_PROFILE(SMBdskattr);
748 return(outsize);
751 /****************************************************************************
752 Reply to a search.
753 Can be called from SMBsearch, SMBffirst or SMBfunique.
754 ****************************************************************************/
756 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
758 pstring mask;
759 pstring directory;
760 pstring fname;
761 SMB_OFF_T size;
762 int mode;
763 time_t date;
764 int dirtype;
765 int outsize = 0;
766 unsigned int numentries = 0;
767 unsigned int maxentries = 0;
768 BOOL finished = False;
769 char *p;
770 BOOL ok = False;
771 int status_len;
772 pstring path;
773 char status[21];
774 int dptr_num= -1;
775 BOOL check_descend = False;
776 BOOL expect_close = False;
777 BOOL can_open = True;
778 BOOL bad_path = False;
779 NTSTATUS nt_status;
780 START_PROFILE(SMBsearch);
782 *mask = *directory = *fname = 0;
784 /* If we were called as SMBffirst then we must expect close. */
785 if(CVAL(inbuf,smb_com) == SMBffirst)
786 expect_close = True;
788 outsize = set_message(outbuf,1,3,True);
789 maxentries = SVAL(inbuf,smb_vwv0);
790 dirtype = SVAL(inbuf,smb_vwv1);
791 p = smb_buf(inbuf) + 1;
792 p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &nt_status);
793 if (!NT_STATUS_IS_OK(nt_status)) {
794 END_PROFILE(SMBsearch);
795 return ERROR_NT(nt_status);
797 p++;
798 status_len = SVAL(p, 0);
799 p += 2;
801 /* dirtype &= ~aDIR; */
803 if (status_len == 0) {
804 SMB_STRUCT_STAT sbuf;
805 pstring dir2;
807 pstrcpy(directory,path);
808 pstrcpy(dir2,path);
809 unix_convert(directory,conn,0,&bad_path,&sbuf);
810 unix_format(dir2);
812 if (!check_name(directory,conn))
813 can_open = False;
815 p = strrchr_m(dir2,'/');
816 if (p == NULL) {
817 pstrcpy(mask,dir2);
818 *dir2 = 0;
819 } else {
820 *p = 0;
821 pstrcpy(mask,p+1);
824 p = strrchr_m(directory,'/');
825 if (!p)
826 *directory = 0;
827 else
828 *p = 0;
830 if (strlen(directory) == 0)
831 pstrcpy(directory,".");
832 memset((char *)status,'\0',21);
833 SCVAL(status,0,(dirtype & 0x1F));
834 } else {
835 int status_dirtype;
837 memcpy(status,p,21);
838 status_dirtype = CVAL(status,0) & 0x1F;
839 if (status_dirtype != (dirtype & 0x1F))
840 dirtype = status_dirtype;
842 conn->dirptr = dptr_fetch(status+12,&dptr_num);
843 if (!conn->dirptr)
844 goto SearchEmpty;
845 string_set(&conn->dirpath,dptr_path(dptr_num));
846 pstrcpy(mask, dptr_wcard(dptr_num));
849 if (can_open) {
850 p = smb_buf(outbuf) + 3;
851 ok = True;
853 if (status_len == 0) {
854 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
855 if (dptr_num < 0) {
856 if(dptr_num == -2) {
857 END_PROFILE(SMBsearch);
858 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnofids);
860 END_PROFILE(SMBsearch);
861 return ERROR_DOS(ERRDOS,ERRnofids);
863 dptr_set_wcard(dptr_num, strdup(mask));
864 dptr_set_attr(dptr_num, dirtype);
865 } else {
866 dirtype = dptr_attr(dptr_num);
869 DEBUG(4,("dptr_num is %d\n",dptr_num));
871 if (ok) {
872 if ((dirtype&0x1F) == aVOLID) {
873 memcpy(p,status,21);
874 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
875 dptr_fill(p+12,dptr_num);
876 if (dptr_zero(p+12) && (status_len==0))
877 numentries = 1;
878 else
879 numentries = 0;
880 p += DIR_STRUCT_SIZE;
881 } else {
882 unsigned int i;
883 maxentries = MIN(maxentries, ((BUFFER_SIZE - (p - outbuf))/DIR_STRUCT_SIZE));
885 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
886 conn->dirpath,lp_dontdescend(SNUM(conn))));
887 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
888 check_descend = True;
890 for (i=numentries;(i<maxentries) && !finished;i++) {
891 finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
892 if (!finished) {
893 memcpy(p,status,21);
894 make_dir_struct(p,mask,fname,size,mode,date);
895 dptr_fill(p+12,dptr_num);
896 numentries++;
898 p += DIR_STRUCT_SIZE;
901 } /* if (ok ) */
905 SearchEmpty:
907 /* If we were called as SMBffirst with smb_search_id == NULL
908 and no entries were found then return error and close dirptr
909 (X/Open spec) */
911 if(ok && expect_close && numentries == 0 && status_len == 0) {
912 if (Protocol < PROTOCOL_NT1) {
913 SCVAL(outbuf,smb_rcls,ERRDOS);
914 SSVAL(outbuf,smb_err,ERRnofiles);
916 /* Also close the dptr - we know it's gone */
917 dptr_close(&dptr_num);
918 } else if (numentries == 0 || !ok) {
919 if (Protocol < PROTOCOL_NT1) {
920 SCVAL(outbuf,smb_rcls,ERRDOS);
921 SSVAL(outbuf,smb_err,ERRnofiles);
923 dptr_close(&dptr_num);
926 /* If we were called as SMBfunique, then we can close the dirptr now ! */
927 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
928 dptr_close(&dptr_num);
930 SSVAL(outbuf,smb_vwv0,numentries);
931 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
932 SCVAL(smb_buf(outbuf),0,5);
933 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
935 if (Protocol >= PROTOCOL_NT1)
936 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
938 outsize += DIR_STRUCT_SIZE*numentries;
939 smb_setlen(outbuf,outsize - 4);
941 if ((! *directory) && dptr_path(dptr_num))
942 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
944 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
945 smb_fn_name(CVAL(inbuf,smb_com)),
946 mask, directory, dirtype, numentries, maxentries ) );
948 END_PROFILE(SMBsearch);
949 return(outsize);
952 /****************************************************************************
953 Reply to a fclose (stop directory search).
954 ****************************************************************************/
956 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
958 int outsize = 0;
959 int status_len;
960 pstring path;
961 char status[21];
962 int dptr_num= -2;
963 char *p;
964 NTSTATUS err;
966 START_PROFILE(SMBfclose);
968 outsize = set_message(outbuf,1,0,True);
969 p = smb_buf(inbuf) + 1;
970 p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err);
971 if (!NT_STATUS_IS_OK(err)) {
972 END_PROFILE(SMBfclose);
973 return ERROR_NT(err);
975 p++;
976 status_len = SVAL(p,0);
977 p += 2;
979 if (status_len == 0) {
980 END_PROFILE(SMBfclose);
981 return ERROR_DOS(ERRSRV,ERRsrverror);
984 memcpy(status,p,21);
986 if(dptr_fetch(status+12,&dptr_num)) {
987 /* Close the dptr - we know it's gone */
988 dptr_close(&dptr_num);
991 SSVAL(outbuf,smb_vwv0,0);
993 DEBUG(3,("search close\n"));
995 END_PROFILE(SMBfclose);
996 return(outsize);
999 /****************************************************************************
1000 Reply to an open.
1001 ****************************************************************************/
1003 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1005 pstring fname;
1006 int outsize = 0;
1007 int fmode=0;
1008 int share_mode;
1009 SMB_OFF_T size = 0;
1010 time_t mtime=0;
1011 mode_t unixmode;
1012 int rmode=0;
1013 SMB_STRUCT_STAT sbuf;
1014 BOOL bad_path = False;
1015 files_struct *fsp;
1016 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1017 NTSTATUS status;
1018 START_PROFILE(SMBopen);
1020 share_mode = SVAL(inbuf,smb_vwv0);
1022 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
1023 if (!NT_STATUS_IS_OK(status)) {
1024 END_PROFILE(SMBopen);
1025 return ERROR_NT(status);
1028 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1030 unix_convert(fname,conn,0,&bad_path,&sbuf);
1032 unixmode = unix_mode(conn,aARCH,fname);
1034 fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1035 unixmode, oplock_request,&rmode,NULL);
1037 if (!fsp) {
1038 END_PROFILE(SMBopen);
1039 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1042 size = sbuf.st_size;
1043 fmode = dos_mode(conn,fname,&sbuf);
1044 mtime = sbuf.st_mtime;
1046 if (fmode & aDIR) {
1047 DEBUG(3,("attempt to open a directory %s\n",fname));
1048 close_file(fsp,False);
1049 END_PROFILE(SMBopen);
1050 return ERROR_DOS(ERRDOS,ERRnoaccess);
1053 outsize = set_message(outbuf,7,0,True);
1054 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1055 SSVAL(outbuf,smb_vwv1,fmode);
1056 if(lp_dos_filetime_resolution(SNUM(conn)) )
1057 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1058 else
1059 put_dos_date3(outbuf,smb_vwv2,mtime);
1060 SIVAL(outbuf,smb_vwv4,(uint32)size);
1061 SSVAL(outbuf,smb_vwv6,rmode);
1063 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1064 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1066 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1067 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1068 END_PROFILE(SMBopen);
1069 return(outsize);
1072 /****************************************************************************
1073 Reply to an open and X.
1074 ****************************************************************************/
1076 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1078 pstring fname;
1079 int smb_mode = SVAL(inbuf,smb_vwv3);
1080 int smb_attr = SVAL(inbuf,smb_vwv5);
1081 /* Breakout the oplock request bits so we can set the
1082 reply bits separately. */
1083 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1084 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1085 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1086 #if 0
1087 int open_flags = SVAL(inbuf,smb_vwv2);
1088 int smb_sattr = SVAL(inbuf,smb_vwv4);
1089 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1090 #endif
1091 int smb_ofun = SVAL(inbuf,smb_vwv8);
1092 mode_t unixmode;
1093 SMB_OFF_T size=0;
1094 int fmode=0,mtime=0,rmode=0;
1095 SMB_STRUCT_STAT sbuf;
1096 int smb_action = 0;
1097 BOOL bad_path = False;
1098 files_struct *fsp;
1099 NTSTATUS status;
1100 START_PROFILE(SMBopenX);
1102 /* If it's an IPC, pass off the pipe handler. */
1103 if (IS_IPC(conn)) {
1104 if (lp_nt_pipe_support()) {
1105 END_PROFILE(SMBopenX);
1106 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1107 } else {
1108 END_PROFILE(SMBopenX);
1109 return ERROR_DOS(ERRSRV,ERRaccess);
1113 /* XXXX we need to handle passed times, sattr and flags */
1114 srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status);
1115 if (!NT_STATUS_IS_OK(status)) {
1116 END_PROFILE(SMBopenX);
1117 return ERROR_NT(status);
1120 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1122 unix_convert(fname,conn,0,&bad_path,&sbuf);
1124 unixmode = unix_mode(conn,smb_attr | aARCH, fname);
1126 fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,unixmode,
1127 oplock_request, &rmode,&smb_action);
1129 if (!fsp) {
1130 END_PROFILE(SMBopenX);
1131 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1134 size = sbuf.st_size;
1135 fmode = dos_mode(conn,fname,&sbuf);
1136 mtime = sbuf.st_mtime;
1137 if (fmode & aDIR) {
1138 close_file(fsp,False);
1139 END_PROFILE(SMBopenX);
1140 return ERROR_DOS(ERRDOS,ERRnoaccess);
1143 /* If the caller set the extended oplock request bit
1144 and we granted one (by whatever means) - set the
1145 correct bit for extended oplock reply.
1148 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn)))
1149 smb_action |= EXTENDED_OPLOCK_GRANTED;
1151 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1152 smb_action |= EXTENDED_OPLOCK_GRANTED;
1154 /* If the caller set the core oplock request bit
1155 and we granted one (by whatever means) - set the
1156 correct bit for core oplock reply.
1159 if (core_oplock_request && lp_fake_oplocks(SNUM(conn)))
1160 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1162 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1163 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1165 set_message(outbuf,15,0,True);
1166 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1167 SSVAL(outbuf,smb_vwv3,fmode);
1168 if(lp_dos_filetime_resolution(SNUM(conn)) )
1169 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1170 else
1171 put_dos_date3(outbuf,smb_vwv4,mtime);
1172 SIVAL(outbuf,smb_vwv6,(uint32)size);
1173 SSVAL(outbuf,smb_vwv8,rmode);
1174 SSVAL(outbuf,smb_vwv11,smb_action);
1176 END_PROFILE(SMBopenX);
1177 return chain_reply(inbuf,outbuf,length,bufsize);
1180 /****************************************************************************
1181 Reply to a SMBulogoffX.
1182 ****************************************************************************/
1184 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1186 uint16 vuid = SVAL(inbuf,smb_uid);
1187 user_struct *vuser = get_valid_user_struct(vuid);
1188 START_PROFILE(SMBulogoffX);
1190 if(vuser == 0)
1191 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1193 /* in user level security we are supposed to close any files
1194 open by this user */
1195 if ((vuser != 0) && (lp_security() != SEC_SHARE))
1196 file_close_user(vuid);
1198 invalidate_vuid(vuid);
1200 set_message(outbuf,2,0,True);
1202 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1204 END_PROFILE(SMBulogoffX);
1205 return chain_reply(inbuf,outbuf,length,bufsize);
1208 /****************************************************************************
1209 Reply to a mknew or a create.
1210 ****************************************************************************/
1212 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1214 pstring fname;
1215 int com;
1216 int outsize = 0;
1217 int createmode;
1218 mode_t unixmode;
1219 int ofun = 0;
1220 BOOL bad_path = False;
1221 files_struct *fsp;
1222 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1223 SMB_STRUCT_STAT sbuf;
1224 NTSTATUS status;
1225 START_PROFILE(SMBcreate);
1227 com = SVAL(inbuf,smb_com);
1229 createmode = SVAL(inbuf,smb_vwv0);
1230 srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status);
1231 if (!NT_STATUS_IS_OK(status)) {
1232 END_PROFILE(SMBcreate);
1233 return ERROR_NT(status);
1236 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1238 unix_convert(fname,conn,0,&bad_path,&sbuf);
1240 if (createmode & aVOLID)
1241 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1243 unixmode = unix_mode(conn,createmode,fname);
1245 if(com == SMBmknew) {
1246 /* We should fail if file exists. */
1247 ofun = FILE_CREATE_IF_NOT_EXIST;
1248 } else {
1249 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1250 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1253 /* Open file in dos compatibility share mode. */
1254 fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1255 ofun, unixmode, oplock_request, NULL, NULL);
1257 if (!fsp) {
1258 END_PROFILE(SMBcreate);
1259 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1262 outsize = set_message(outbuf,1,0,True);
1263 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1265 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1266 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1268 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1269 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1271 DEBUG( 2, ( "new file %s\n", fname ) );
1272 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n", fname, fsp->fd, createmode, (int)unixmode ) );
1274 END_PROFILE(SMBcreate);
1275 return(outsize);
1278 /****************************************************************************
1279 Reply to a create temporary file.
1280 ****************************************************************************/
1282 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1284 pstring fname;
1285 int outsize = 0;
1286 int createmode;
1287 mode_t unixmode;
1288 BOOL bad_path = False;
1289 files_struct *fsp;
1290 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1291 int tmpfd;
1292 SMB_STRUCT_STAT sbuf;
1293 char *p, *s;
1294 NTSTATUS status;
1296 START_PROFILE(SMBctemp);
1298 createmode = SVAL(inbuf,smb_vwv0);
1299 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
1300 if (!NT_STATUS_IS_OK(status)) {
1301 END_PROFILE(SMBctemp);
1302 return ERROR_NT(status);
1304 pstrcat(fname,"\\TMXXXXXX");
1306 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1308 unix_convert(fname,conn,0,&bad_path,&sbuf);
1310 unixmode = unix_mode(conn,createmode,fname);
1312 tmpfd = smb_mkstemp(fname);
1313 if (tmpfd == -1) {
1314 END_PROFILE(SMBctemp);
1315 return(UNIXERROR(ERRDOS,ERRnoaccess));
1318 SMB_VFS_STAT(conn,fname,&sbuf);
1320 /* Open file in dos compatibility share mode. */
1321 /* We should fail if file does not exist. */
1322 fsp = open_file_shared(conn,fname,&sbuf,
1323 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1324 FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
1325 unixmode, oplock_request, NULL, NULL);
1327 /* close fd from smb_mkstemp() */
1328 close(tmpfd);
1330 if (!fsp) {
1331 END_PROFILE(SMBctemp);
1332 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1335 outsize = set_message(outbuf,1,0,True);
1336 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1338 /* the returned filename is relative to the directory */
1339 s = strrchr_m(fname, '/');
1340 if (!s)
1341 s = fname;
1342 else
1343 s++;
1345 p = smb_buf(outbuf);
1346 SSVALS(p, 0, -1); /* what is this? not in spec */
1347 SSVAL(p, 2, strlen(s));
1348 p += 4;
1349 p += srvstr_push(outbuf, p, s, -1, STR_ASCII);
1350 outsize = set_message_end(outbuf, p);
1352 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1353 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1355 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1356 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1358 DEBUG( 2, ( "created temp file %s\n", fname ) );
1359 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1360 fname, fsp->fd, createmode, (int)unixmode ) );
1362 END_PROFILE(SMBctemp);
1363 return(outsize);
1366 /*******************************************************************
1367 Check if a user is allowed to rename a file.
1368 ********************************************************************/
1370 static NTSTATUS can_rename(char *fname,connection_struct *conn, SMB_STRUCT_STAT *pst)
1372 int smb_action;
1373 int access_mode;
1374 files_struct *fsp;
1376 if (!CAN_WRITE(conn))
1377 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1379 if (S_ISDIR(pst->st_mode))
1380 return NT_STATUS_OK;
1382 /* We need a better way to return NT status codes from open... */
1383 unix_ERR_class = 0;
1384 unix_ERR_code = 0;
1386 fsp = open_file_shared1(conn, fname, pst, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1387 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
1389 if (!fsp) {
1390 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1391 if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1392 ret = NT_STATUS_SHARING_VIOLATION;
1393 unix_ERR_class = 0;
1394 unix_ERR_code = 0;
1395 unix_ERR_ntstatus = NT_STATUS_OK;
1396 return ret;
1398 close_file(fsp,False);
1399 return NT_STATUS_OK;
1402 /*******************************************************************
1403 Check if a user is allowed to delete a file.
1404 ********************************************************************/
1406 static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype, BOOL bad_path)
1408 SMB_STRUCT_STAT sbuf;
1409 int fmode;
1410 int smb_action;
1411 int access_mode;
1412 files_struct *fsp;
1414 DEBUG(10,("can_delete: %s, dirtype = %d\n",
1415 fname, dirtype ));
1417 if (!CAN_WRITE(conn))
1418 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1420 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
1421 if(errno == ENOENT) {
1422 if (bad_path)
1423 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1424 else
1425 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1427 return map_nt_error_from_unix(errno);
1430 fmode = dos_mode(conn,fname,&sbuf);
1432 /* Can't delete a directory. */
1433 if (fmode & aDIR)
1434 return NT_STATUS_FILE_IS_A_DIRECTORY;
1435 #if 0 /* JRATEST */
1436 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
1437 return NT_STATUS_OBJECT_NAME_INVALID;
1438 #endif /* JRATEST */
1440 if (!lp_delete_readonly(SNUM(conn))) {
1441 if (fmode & aRONLY)
1442 return NT_STATUS_CANNOT_DELETE;
1444 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1445 return NT_STATUS_NO_SUCH_FILE;
1447 /* We need a better way to return NT status codes from open... */
1448 unix_ERR_class = 0;
1449 unix_ERR_code = 0;
1451 fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1452 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
1454 if (!fsp) {
1455 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1456 if (!NT_STATUS_IS_OK(unix_ERR_ntstatus))
1457 ret = unix_ERR_ntstatus;
1458 else if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1459 ret = NT_STATUS_SHARING_VIOLATION;
1460 unix_ERR_class = 0;
1461 unix_ERR_code = 0;
1462 unix_ERR_ntstatus = NT_STATUS_OK;
1463 return ret;
1465 close_file(fsp,False);
1466 return NT_STATUS_OK;
1469 /****************************************************************************
1470 The guts of the unlink command, split out so it may be called by the NT SMB
1471 code.
1472 ****************************************************************************/
1474 NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
1476 pstring directory;
1477 pstring mask;
1478 char *p;
1479 int count=0;
1480 NTSTATUS error = NT_STATUS_OK;
1481 BOOL has_wild;
1482 BOOL bad_path = False;
1483 BOOL rc = True;
1484 SMB_STRUCT_STAT sbuf;
1486 *directory = *mask = 0;
1488 /* We must check for wildcards in the name given
1489 * directly by the client - before any unmangling.
1490 * This prevents an unmangling of a UNIX name containing
1491 * a DOS wildcard like '*' or '?' from unmangling into
1492 * a wildcard delete which was not intended.
1493 * FIX for #226. JRA.
1496 has_wild = ms_has_wild(name);
1498 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1500 p = strrchr_m(name,'/');
1501 if (!p) {
1502 pstrcpy(directory,".");
1503 pstrcpy(mask,name);
1504 } else {
1505 *p = 0;
1506 pstrcpy(directory,name);
1507 pstrcpy(mask,p+1);
1511 * We should only check the mangled cache
1512 * here if unix_convert failed. This means
1513 * that the path in 'mask' doesn't exist
1514 * on the file system and so we need to look
1515 * for a possible mangle. This patch from
1516 * Tine Smukavec <valentin.smukavec@hermes.si>.
1519 if (!rc && mangle_is_mangled(mask))
1520 mangle_check_cache( mask );
1522 if (!has_wild) {
1523 pstrcat(directory,"/");
1524 pstrcat(directory,mask);
1525 error = can_delete(directory,conn,dirtype,bad_path);
1526 if (!NT_STATUS_IS_OK(error))
1527 return error;
1529 if (SMB_VFS_UNLINK(conn,directory) == 0) {
1530 count++;
1532 } else {
1533 void *dirptr = NULL;
1534 const char *dname;
1536 if (check_name(directory,conn))
1537 dirptr = OpenDir(conn, directory, True);
1539 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1540 the pattern matches against the long name, otherwise the short name
1541 We don't implement this yet XXXX
1544 if (dirptr) {
1545 error = NT_STATUS_NO_SUCH_FILE;
1547 if (strequal(mask,"????????.???"))
1548 pstrcpy(mask,"*");
1550 while ((dname = ReadDirName(dirptr))) {
1551 pstring fname;
1552 BOOL sys_direntry = False;
1553 pstrcpy(fname,dname);
1555 /* Quick check for "." and ".." */
1556 if (fname[0] == '.') {
1557 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
1558 if ((dirtype & aDIR)) {
1559 sys_direntry = True;
1560 } else {
1561 continue;
1566 if(!mask_match(fname, mask, case_sensitive))
1567 continue;
1569 if (sys_direntry) {
1570 error = NT_STATUS_OBJECT_NAME_INVALID;
1571 continue;
1574 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1575 error = can_delete(fname,conn,dirtype,bad_path);
1576 if (!NT_STATUS_IS_OK(error))
1577 continue;
1578 if (SMB_VFS_UNLINK(conn,fname) == 0)
1579 count++;
1580 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
1582 CloseDir(dirptr);
1586 if (count == 0 && NT_STATUS_IS_OK(error)) {
1587 error = map_nt_error_from_unix(errno);
1590 return error;
1593 /****************************************************************************
1594 Reply to a unlink
1595 ****************************************************************************/
1597 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
1598 int dum_buffsize)
1600 int outsize = 0;
1601 pstring name;
1602 int dirtype;
1603 NTSTATUS status;
1604 START_PROFILE(SMBunlink);
1606 dirtype = SVAL(inbuf,smb_vwv0);
1608 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
1609 if (!NT_STATUS_IS_OK(status)) {
1610 END_PROFILE(SMBunlink);
1611 return ERROR_NT(status);
1614 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1616 DEBUG(3,("reply_unlink : %s\n",name));
1618 status = unlink_internals(conn, dirtype, name);
1619 if (!NT_STATUS_IS_OK(status))
1620 return ERROR_NT(status);
1623 * Win2k needs a changenotify request response before it will
1624 * update after a rename..
1626 process_pending_change_notify_queue((time_t)0);
1628 outsize = set_message(outbuf,0,0,True);
1630 END_PROFILE(SMBunlink);
1631 return outsize;
1634 /****************************************************************************
1635 Fail for readbraw.
1636 ****************************************************************************/
1638 void fail_readraw(void)
1640 pstring errstr;
1641 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
1642 strerror(errno) );
1643 exit_server(errstr);
1646 /****************************************************************************
1647 Use sendfile in readbraw.
1648 ****************************************************************************/
1650 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
1651 ssize_t mincount, char *outbuf)
1653 ssize_t ret=0;
1655 #if defined(WITH_SENDFILE)
1657 * We can only use sendfile on a non-chained packet and on a file
1658 * that is exclusively oplocked. reply_readbraw has already checked the length.
1661 if ((nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) &&
1662 EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && lp_use_sendfile(SNUM(conn)) ) {
1663 DATA_BLOB header;
1665 _smb_setlen(outbuf,nread);
1666 header.data = outbuf;
1667 header.length = 4;
1668 header.free = NULL;
1670 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) {
1672 * Special hack for broken Linux with no 64 bit clean sendfile. If we
1673 * return ENOSYS then pretend we just got a normal read.
1675 if (errno == ENOSYS)
1676 goto normal_read;
1678 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
1679 fsp->fsp_name, strerror(errno) ));
1680 exit_server("send_file_readbraw sendfile failed");
1685 normal_read:
1686 #endif
1688 if (nread > 0) {
1689 ret = read_file(fsp,outbuf+4,startpos,nread);
1690 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1691 if (ret < mincount)
1692 ret = 0;
1693 #else
1694 if (ret < nread)
1695 ret = 0;
1696 #endif
1699 _smb_setlen(outbuf,ret);
1700 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
1701 fail_readraw();
1704 /****************************************************************************
1705 Reply to a readbraw (core+ protocol).
1706 ****************************************************************************/
1708 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
1710 extern struct current_user current_user;
1711 ssize_t maxcount,mincount;
1712 size_t nread = 0;
1713 SMB_OFF_T startpos;
1714 char *header = outbuf;
1715 files_struct *fsp;
1716 START_PROFILE(SMBreadbraw);
1718 if (srv_is_signing_active()) {
1719 exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
1723 * Special check if an oplock break has been issued
1724 * and the readraw request croses on the wire, we must
1725 * return a zero length response here.
1728 if(global_oplock_break) {
1729 _smb_setlen(header,0);
1730 if (write_data(smbd_server_fd(),header,4) != 4)
1731 fail_readraw();
1732 DEBUG(5,("readbraw - oplock break finished\n"));
1733 END_PROFILE(SMBreadbraw);
1734 return -1;
1737 fsp = file_fsp(inbuf,smb_vwv0);
1739 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1741 * fsp could be NULL here so use the value from the packet. JRA.
1743 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
1744 _smb_setlen(header,0);
1745 if (write_data(smbd_server_fd(),header,4) != 4)
1746 fail_readraw();
1747 END_PROFILE(SMBreadbraw);
1748 return(-1);
1751 CHECK_FSP(fsp,conn);
1753 flush_write_cache(fsp, READRAW_FLUSH);
1755 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
1756 if(CVAL(inbuf,smb_wct) == 10) {
1758 * This is a large offset (64 bit) read.
1760 #ifdef LARGE_SMB_OFF_T
1762 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
1764 #else /* !LARGE_SMB_OFF_T */
1767 * Ensure we haven't been sent a >32 bit offset.
1770 if(IVAL(inbuf,smb_vwv8) != 0) {
1771 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
1772 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
1773 _smb_setlen(header,0);
1774 if (write_data(smbd_server_fd(),header,4) != 4)
1775 fail_readraw();
1776 END_PROFILE(SMBreadbraw);
1777 return(-1);
1780 #endif /* LARGE_SMB_OFF_T */
1782 if(startpos < 0) {
1783 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
1784 _smb_setlen(header,0);
1785 if (write_data(smbd_server_fd(),header,4) != 4)
1786 fail_readraw();
1787 END_PROFILE(SMBreadbraw);
1788 return(-1);
1791 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
1792 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
1794 /* ensure we don't overrun the packet size */
1795 maxcount = MIN(65535,maxcount);
1797 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1798 SMB_OFF_T size = fsp->size;
1799 SMB_OFF_T sizeneeded = startpos + maxcount;
1801 if (size < sizeneeded) {
1802 SMB_STRUCT_STAT st;
1803 if (SMB_VFS_FSTAT(fsp,fsp->fd,&st) == 0)
1804 size = st.st_size;
1805 if (!fsp->can_write)
1806 fsp->size = size;
1809 if (startpos >= size)
1810 nread = 0;
1811 else
1812 nread = MIN(maxcount,(size - startpos));
1815 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1816 if (nread < mincount)
1817 nread = 0;
1818 #endif
1820 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
1821 (int)maxcount, (int)mincount, (int)nread ) );
1823 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf);
1825 DEBUG(5,("readbraw finished\n"));
1826 END_PROFILE(SMBreadbraw);
1827 return -1;
1830 /****************************************************************************
1831 Reply to a lockread (core+ protocol).
1832 ****************************************************************************/
1834 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
1836 ssize_t nread = -1;
1837 char *data;
1838 int outsize = 0;
1839 SMB_OFF_T startpos;
1840 size_t numtoread;
1841 NTSTATUS status;
1842 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1843 BOOL my_lock_ctx = False;
1844 START_PROFILE(SMBlockread);
1846 CHECK_FSP(fsp,conn);
1847 CHECK_READ(fsp);
1849 release_level_2_oplocks_on_change(fsp);
1851 numtoread = SVAL(inbuf,smb_vwv1);
1852 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
1854 outsize = set_message(outbuf,5,3,True);
1855 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1856 data = smb_buf(outbuf) + 3;
1859 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
1860 * protocol request that predates the read/write lock concept.
1861 * Thus instead of asking for a read lock here we need to ask
1862 * for a write lock. JRA.
1863 * Note that the requested lock size is unaffected by max_recv.
1866 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid),
1867 (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, &my_lock_ctx);
1869 if (NT_STATUS_V(status)) {
1870 #if 0
1872 * We used to make lockread a blocking lock. It turns out
1873 * that this isn't on W2k. Found by the Samba 4 RAW-READ torture
1874 * tester. JRA.
1877 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
1879 * A blocking lock was requested. Package up
1880 * this smb into a queued request and push it
1881 * onto the blocking lock queue.
1883 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)startpos,
1884 (SMB_BIG_UINT)numtoread)) {
1885 END_PROFILE(SMBlockread);
1886 return -1;
1889 #endif
1890 END_PROFILE(SMBlockread);
1891 return ERROR_NT(status);
1895 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
1898 if (numtoread > max_recv) {
1899 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
1900 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
1901 (unsigned int)numtoread, (unsigned int)max_recv ));
1902 numtoread = MIN(numtoread,max_recv);
1904 nread = read_file(fsp,data,startpos,numtoread);
1906 if (nread < 0) {
1907 END_PROFILE(SMBlockread);
1908 return(UNIXERROR(ERRDOS,ERRnoaccess));
1911 outsize += nread;
1912 SSVAL(outbuf,smb_vwv0,nread);
1913 SSVAL(outbuf,smb_vwv5,nread+3);
1914 SSVAL(smb_buf(outbuf),1,nread);
1916 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
1917 fsp->fnum, (int)numtoread, (int)nread));
1919 END_PROFILE(SMBlockread);
1920 return(outsize);
1923 /****************************************************************************
1924 Reply to a read.
1925 ****************************************************************************/
1927 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
1929 size_t numtoread;
1930 ssize_t nread = 0;
1931 char *data;
1932 SMB_OFF_T startpos;
1933 int outsize = 0;
1934 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1935 START_PROFILE(SMBread);
1937 CHECK_FSP(fsp,conn);
1938 CHECK_READ(fsp);
1940 numtoread = SVAL(inbuf,smb_vwv1);
1941 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
1943 outsize = set_message(outbuf,5,3,True);
1944 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1946 * The requested read size cannot be greater than max_recv. JRA.
1948 if (numtoread > max_recv) {
1949 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
1950 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
1951 (unsigned int)numtoread, (unsigned int)max_recv ));
1952 numtoread = MIN(numtoread,max_recv);
1955 data = smb_buf(outbuf) + 3;
1957 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1958 END_PROFILE(SMBread);
1959 return ERROR_DOS(ERRDOS,ERRlock);
1962 if (numtoread > 0)
1963 nread = read_file(fsp,data,startpos,numtoread);
1965 if (nread < 0) {
1966 END_PROFILE(SMBread);
1967 return(UNIXERROR(ERRDOS,ERRnoaccess));
1970 outsize += nread;
1971 SSVAL(outbuf,smb_vwv0,nread);
1972 SSVAL(outbuf,smb_vwv5,nread+3);
1973 SCVAL(smb_buf(outbuf),0,1);
1974 SSVAL(smb_buf(outbuf),1,nread);
1976 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
1977 fsp->fnum, (int)numtoread, (int)nread ) );
1979 END_PROFILE(SMBread);
1980 return(outsize);
1983 /****************************************************************************
1984 Reply to a read and X - possibly using sendfile.
1985 ****************************************************************************/
1987 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length,
1988 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
1990 ssize_t nread = -1;
1991 char *data = smb_buf(outbuf);
1993 #if defined(WITH_SENDFILE)
1995 * We can only use sendfile on a non-chained packet and on a file
1996 * that is exclusively oplocked.
1999 if ((CVAL(inbuf,smb_vwv0) == 0xFF) && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) &&
2000 lp_use_sendfile(SNUM(conn)) && (lp_write_cache_size(SNUM(conn)) == 0) ) {
2001 SMB_STRUCT_STAT sbuf;
2002 DATA_BLOB header;
2004 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1)
2005 return(UNIXERROR(ERRDOS,ERRnoaccess));
2007 if (startpos > sbuf.st_size)
2008 goto normal_read;
2010 if (smb_maxcnt > (sbuf.st_size - startpos))
2011 smb_maxcnt = (sbuf.st_size - startpos);
2013 if (smb_maxcnt == 0)
2014 goto normal_read;
2017 * Set up the packet header before send. We
2018 * assume here the sendfile will work (get the
2019 * correct amount of data).
2022 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2023 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
2024 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2025 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
2026 SCVAL(outbuf,smb_vwv0,0xFF);
2027 set_message(outbuf,12,smb_maxcnt,False);
2028 header.data = outbuf;
2029 header.length = data - outbuf;
2030 header.free = NULL;
2032 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt) == -1) {
2034 * Special hack for broken Linux with no 64 bit clean sendfile. If we
2035 * return ENOSYS then pretend we just got a normal read.
2037 if (errno == ENOSYS)
2038 goto normal_read;
2040 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2041 fsp->fsp_name, strerror(errno) ));
2042 exit_server("send_file_readX sendfile failed");
2045 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2046 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2047 return -1;
2050 normal_read:
2052 #endif
2054 nread = read_file(fsp,data,startpos,smb_maxcnt);
2056 if (nread < 0) {
2057 END_PROFILE(SMBreadX);
2058 return(UNIXERROR(ERRDOS,ERRnoaccess));
2061 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2062 SSVAL(outbuf,smb_vwv5,nread);
2063 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2064 SSVAL(smb_buf(outbuf),-2,nread);
2066 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2067 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2069 return nread;
2072 /****************************************************************************
2073 Reply to a read and X.
2074 ****************************************************************************/
2076 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2078 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2079 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2080 ssize_t nread = -1;
2081 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2082 #if 0
2083 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2084 #endif
2086 START_PROFILE(SMBreadX);
2088 /* If it's an IPC, pass off the pipe handler. */
2089 if (IS_IPC(conn)) {
2090 END_PROFILE(SMBreadX);
2091 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2094 CHECK_FSP(fsp,conn);
2095 CHECK_READ(fsp);
2097 set_message(outbuf,12,0,True);
2099 if(CVAL(inbuf,smb_wct) == 12) {
2100 #ifdef LARGE_SMB_OFF_T
2102 * This is a large offset (64 bit) read.
2104 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2106 #else /* !LARGE_SMB_OFF_T */
2109 * Ensure we haven't been sent a >32 bit offset.
2112 if(IVAL(inbuf,smb_vwv10) != 0) {
2113 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2114 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2115 END_PROFILE(SMBreadX);
2116 return ERROR_DOS(ERRDOS,ERRbadaccess);
2119 #endif /* LARGE_SMB_OFF_T */
2123 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
2124 END_PROFILE(SMBreadX);
2125 return ERROR_DOS(ERRDOS,ERRlock);
2128 nread = send_file_readX(conn, inbuf, outbuf, length, fsp, startpos, smb_maxcnt);
2129 if (nread != -1)
2130 nread = chain_reply(inbuf,outbuf,length,bufsize);
2132 END_PROFILE(SMBreadX);
2133 return nread;
2136 /****************************************************************************
2137 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2138 ****************************************************************************/
2140 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2142 ssize_t nwritten=0;
2143 ssize_t total_written=0;
2144 size_t numtowrite=0;
2145 size_t tcount;
2146 SMB_OFF_T startpos;
2147 char *data=NULL;
2148 BOOL write_through;
2149 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2150 int outsize = 0;
2151 START_PROFILE(SMBwritebraw);
2153 if (srv_is_signing_active()) {
2154 exit_server("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2157 CHECK_FSP(fsp,conn);
2158 CHECK_WRITE(fsp);
2160 tcount = IVAL(inbuf,smb_vwv1);
2161 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2162 write_through = BITSETW(inbuf+smb_vwv7,0);
2164 /* We have to deal with slightly different formats depending
2165 on whether we are using the core+ or lanman1.0 protocol */
2167 if(Protocol <= PROTOCOL_COREPLUS) {
2168 numtowrite = SVAL(smb_buf(inbuf),-2);
2169 data = smb_buf(inbuf);
2170 } else {
2171 numtowrite = SVAL(inbuf,smb_vwv10);
2172 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2175 /* force the error type */
2176 SCVAL(inbuf,smb_com,SMBwritec);
2177 SCVAL(outbuf,smb_com,SMBwritec);
2179 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2180 END_PROFILE(SMBwritebraw);
2181 return(ERROR_DOS(ERRDOS,ERRlock));
2184 if (numtowrite>0)
2185 nwritten = write_file(fsp,data,startpos,numtowrite);
2187 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2188 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2190 if (nwritten < (ssize_t)numtowrite) {
2191 END_PROFILE(SMBwritebraw);
2192 return(UNIXERROR(ERRHRD,ERRdiskfull));
2195 total_written = nwritten;
2197 /* Return a message to the redirector to tell it to send more bytes */
2198 SCVAL(outbuf,smb_com,SMBwritebraw);
2199 SSVALS(outbuf,smb_vwv0,-1);
2200 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2201 if (!send_smb(smbd_server_fd(),outbuf))
2202 exit_server("reply_writebraw: send_smb failed.");
2204 /* Now read the raw data into the buffer and write it */
2205 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2206 exit_server("secondary writebraw failed");
2209 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2210 numtowrite = smb_len(inbuf);
2212 /* Set up outbuf to return the correct return */
2213 outsize = set_message(outbuf,1,0,True);
2214 SCVAL(outbuf,smb_com,SMBwritec);
2215 SSVAL(outbuf,smb_vwv0,total_written);
2217 if (numtowrite != 0) {
2219 if (numtowrite > BUFFER_SIZE) {
2220 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2221 (unsigned int)numtowrite ));
2222 exit_server("secondary writebraw failed");
2225 if (tcount > nwritten+numtowrite) {
2226 DEBUG(3,("Client overestimated the write %d %d %d\n",
2227 (int)tcount,(int)nwritten,(int)numtowrite));
2230 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2231 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2232 strerror(errno) ));
2233 exit_server("secondary writebraw failed");
2236 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2238 if (nwritten < (ssize_t)numtowrite) {
2239 SCVAL(outbuf,smb_rcls,ERRHRD);
2240 SSVAL(outbuf,smb_err,ERRdiskfull);
2243 if (nwritten > 0)
2244 total_written += nwritten;
2247 if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn)))
2248 sync_file(conn,fsp);
2250 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2251 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2253 /* we won't return a status if write through is not selected - this follows what WfWg does */
2254 END_PROFILE(SMBwritebraw);
2255 if (!write_through && total_written==tcount) {
2257 #if RABBIT_PELLET_FIX
2259 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2260 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2262 if (!send_keepalive(smbd_server_fd()))
2263 exit_server("reply_writebraw: send of keepalive failed");
2264 #endif
2265 return(-1);
2268 return(outsize);
2271 /****************************************************************************
2272 Reply to a writeunlock (core+).
2273 ****************************************************************************/
2275 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
2276 int size, int dum_buffsize)
2278 ssize_t nwritten = -1;
2279 size_t numtowrite;
2280 SMB_OFF_T startpos;
2281 char *data;
2282 NTSTATUS status = NT_STATUS_OK;
2283 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2284 int outsize = 0;
2285 START_PROFILE(SMBwriteunlock);
2287 CHECK_FSP(fsp,conn);
2288 CHECK_WRITE(fsp);
2290 numtowrite = SVAL(inbuf,smb_vwv1);
2291 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2292 data = smb_buf(inbuf) + 3;
2294 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos,
2295 WRITE_LOCK,False)) {
2296 END_PROFILE(SMBwriteunlock);
2297 return ERROR_DOS(ERRDOS,ERRlock);
2300 /* The special X/Open SMB protocol handling of
2301 zero length writes is *NOT* done for
2302 this call */
2303 if(numtowrite == 0)
2304 nwritten = 0;
2305 else
2306 nwritten = write_file(fsp,data,startpos,numtowrite);
2308 if (lp_syncalways(SNUM(conn)))
2309 sync_file(conn,fsp);
2311 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2312 END_PROFILE(SMBwriteunlock);
2313 return(UNIXERROR(ERRHRD,ERRdiskfull));
2316 if (numtowrite) {
2317 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite,
2318 (SMB_BIG_UINT)startpos);
2319 if (NT_STATUS_V(status)) {
2320 END_PROFILE(SMBwriteunlock);
2321 return ERROR_NT(status);
2325 outsize = set_message(outbuf,1,0,True);
2327 SSVAL(outbuf,smb_vwv0,nwritten);
2329 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2330 fsp->fnum, (int)numtowrite, (int)nwritten));
2332 END_PROFILE(SMBwriteunlock);
2333 return outsize;
2336 /****************************************************************************
2337 Reply to a write.
2338 ****************************************************************************/
2340 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2342 size_t numtowrite;
2343 ssize_t nwritten = -1;
2344 SMB_OFF_T startpos;
2345 char *data;
2346 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2347 int outsize = 0;
2348 START_PROFILE(SMBwrite);
2350 /* If it's an IPC, pass off the pipe handler. */
2351 if (IS_IPC(conn)) {
2352 END_PROFILE(SMBwrite);
2353 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2356 CHECK_FSP(fsp,conn);
2357 CHECK_WRITE(fsp);
2359 numtowrite = SVAL(inbuf,smb_vwv1);
2360 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2361 data = smb_buf(inbuf) + 3;
2363 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2364 END_PROFILE(SMBwrite);
2365 return ERROR_DOS(ERRDOS,ERRlock);
2369 * X/Open SMB protocol says that if smb_vwv1 is
2370 * zero then the file size should be extended or
2371 * truncated to the size given in smb_vwv[2-3].
2374 if(numtowrite == 0) {
2376 * This is actually an allocate call, and set EOF. JRA.
2378 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2379 if (nwritten < 0) {
2380 END_PROFILE(SMBwrite);
2381 return ERROR_NT(NT_STATUS_DISK_FULL);
2383 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2384 if (nwritten < 0) {
2385 END_PROFILE(SMBwrite);
2386 return ERROR_NT(NT_STATUS_DISK_FULL);
2388 } else
2389 nwritten = write_file(fsp,data,startpos,numtowrite);
2391 if (lp_syncalways(SNUM(conn)))
2392 sync_file(conn,fsp);
2394 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2395 END_PROFILE(SMBwrite);
2396 return(UNIXERROR(ERRHRD,ERRdiskfull));
2399 outsize = set_message(outbuf,1,0,True);
2401 SSVAL(outbuf,smb_vwv0,nwritten);
2403 if (nwritten < (ssize_t)numtowrite) {
2404 SCVAL(outbuf,smb_rcls,ERRHRD);
2405 SSVAL(outbuf,smb_err,ERRdiskfull);
2408 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2410 END_PROFILE(SMBwrite);
2411 return(outsize);
2414 /****************************************************************************
2415 Reply to a write and X.
2416 ****************************************************************************/
2418 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2420 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2421 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2422 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2423 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2424 ssize_t nwritten = -1;
2425 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2426 unsigned int smblen = smb_len(inbuf);
2427 char *data;
2428 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2429 START_PROFILE(SMBwriteX);
2431 /* If it's an IPC, pass off the pipe handler. */
2432 if (IS_IPC(conn)) {
2433 END_PROFILE(SMBwriteX);
2434 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2437 CHECK_FSP(fsp,conn);
2438 CHECK_WRITE(fsp);
2440 /* Deal with possible LARGE_WRITEX */
2441 if (large_writeX)
2442 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2444 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2445 END_PROFILE(SMBwriteX);
2446 return ERROR_DOS(ERRDOS,ERRbadmem);
2449 data = smb_base(inbuf) + smb_doff;
2451 if(CVAL(inbuf,smb_wct) == 14) {
2452 #ifdef LARGE_SMB_OFF_T
2454 * This is a large offset (64 bit) write.
2456 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2458 #else /* !LARGE_SMB_OFF_T */
2461 * Ensure we haven't been sent a >32 bit offset.
2464 if(IVAL(inbuf,smb_vwv12) != 0) {
2465 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2466 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2467 END_PROFILE(SMBwriteX);
2468 return ERROR_DOS(ERRDOS,ERRbadaccess);
2471 #endif /* LARGE_SMB_OFF_T */
2474 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2475 END_PROFILE(SMBwriteX);
2476 return ERROR_DOS(ERRDOS,ERRlock);
2479 /* X/Open SMB protocol says that, unlike SMBwrite
2480 if the length is zero then NO truncation is
2481 done, just a write of zero. To truncate a file,
2482 use SMBwrite. */
2484 if(numtowrite == 0)
2485 nwritten = 0;
2486 else
2487 nwritten = write_file(fsp,data,startpos,numtowrite);
2489 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2490 END_PROFILE(SMBwriteX);
2491 return(UNIXERROR(ERRHRD,ERRdiskfull));
2494 set_message(outbuf,6,0,True);
2496 SSVAL(outbuf,smb_vwv2,nwritten);
2497 if (large_writeX)
2498 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2500 if (nwritten < (ssize_t)numtowrite) {
2501 SCVAL(outbuf,smb_rcls,ERRHRD);
2502 SSVAL(outbuf,smb_err,ERRdiskfull);
2505 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2506 fsp->fnum, (int)numtowrite, (int)nwritten));
2508 if (lp_syncalways(SNUM(conn)) || write_through)
2509 sync_file(conn,fsp);
2511 END_PROFILE(SMBwriteX);
2512 return chain_reply(inbuf,outbuf,length,bufsize);
2515 /****************************************************************************
2516 Reply to a lseek.
2517 ****************************************************************************/
2519 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2521 SMB_OFF_T startpos;
2522 SMB_OFF_T res= -1;
2523 int mode,umode;
2524 int outsize = 0;
2525 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2526 START_PROFILE(SMBlseek);
2528 CHECK_FSP(fsp,conn);
2530 flush_write_cache(fsp, SEEK_FLUSH);
2532 mode = SVAL(inbuf,smb_vwv1) & 3;
2533 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
2534 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
2536 switch (mode) {
2537 case 0:
2538 umode = SEEK_SET;
2539 res = startpos;
2540 break;
2541 case 1:
2542 umode = SEEK_CUR;
2543 res = fsp->pos + startpos;
2544 break;
2545 case 2:
2546 umode = SEEK_END;
2547 break;
2548 default:
2549 umode = SEEK_SET;
2550 res = startpos;
2551 break;
2554 if (umode == SEEK_END) {
2555 if((res = SMB_VFS_LSEEK(fsp,fsp->fd,startpos,umode)) == -1) {
2556 if(errno == EINVAL) {
2557 SMB_OFF_T current_pos = startpos;
2558 SMB_STRUCT_STAT sbuf;
2560 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) {
2561 END_PROFILE(SMBlseek);
2562 return(UNIXERROR(ERRDOS,ERRnoaccess));
2565 current_pos += sbuf.st_size;
2566 if(current_pos < 0)
2567 res = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_SET);
2571 if(res == -1) {
2572 END_PROFILE(SMBlseek);
2573 return(UNIXERROR(ERRDOS,ERRnoaccess));
2577 fsp->pos = res;
2579 outsize = set_message(outbuf,2,0,True);
2580 SIVAL(outbuf,smb_vwv0,res);
2582 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2583 fsp->fnum, (double)startpos, (double)res, mode));
2585 END_PROFILE(SMBlseek);
2586 return(outsize);
2589 /****************************************************************************
2590 Reply to a flush.
2591 ****************************************************************************/
2593 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2595 int outsize = set_message(outbuf,0,0,True);
2596 uint16 fnum = SVAL(inbuf,smb_vwv0);
2597 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2598 START_PROFILE(SMBflush);
2600 if (fnum != 0xFFFF)
2601 CHECK_FSP(fsp,conn);
2603 if (!fsp) {
2604 file_sync_all(conn);
2605 } else {
2606 sync_file(conn,fsp);
2609 DEBUG(3,("flush\n"));
2610 END_PROFILE(SMBflush);
2611 return(outsize);
2614 /****************************************************************************
2615 Reply to a exit.
2616 ****************************************************************************/
2618 int reply_exit(connection_struct *conn,
2619 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2621 int outsize;
2622 START_PROFILE(SMBexit);
2624 file_close_pid(SVAL(inbuf,smb_pid));
2626 outsize = set_message(outbuf,0,0,True);
2628 DEBUG(3,("exit\n"));
2630 END_PROFILE(SMBexit);
2631 return(outsize);
2634 /****************************************************************************
2635 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2636 ****************************************************************************/
2638 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2639 int dum_buffsize)
2641 extern struct current_user current_user;
2642 int outsize = 0;
2643 time_t mtime;
2644 int32 eclass = 0, err = 0;
2645 files_struct *fsp = NULL;
2646 START_PROFILE(SMBclose);
2648 outsize = set_message(outbuf,0,0,True);
2650 /* If it's an IPC, pass off to the pipe handler. */
2651 if (IS_IPC(conn)) {
2652 END_PROFILE(SMBclose);
2653 return reply_pipe_close(conn, inbuf,outbuf);
2656 fsp = file_fsp(inbuf,smb_vwv0);
2659 * We can only use CHECK_FSP if we know it's not a directory.
2662 if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
2663 END_PROFILE(SMBclose);
2664 return ERROR_DOS(ERRDOS,ERRbadfid);
2667 if(fsp->is_directory) {
2669 * Special case - close NT SMB directory handle.
2671 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2672 close_file(fsp,True);
2673 } else {
2675 * Close ordinary file.
2677 int close_err;
2678 pstring file_name;
2680 /* Save the name for time set in close. */
2681 pstrcpy( file_name, fsp->fsp_name);
2683 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2684 fsp->fd, fsp->fnum,
2685 conn->num_files_open));
2688 * close_file() returns the unix errno if an error
2689 * was detected on close - normally this is due to
2690 * a disk full error. If not then it was probably an I/O error.
2693 if((close_err = close_file(fsp,True)) != 0) {
2694 errno = close_err;
2695 END_PROFILE(SMBclose);
2696 return (UNIXERROR(ERRHRD,ERRgeneral));
2700 * Now take care of any time sent in the close.
2703 mtime = make_unix_date3(inbuf+smb_vwv1);
2705 /* try and set the date */
2706 set_filetime(conn, file_name, mtime);
2710 /* We have a cached error */
2711 if(eclass || err) {
2712 END_PROFILE(SMBclose);
2713 return ERROR_DOS(eclass,err);
2716 END_PROFILE(SMBclose);
2717 return(outsize);
2720 /****************************************************************************
2721 Reply to a writeclose (Core+ protocol).
2722 ****************************************************************************/
2724 int reply_writeclose(connection_struct *conn,
2725 char *inbuf,char *outbuf, int size, int dum_buffsize)
2727 size_t numtowrite;
2728 ssize_t nwritten = -1;
2729 int outsize = 0;
2730 int close_err = 0;
2731 SMB_OFF_T startpos;
2732 char *data;
2733 time_t mtime;
2734 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2735 START_PROFILE(SMBwriteclose);
2737 CHECK_FSP(fsp,conn);
2738 CHECK_WRITE(fsp);
2740 numtowrite = SVAL(inbuf,smb_vwv1);
2741 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2742 mtime = make_unix_date3(inbuf+smb_vwv4);
2743 data = smb_buf(inbuf) + 1;
2745 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2746 END_PROFILE(SMBwriteclose);
2747 return ERROR_DOS(ERRDOS,ERRlock);
2750 nwritten = write_file(fsp,data,startpos,numtowrite);
2752 set_filetime(conn, fsp->fsp_name,mtime);
2755 * More insanity. W2K only closes the file if writelen > 0.
2756 * JRA.
2759 if (numtowrite) {
2760 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
2761 fsp->fsp_name ));
2762 close_err = close_file(fsp,True);
2765 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2766 fsp->fnum, (int)numtowrite, (int)nwritten,
2767 conn->num_files_open));
2769 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2770 END_PROFILE(SMBwriteclose);
2771 return(UNIXERROR(ERRHRD,ERRdiskfull));
2774 if(close_err != 0) {
2775 errno = close_err;
2776 END_PROFILE(SMBwriteclose);
2777 return(UNIXERROR(ERRHRD,ERRgeneral));
2780 outsize = set_message(outbuf,1,0,True);
2782 SSVAL(outbuf,smb_vwv0,nwritten);
2783 END_PROFILE(SMBwriteclose);
2784 return(outsize);
2787 /****************************************************************************
2788 Reply to a lock.
2789 ****************************************************************************/
2791 int reply_lock(connection_struct *conn,
2792 char *inbuf,char *outbuf, int length, int dum_buffsize)
2794 int outsize = set_message(outbuf,0,0,True);
2795 SMB_BIG_UINT count,offset;
2796 NTSTATUS status;
2797 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2798 BOOL my_lock_ctx = False;
2800 START_PROFILE(SMBlock);
2802 CHECK_FSP(fsp,conn);
2804 release_level_2_oplocks_on_change(fsp);
2806 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2807 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2809 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2810 fsp->fd, fsp->fnum, (double)offset, (double)count));
2812 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &my_lock_ctx);
2813 if (NT_STATUS_V(status)) {
2814 #if 0
2815 /* Tests using Samba4 against W2K show this call never creates a blocking lock. */
2816 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
2818 * A blocking lock was requested. Package up
2819 * this smb into a queued request and push it
2820 * onto the blocking lock queue.
2822 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), offset, count)) {
2823 END_PROFILE(SMBlock);
2824 return -1;
2827 #endif
2828 END_PROFILE(SMBlock);
2829 return ERROR_NT(status);
2832 END_PROFILE(SMBlock);
2833 return(outsize);
2836 /****************************************************************************
2837 Reply to a unlock.
2838 ****************************************************************************/
2840 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
2841 int dum_buffsize)
2843 int outsize = set_message(outbuf,0,0,True);
2844 SMB_BIG_UINT count,offset;
2845 NTSTATUS status;
2846 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2847 START_PROFILE(SMBunlock);
2849 CHECK_FSP(fsp,conn);
2851 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2852 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2854 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
2855 if (NT_STATUS_V(status)) {
2856 END_PROFILE(SMBunlock);
2857 return ERROR_NT(status);
2860 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2861 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
2863 END_PROFILE(SMBunlock);
2864 return(outsize);
2867 /****************************************************************************
2868 Reply to a tdis.
2869 ****************************************************************************/
2871 int reply_tdis(connection_struct *conn,
2872 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2874 int outsize = set_message(outbuf,0,0,True);
2875 uint16 vuid;
2876 START_PROFILE(SMBtdis);
2878 vuid = SVAL(inbuf,smb_uid);
2880 if (!conn) {
2881 DEBUG(4,("Invalid connection in tdis\n"));
2882 END_PROFILE(SMBtdis);
2883 return ERROR_DOS(ERRSRV,ERRinvnid);
2886 conn->used = False;
2888 close_cnum(conn,vuid);
2890 END_PROFILE(SMBtdis);
2891 return outsize;
2894 /****************************************************************************
2895 Reply to a echo.
2896 ****************************************************************************/
2898 int reply_echo(connection_struct *conn,
2899 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2901 int smb_reverb = SVAL(inbuf,smb_vwv0);
2902 int seq_num;
2903 unsigned int data_len = smb_buflen(inbuf);
2904 int outsize = set_message(outbuf,1,data_len,True);
2905 START_PROFILE(SMBecho);
2907 if (data_len > BUFFER_SIZE) {
2908 DEBUG(0,("reply_echo: data_len too large.\n"));
2909 END_PROFILE(SMBecho);
2910 return -1;
2913 /* copy any incoming data back out */
2914 if (data_len > 0)
2915 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2917 if (smb_reverb > 100) {
2918 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2919 smb_reverb = 100;
2922 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
2923 SSVAL(outbuf,smb_vwv0,seq_num);
2925 smb_setlen(outbuf,outsize - 4);
2927 if (!send_smb(smbd_server_fd(),outbuf))
2928 exit_server("reply_echo: send_smb failed.");
2931 DEBUG(3,("echo %d times\n", smb_reverb));
2933 smb_echo_count++;
2935 END_PROFILE(SMBecho);
2936 return -1;
2939 /****************************************************************************
2940 Reply to a printopen.
2941 ****************************************************************************/
2943 int reply_printopen(connection_struct *conn,
2944 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2946 int outsize = 0;
2947 files_struct *fsp;
2948 START_PROFILE(SMBsplopen);
2950 if (!CAN_PRINT(conn)) {
2951 END_PROFILE(SMBsplopen);
2952 return ERROR_DOS(ERRDOS,ERRnoaccess);
2955 /* Open for exclusive use, write only. */
2956 fsp = print_fsp_open(conn, NULL);
2958 if (!fsp) {
2959 END_PROFILE(SMBsplopen);
2960 return(UNIXERROR(ERRDOS,ERRnoaccess));
2963 outsize = set_message(outbuf,1,0,True);
2964 SSVAL(outbuf,smb_vwv0,fsp->fnum);
2966 DEBUG(3,("openprint fd=%d fnum=%d\n",
2967 fsp->fd, fsp->fnum));
2969 END_PROFILE(SMBsplopen);
2970 return(outsize);
2973 /****************************************************************************
2974 Reply to a printclose.
2975 ****************************************************************************/
2977 int reply_printclose(connection_struct *conn,
2978 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2980 int outsize = set_message(outbuf,0,0,True);
2981 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2982 int close_err = 0;
2983 START_PROFILE(SMBsplclose);
2985 CHECK_FSP(fsp,conn);
2987 if (!CAN_PRINT(conn)) {
2988 END_PROFILE(SMBsplclose);
2989 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
2992 DEBUG(3,("printclose fd=%d fnum=%d\n",
2993 fsp->fd,fsp->fnum));
2995 close_err = close_file(fsp,True);
2997 if(close_err != 0) {
2998 errno = close_err;
2999 END_PROFILE(SMBsplclose);
3000 return(UNIXERROR(ERRHRD,ERRgeneral));
3003 END_PROFILE(SMBsplclose);
3004 return(outsize);
3007 /****************************************************************************
3008 Reply to a printqueue.
3009 ****************************************************************************/
3011 int reply_printqueue(connection_struct *conn,
3012 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3014 int outsize = set_message(outbuf,2,3,True);
3015 int max_count = SVAL(inbuf,smb_vwv0);
3016 int start_index = SVAL(inbuf,smb_vwv1);
3017 START_PROFILE(SMBsplretq);
3019 /* we used to allow the client to get the cnum wrong, but that
3020 is really quite gross and only worked when there was only
3021 one printer - I think we should now only accept it if they
3022 get it right (tridge) */
3023 if (!CAN_PRINT(conn)) {
3024 END_PROFILE(SMBsplretq);
3025 return ERROR_DOS(ERRDOS,ERRnoaccess);
3028 SSVAL(outbuf,smb_vwv0,0);
3029 SSVAL(outbuf,smb_vwv1,0);
3030 SCVAL(smb_buf(outbuf),0,1);
3031 SSVAL(smb_buf(outbuf),1,0);
3033 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3034 start_index, max_count));
3037 print_queue_struct *queue = NULL;
3038 print_status_struct status;
3039 char *p = smb_buf(outbuf) + 3;
3040 int count = print_queue_status(SNUM(conn), &queue, &status);
3041 int num_to_get = ABS(max_count);
3042 int first = (max_count>0?start_index:start_index+max_count+1);
3043 int i;
3045 if (first >= count)
3046 num_to_get = 0;
3047 else
3048 num_to_get = MIN(num_to_get,count-first);
3051 for (i=first;i<first+num_to_get;i++) {
3052 put_dos_date2(p,0,queue[i].time);
3053 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
3054 SSVAL(p,5, queue[i].job);
3055 SIVAL(p,7,queue[i].size);
3056 SCVAL(p,11,0);
3057 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
3058 p += 28;
3061 if (count > 0) {
3062 outsize = set_message(outbuf,2,28*count+3,False);
3063 SSVAL(outbuf,smb_vwv0,count);
3064 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3065 SCVAL(smb_buf(outbuf),0,1);
3066 SSVAL(smb_buf(outbuf),1,28*count);
3069 SAFE_FREE(queue);
3071 DEBUG(3,("%d entries returned in queue\n",count));
3074 END_PROFILE(SMBsplretq);
3075 return(outsize);
3078 /****************************************************************************
3079 Reply to a printwrite.
3080 ****************************************************************************/
3082 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3084 int numtowrite;
3085 int outsize = set_message(outbuf,0,0,True);
3086 char *data;
3087 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3089 START_PROFILE(SMBsplwr);
3091 if (!CAN_PRINT(conn)) {
3092 END_PROFILE(SMBsplwr);
3093 return ERROR_DOS(ERRDOS,ERRnoaccess);
3096 CHECK_FSP(fsp,conn);
3097 CHECK_WRITE(fsp);
3099 numtowrite = SVAL(smb_buf(inbuf),1);
3100 data = smb_buf(inbuf) + 3;
3102 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3103 END_PROFILE(SMBsplwr);
3104 return(UNIXERROR(ERRHRD,ERRdiskfull));
3107 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3109 END_PROFILE(SMBsplwr);
3110 return(outsize);
3113 /****************************************************************************
3114 The guts of the mkdir command, split out so it may be called by the NT SMB
3115 code.
3116 ****************************************************************************/
3118 NTSTATUS mkdir_internal(connection_struct *conn, pstring directory)
3120 BOOL bad_path = False;
3121 SMB_STRUCT_STAT sbuf;
3122 int ret= -1;
3124 unix_convert(directory,conn,0,&bad_path,&sbuf);
3126 if( strchr_m(directory, ':')) {
3127 return NT_STATUS_NOT_A_DIRECTORY;
3130 if (ms_has_wild(directory)) {
3131 return NT_STATUS_OBJECT_NAME_INVALID;
3134 if (check_name(directory, conn))
3135 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory));
3137 if (ret == -1) {
3138 if(errno == ENOENT) {
3139 if (bad_path)
3140 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3141 else
3142 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3144 return map_nt_error_from_unix(errno);
3147 return NT_STATUS_OK;
3150 /****************************************************************************
3151 Reply to a mkdir.
3152 ****************************************************************************/
3154 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3156 pstring directory;
3157 int outsize;
3158 NTSTATUS status;
3159 START_PROFILE(SMBmkdir);
3161 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
3162 if (!NT_STATUS_IS_OK(status)) {
3163 END_PROFILE(SMBmkdir);
3164 return ERROR_NT(status);
3167 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
3169 status = mkdir_internal(conn, directory);
3170 if (!NT_STATUS_IS_OK(status)) {
3171 END_PROFILE(SMBmkdir);
3172 return ERROR_NT(status);
3175 outsize = set_message(outbuf,0,0,True);
3177 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3179 END_PROFILE(SMBmkdir);
3180 return(outsize);
3183 /****************************************************************************
3184 Static function used by reply_rmdir to delete an entire directory
3185 tree recursively. Return False on ok, True on fail.
3186 ****************************************************************************/
3188 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3190 const char *dname = NULL;
3191 BOOL ret = False;
3192 void *dirptr = OpenDir(conn, directory, False);
3194 if(dirptr == NULL)
3195 return True;
3197 while((dname = ReadDirName(dirptr))) {
3198 pstring fullname;
3199 SMB_STRUCT_STAT st;
3201 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3202 continue;
3204 /* Construct the full name. */
3205 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3206 errno = ENOMEM;
3207 ret = True;
3208 break;
3211 pstrcpy(fullname, directory);
3212 pstrcat(fullname, "/");
3213 pstrcat(fullname, dname);
3215 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
3216 ret = True;
3217 break;
3220 if(st.st_mode & S_IFDIR) {
3221 if(recursive_rmdir(conn, fullname)!=0) {
3222 ret = True;
3223 break;
3225 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
3226 ret = True;
3227 break;
3229 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
3230 ret = True;
3231 break;
3234 CloseDir(dirptr);
3235 return ret;
3238 /****************************************************************************
3239 The internals of the rmdir code - called elsewhere.
3240 ****************************************************************************/
3242 BOOL rmdir_internals(connection_struct *conn, char *directory)
3244 BOOL ok;
3246 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3247 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3249 * Check to see if the only thing in this directory are
3250 * vetoed files/directories. If so then delete them and
3251 * retry. If we fail to delete any of them (and we *don't*
3252 * do a recursive delete) then fail the rmdir.
3254 BOOL all_veto_files = True;
3255 const char *dname;
3256 void *dirptr = OpenDir(conn, directory, False);
3258 if(dirptr != NULL) {
3259 int dirpos = TellDir(dirptr);
3260 while ((dname = ReadDirName(dirptr))) {
3261 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3262 continue;
3263 if(!IS_VETO_PATH(conn, dname)) {
3264 all_veto_files = False;
3265 break;
3269 if(all_veto_files) {
3270 SeekDir(dirptr,dirpos);
3271 while ((dname = ReadDirName(dirptr))) {
3272 pstring fullname;
3273 SMB_STRUCT_STAT st;
3275 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3276 continue;
3278 /* Construct the full name. */
3279 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3280 errno = ENOMEM;
3281 break;
3284 pstrcpy(fullname, directory);
3285 pstrcat(fullname, "/");
3286 pstrcat(fullname, dname);
3288 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
3289 break;
3290 if(st.st_mode & S_IFDIR) {
3291 if(lp_recursive_veto_delete(SNUM(conn))) {
3292 if(recursive_rmdir(conn, fullname) != 0)
3293 break;
3295 if(SMB_VFS_RMDIR(conn,fullname) != 0)
3296 break;
3297 } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
3298 break;
3300 CloseDir(dirptr);
3301 /* Retry the rmdir */
3302 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3303 } else {
3304 CloseDir(dirptr);
3306 } else {
3307 errno = ENOTEMPTY;
3311 if (!ok)
3312 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
3314 return ok;
3317 /****************************************************************************
3318 Reply to a rmdir.
3319 ****************************************************************************/
3321 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3323 pstring directory;
3324 int outsize = 0;
3325 BOOL ok = False;
3326 BOOL bad_path = False;
3327 SMB_STRUCT_STAT sbuf;
3328 NTSTATUS status;
3329 START_PROFILE(SMBrmdir);
3331 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
3332 if (!NT_STATUS_IS_OK(status)) {
3333 END_PROFILE(SMBrmdir);
3334 return ERROR_NT(status);
3337 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3339 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3341 if (check_name(directory,conn)) {
3342 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3343 ok = rmdir_internals(conn, directory);
3346 if (!ok) {
3347 END_PROFILE(SMBrmdir);
3348 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRbadpath);
3351 outsize = set_message(outbuf,0,0,True);
3353 DEBUG( 3, ( "rmdir %s\n", directory ) );
3355 END_PROFILE(SMBrmdir);
3356 return(outsize);
3359 /*******************************************************************
3360 Resolve wildcards in a filename rename.
3361 Note that name is in UNIX charset and thus potentially can be more
3362 than fstring buffer (255 bytes) especially in default UTF-8 case.
3363 Therefore, we use pstring inside and all calls should ensure that
3364 name2 is at least pstring-long (they do already)
3365 ********************************************************************/
3367 static BOOL resolve_wildcards(const char *name1, char *name2)
3369 pstring root1,root2;
3370 pstring ext1,ext2;
3371 char *p,*p2, *pname1, *pname2;
3372 int available_space, actual_space;
3375 pname1 = strrchr_m(name1,'/');
3376 pname2 = strrchr_m(name2,'/');
3378 if (!pname1 || !pname2)
3379 return(False);
3381 pstrcpy(root1,pname1);
3382 pstrcpy(root2,pname2);
3383 p = strrchr_m(root1,'.');
3384 if (p) {
3385 *p = 0;
3386 pstrcpy(ext1,p+1);
3387 } else {
3388 pstrcpy(ext1,"");
3390 p = strrchr_m(root2,'.');
3391 if (p) {
3392 *p = 0;
3393 pstrcpy(ext2,p+1);
3394 } else {
3395 pstrcpy(ext2,"");
3398 p = root1;
3399 p2 = root2;
3400 while (*p2) {
3401 if (*p2 == '?') {
3402 *p2 = *p;
3403 p2++;
3404 } else {
3405 p2++;
3407 if (*p)
3408 p++;
3411 p = ext1;
3412 p2 = ext2;
3413 while (*p2) {
3414 if (*p2 == '?') {
3415 *p2 = *p;
3416 p2++;
3417 } else {
3418 p2++;
3420 if (*p)
3421 p++;
3424 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
3426 if (ext2[0]) {
3427 actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
3428 if (actual_space >= available_space - 1) {
3429 DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
3430 actual_space - available_space));
3432 } else {
3433 pstrcpy_base(pname2, root2, name2);
3436 return(True);
3439 /****************************************************************************
3440 Ensure open files have their names updates.
3441 ****************************************************************************/
3443 static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode, char *newname)
3445 files_struct *fsp;
3446 BOOL did_rename = False;
3448 for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
3449 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
3450 fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
3451 fsp->fsp_name, newname ));
3452 string_set(&fsp->fsp_name, newname);
3453 did_rename = True;
3456 if (!did_rename)
3457 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
3458 (unsigned int)dev, (double)inode, newname ));
3461 /****************************************************************************
3462 Rename an open file - given an fsp.
3463 ****************************************************************************/
3465 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, BOOL replace_if_exists)
3467 SMB_STRUCT_STAT sbuf;
3468 BOOL bad_path = False;
3469 pstring newname_last_component;
3470 NTSTATUS error = NT_STATUS_OK;
3471 BOOL dest_exists;
3472 BOOL rcdest = True;
3474 ZERO_STRUCT(sbuf);
3475 rcdest = unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf);
3477 /* Quick check for "." and ".." */
3478 if (!bad_path && newname_last_component[0] == '.') {
3479 if (!newname_last_component[1] || (newname_last_component[1] == '.' && !newname_last_component[2])) {
3480 return NT_STATUS_ACCESS_DENIED;
3483 if (!rcdest && bad_path) {
3484 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3487 /* Ensure newname contains a '/' */
3488 if(strrchr_m(newname,'/') == 0) {
3489 pstring tmpstr;
3491 pstrcpy(tmpstr, "./");
3492 pstrcat(tmpstr, newname);
3493 pstrcpy(newname, tmpstr);
3497 * Check for special case with case preserving and not
3498 * case sensitive. If the old last component differs from the original
3499 * last component only by case, then we should allow
3500 * the rename (user is trying to change the case of the
3501 * filename).
3504 if((case_sensitive == False) && (case_preserve == True) &&
3505 strequal(newname, fsp->fsp_name)) {
3506 char *p;
3507 pstring newname_modified_last_component;
3510 * Get the last component of the modified name.
3511 * Note that we guarantee that newname contains a '/'
3512 * character above.
3514 p = strrchr_m(newname,'/');
3515 pstrcpy(newname_modified_last_component,p+1);
3517 if(strcsequal(newname_modified_last_component,
3518 newname_last_component) == False) {
3520 * Replace the modified last component with
3521 * the original.
3523 pstrcpy(p+1, newname_last_component);
3528 * If the src and dest names are identical - including case,
3529 * don't do the rename, just return success.
3532 if (strcsequal(fsp->fsp_name, newname)) {
3533 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
3534 newname));
3535 return NT_STATUS_OK;
3538 dest_exists = vfs_object_exist(conn,newname,NULL);
3540 if(!replace_if_exists && dest_exists) {
3541 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
3542 fsp->fsp_name,newname));
3543 return NT_STATUS_OBJECT_NAME_COLLISION;
3546 error = can_rename(newname,conn,&sbuf);
3548 if (dest_exists && !NT_STATUS_IS_OK(error)) {
3549 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3550 nt_errstr(error), fsp->fsp_name,newname));
3551 if (NT_STATUS_EQUAL(error,NT_STATUS_SHARING_VIOLATION))
3552 error = NT_STATUS_ACCESS_DENIED;
3553 return error;
3556 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
3557 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
3558 fsp->fsp_name,newname));
3559 rename_open_files(conn, fsp->dev, fsp->inode, newname);
3560 return NT_STATUS_OK;
3563 if (errno == ENOTDIR || errno == EISDIR)
3564 error = NT_STATUS_OBJECT_NAME_COLLISION;
3565 else
3566 error = map_nt_error_from_unix(errno);
3568 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
3569 nt_errstr(error), fsp->fsp_name,newname));
3571 return error;
3574 /****************************************************************************
3575 The guts of the rename command, split out so it may be called by the NT SMB
3576 code.
3577 ****************************************************************************/
3579 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, uint16 attrs, BOOL replace_if_exists)
3581 pstring directory;
3582 pstring mask;
3583 pstring last_component_src;
3584 pstring last_component_dest;
3585 char *p;
3586 BOOL has_wild;
3587 BOOL bad_path_src = False;
3588 BOOL bad_path_dest = False;
3589 int count=0;
3590 NTSTATUS error = NT_STATUS_OK;
3591 BOOL rc = True;
3592 BOOL rcdest = True;
3593 SMB_STRUCT_STAT sbuf1, sbuf2;
3595 *directory = *mask = 0;
3597 ZERO_STRUCT(sbuf1);
3598 ZERO_STRUCT(sbuf2);
3600 rc = unix_convert(name,conn,last_component_src,&bad_path_src,&sbuf1);
3601 if (!rc && bad_path_src) {
3602 if (ms_has_wild(last_component_src))
3603 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3604 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3607 /* Quick check for "." and ".." */
3608 if (last_component_src[0] == '.') {
3609 if (!last_component_src[1] || (last_component_src[1] == '.' && !last_component_src[2])) {
3610 return NT_STATUS_OBJECT_NAME_INVALID;
3614 rcdest = unix_convert(newname,conn,last_component_dest,&bad_path_dest,&sbuf2);
3616 /* Quick check for "." and ".." */
3617 if (last_component_dest[0] == '.') {
3618 if (!last_component_dest[1] || (last_component_dest[1] == '.' && !last_component_dest[2])) {
3619 return NT_STATUS_OBJECT_NAME_INVALID;
3624 * Split the old name into directory and last component
3625 * strings. Note that unix_convert may have stripped off a
3626 * leading ./ from both name and newname if the rename is
3627 * at the root of the share. We need to make sure either both
3628 * name and newname contain a / character or neither of them do
3629 * as this is checked in resolve_wildcards().
3632 p = strrchr_m(name,'/');
3633 if (!p) {
3634 pstrcpy(directory,".");
3635 pstrcpy(mask,name);
3636 } else {
3637 *p = 0;
3638 pstrcpy(directory,name);
3639 pstrcpy(mask,p+1);
3640 *p = '/'; /* Replace needed for exceptional test below. */
3644 * We should only check the mangled cache
3645 * here if unix_convert failed. This means
3646 * that the path in 'mask' doesn't exist
3647 * on the file system and so we need to look
3648 * for a possible mangle. This patch from
3649 * Tine Smukavec <valentin.smukavec@hermes.si>.
3652 if (!rc && mangle_is_mangled(mask))
3653 mangle_check_cache( mask );
3655 has_wild = ms_has_wild(mask);
3657 if (!has_wild) {
3659 * No wildcards - just process the one file.
3661 BOOL is_short_name = mangle_is_8_3(name, True);
3663 /* Add a terminating '/' to the directory name. */
3664 pstrcat(directory,"/");
3665 pstrcat(directory,mask);
3667 /* Ensure newname contains a '/' also */
3668 if(strrchr_m(newname,'/') == 0) {
3669 pstring tmpstr;
3671 pstrcpy(tmpstr, "./");
3672 pstrcat(tmpstr, newname);
3673 pstrcpy(newname, tmpstr);
3676 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
3677 directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
3678 case_sensitive, case_preserve, short_case_preserve, directory,
3679 newname, last_component_dest, is_short_name));
3682 * Check for special case with case preserving and not
3683 * case sensitive, if directory and newname are identical,
3684 * and the old last component differs from the original
3685 * last component only by case, then we should allow
3686 * the rename (user is trying to change the case of the
3687 * filename).
3689 if((case_sensitive == False) &&
3690 (((case_preserve == True) &&
3691 (is_short_name == False)) ||
3692 ((short_case_preserve == True) &&
3693 (is_short_name == True))) &&
3694 strcsequal(directory, newname)) {
3695 pstring modified_last_component;
3698 * Get the last component of the modified name.
3699 * Note that we guarantee that newname contains a '/'
3700 * character above.
3702 p = strrchr_m(newname,'/');
3703 pstrcpy(modified_last_component,p+1);
3705 if(strcsequal(modified_last_component,
3706 last_component_dest) == False) {
3708 * Replace the modified last component with
3709 * the original.
3711 pstrcpy(p+1, last_component_dest);
3715 resolve_wildcards(directory,newname);
3718 * The source object must exist.
3721 if (!vfs_object_exist(conn, directory, &sbuf1)) {
3722 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
3723 directory,newname));
3725 if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
3727 * Must return different errors depending on whether the parent
3728 * directory existed or not.
3731 p = strrchr_m(directory, '/');
3732 if (!p)
3733 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3734 *p = '\0';
3735 if (vfs_object_exist(conn, directory, NULL))
3736 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3737 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3739 error = map_nt_error_from_unix(errno);
3740 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3741 nt_errstr(error), directory,newname));
3743 return error;
3746 if (!rcdest && bad_path_dest) {
3747 if (ms_has_wild(last_component_dest))
3748 return NT_STATUS_OBJECT_NAME_INVALID;
3749 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3752 error = can_rename(directory,conn,&sbuf1);
3754 if (!NT_STATUS_IS_OK(error)) {
3755 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3756 nt_errstr(error), directory,newname));
3757 return error;
3761 * If the src and dest names are identical - including case,
3762 * don't do the rename, just return success.
3765 if (strcsequal(directory, newname)) {
3766 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3767 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
3768 return NT_STATUS_OK;
3771 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
3772 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
3773 directory,newname));
3774 return NT_STATUS_OBJECT_NAME_COLLISION;
3777 if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
3778 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
3779 directory,newname));
3780 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3781 return NT_STATUS_OK;
3784 if (errno == ENOTDIR || errno == EISDIR)
3785 error = NT_STATUS_OBJECT_NAME_COLLISION;
3786 else
3787 error = map_nt_error_from_unix(errno);
3789 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3790 nt_errstr(error), directory,newname));
3792 return error;
3793 } else {
3795 * Wildcards - process each file that matches.
3797 void *dirptr = NULL;
3798 const char *dname;
3799 pstring destname;
3801 if (check_name(directory,conn))
3802 dirptr = OpenDir(conn, directory, True);
3804 if (dirptr) {
3805 error = NT_STATUS_NO_SUCH_FILE;
3806 /* Was error = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */
3808 if (strequal(mask,"????????.???"))
3809 pstrcpy(mask,"*");
3811 while ((dname = ReadDirName(dirptr))) {
3812 pstring fname;
3813 BOOL sysdir_entry = False;
3815 pstrcpy(fname,dname);
3817 /* Quick check for "." and ".." */
3818 if (fname[0] == '.') {
3819 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
3820 if (attrs & aDIR) {
3821 sysdir_entry = True;
3822 } else {
3823 continue;
3828 if(!mask_match(fname, mask, case_sensitive))
3829 continue;
3831 if (sysdir_entry) {
3832 error = NT_STATUS_OBJECT_NAME_INVALID;
3833 continue;
3836 error = NT_STATUS_ACCESS_DENIED;
3837 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3838 if (!vfs_object_exist(conn, fname, &sbuf1)) {
3839 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3840 DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
3841 continue;
3843 error = can_rename(fname,conn,&sbuf1);
3844 if (!NT_STATUS_IS_OK(error)) {
3845 DEBUG(6,("rename %s refused\n", fname));
3846 continue;
3848 pstrcpy(destname,newname);
3850 if (!resolve_wildcards(fname,destname)) {
3851 DEBUG(6,("resolve_wildcards %s %s failed\n",
3852 fname, destname));
3853 continue;
3856 if (!replace_if_exists &&
3857 vfs_file_exist(conn,destname, NULL)) {
3858 DEBUG(6,("file_exist %s\n", destname));
3859 error = NT_STATUS_OBJECT_NAME_COLLISION;
3860 continue;
3863 if (!SMB_VFS_RENAME(conn,fname,destname)) {
3864 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3865 count++;
3866 error = NT_STATUS_OK;
3868 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3870 CloseDir(dirptr);
3873 if (!NT_STATUS_EQUAL(error,NT_STATUS_NO_SUCH_FILE)) {
3874 if (!rcdest && bad_path_dest) {
3875 if (ms_has_wild(last_component_dest))
3876 return NT_STATUS_OBJECT_NAME_INVALID;
3877 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3882 if (count == 0 && NT_STATUS_IS_OK(error)) {
3883 error = map_nt_error_from_unix(errno);
3886 return error;
3889 /****************************************************************************
3890 Reply to a mv.
3891 ****************************************************************************/
3893 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
3894 int dum_buffsize)
3896 int outsize = 0;
3897 pstring name;
3898 pstring newname;
3899 char *p;
3900 uint16 attrs = SVAL(inbuf,smb_vwv0);
3901 NTSTATUS status;
3903 START_PROFILE(SMBmv);
3905 p = smb_buf(inbuf) + 1;
3906 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status);
3907 if (!NT_STATUS_IS_OK(status)) {
3908 END_PROFILE(SMBmv);
3909 return ERROR_NT(status);
3911 p++;
3912 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status);
3913 if (!NT_STATUS_IS_OK(status)) {
3914 END_PROFILE(SMBmv);
3915 return ERROR_NT(status);
3918 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3919 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3921 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3923 status = rename_internals(conn, name, newname, attrs, False);
3924 if (!NT_STATUS_IS_OK(status)) {
3925 END_PROFILE(SMBmv);
3926 return ERROR_NT(status);
3930 * Win2k needs a changenotify request response before it will
3931 * update after a rename..
3933 process_pending_change_notify_queue((time_t)0);
3934 outsize = set_message(outbuf,0,0,True);
3936 END_PROFILE(SMBmv);
3937 return(outsize);
3940 /*******************************************************************
3941 Copy a file as part of a reply_copy.
3942 ******************************************************************/
3944 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3945 int count,BOOL target_is_directory, int *err_ret)
3947 int Access,action;
3948 SMB_STRUCT_STAT src_sbuf, sbuf2;
3949 SMB_OFF_T ret=-1;
3950 files_struct *fsp1,*fsp2;
3951 pstring dest;
3953 *err_ret = 0;
3955 pstrcpy(dest,dest1);
3956 if (target_is_directory) {
3957 char *p = strrchr_m(src,'/');
3958 if (p)
3959 p++;
3960 else
3961 p = src;
3962 pstrcat(dest,"/");
3963 pstrcat(dest,p);
3966 if (!vfs_file_exist(conn,src,&src_sbuf))
3967 return(False);
3969 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
3970 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
3972 if (!fsp1)
3973 return(False);
3975 if (!target_is_directory && count)
3976 ofun = FILE_EXISTS_OPEN;
3978 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1)
3979 ZERO_STRUCTP(&sbuf2);
3981 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
3982 ofun,src_sbuf.st_mode,0,&Access,&action);
3984 if (!fsp2) {
3985 close_file(fsp1,False);
3986 return(False);
3989 if ((ofun&3) == 1) {
3990 if(SMB_VFS_LSEEK(fsp2,fsp2->fd,0,SEEK_END) == -1) {
3991 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
3993 * Stop the copy from occurring.
3995 ret = -1;
3996 src_sbuf.st_size = 0;
4000 if (src_sbuf.st_size)
4001 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
4003 close_file(fsp1,False);
4005 /* Ensure the modtime is set correctly on the destination file. */
4006 fsp2->pending_modtime = src_sbuf.st_mtime;
4009 * As we are opening fsp1 read-only we only expect
4010 * an error on close on fsp2 if we are out of space.
4011 * Thus we don't look at the error return from the
4012 * close of fsp1.
4014 *err_ret = close_file(fsp2,False);
4016 return(ret == (SMB_OFF_T)src_sbuf.st_size);
4019 /****************************************************************************
4020 Reply to a file copy.
4021 ****************************************************************************/
4023 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4025 int outsize = 0;
4026 pstring name;
4027 pstring directory;
4028 pstring mask,newname;
4029 char *p;
4030 int count=0;
4031 int error = ERRnoaccess;
4032 int err = 0;
4033 BOOL has_wild;
4034 BOOL exists=False;
4035 int tid2 = SVAL(inbuf,smb_vwv0);
4036 int ofun = SVAL(inbuf,smb_vwv1);
4037 int flags = SVAL(inbuf,smb_vwv2);
4038 BOOL target_is_directory=False;
4039 BOOL bad_path1 = False;
4040 BOOL bad_path2 = False;
4041 BOOL rc = True;
4042 SMB_STRUCT_STAT sbuf1, sbuf2;
4043 NTSTATUS status;
4045 START_PROFILE(SMBcopy);
4047 *directory = *mask = 0;
4049 p = smb_buf(inbuf);
4050 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status);
4051 if (!NT_STATUS_IS_OK(status)) {
4052 END_PROFILE(SMBcopy);
4053 return ERROR_NT(status);
4055 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status);
4056 if (!NT_STATUS_IS_OK(status)) {
4057 END_PROFILE(SMBcopy);
4058 return ERROR_NT(status);
4061 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
4063 if (tid2 != conn->cnum) {
4064 /* can't currently handle inter share copies XXXX */
4065 DEBUG(3,("Rejecting inter-share copy\n"));
4066 END_PROFILE(SMBcopy);
4067 return ERROR_DOS(ERRSRV,ERRinvdevice);
4070 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
4071 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4073 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
4074 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
4076 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
4078 if ((flags&1) && target_is_directory) {
4079 END_PROFILE(SMBcopy);
4080 return ERROR_DOS(ERRDOS,ERRbadfile);
4083 if ((flags&2) && !target_is_directory) {
4084 END_PROFILE(SMBcopy);
4085 return ERROR_DOS(ERRDOS,ERRbadpath);
4088 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
4089 /* wants a tree copy! XXXX */
4090 DEBUG(3,("Rejecting tree copy\n"));
4091 END_PROFILE(SMBcopy);
4092 return ERROR_DOS(ERRSRV,ERRerror);
4095 p = strrchr_m(name,'/');
4096 if (!p) {
4097 pstrcpy(directory,"./");
4098 pstrcpy(mask,name);
4099 } else {
4100 *p = 0;
4101 pstrcpy(directory,name);
4102 pstrcpy(mask,p+1);
4106 * We should only check the mangled cache
4107 * here if unix_convert failed. This means
4108 * that the path in 'mask' doesn't exist
4109 * on the file system and so we need to look
4110 * for a possible mangle. This patch from
4111 * Tine Smukavec <valentin.smukavec@hermes.si>.
4114 if (!rc && mangle_is_mangled(mask))
4115 mangle_check_cache( mask );
4117 has_wild = ms_has_wild(mask);
4119 if (!has_wild) {
4120 pstrcat(directory,"/");
4121 pstrcat(directory,mask);
4122 if (resolve_wildcards(directory,newname) &&
4123 copy_file(directory,newname,conn,ofun, count,target_is_directory,&err))
4124 count++;
4125 if(!count && err) {
4126 errno = err;
4127 END_PROFILE(SMBcopy);
4128 return(UNIXERROR(ERRHRD,ERRgeneral));
4130 if (!count) {
4131 exists = vfs_file_exist(conn,directory,NULL);
4133 } else {
4134 void *dirptr = NULL;
4135 const char *dname;
4136 pstring destname;
4138 if (check_name(directory,conn))
4139 dirptr = OpenDir(conn, directory, True);
4141 if (dirptr) {
4142 error = ERRbadfile;
4144 if (strequal(mask,"????????.???"))
4145 pstrcpy(mask,"*");
4147 while ((dname = ReadDirName(dirptr))) {
4148 pstring fname;
4149 pstrcpy(fname,dname);
4151 if(!mask_match(fname, mask, case_sensitive))
4152 continue;
4154 error = ERRnoaccess;
4155 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
4156 pstrcpy(destname,newname);
4157 if (resolve_wildcards(fname,destname) &&
4158 copy_file(fname,destname,conn,ofun,
4159 count,target_is_directory,&err))
4160 count++;
4161 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
4163 CloseDir(dirptr);
4167 if (count == 0) {
4168 if(err) {
4169 /* Error on close... */
4170 errno = err;
4171 END_PROFILE(SMBcopy);
4172 return(UNIXERROR(ERRHRD,ERRgeneral));
4175 if (exists) {
4176 END_PROFILE(SMBcopy);
4177 return ERROR_DOS(ERRDOS,error);
4178 } else {
4179 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
4180 unix_ERR_class = ERRDOS;
4181 unix_ERR_code = ERRbadpath;
4183 END_PROFILE(SMBcopy);
4184 return(UNIXERROR(ERRDOS,error));
4188 outsize = set_message(outbuf,1,0,True);
4189 SSVAL(outbuf,smb_vwv0,count);
4191 END_PROFILE(SMBcopy);
4192 return(outsize);
4195 /****************************************************************************
4196 Reply to a setdir.
4197 ****************************************************************************/
4199 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4201 int snum;
4202 int outsize = 0;
4203 BOOL ok = False;
4204 pstring newdir;
4205 NTSTATUS status;
4207 START_PROFILE(pathworks_setdir);
4209 snum = SNUM(conn);
4210 if (!CAN_SETDIR(snum)) {
4211 END_PROFILE(pathworks_setdir);
4212 return ERROR_DOS(ERRDOS,ERRnoaccess);
4215 srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status);
4216 if (!NT_STATUS_IS_OK(status)) {
4217 END_PROFILE(pathworks_setdir);
4218 return ERROR_NT(status);
4221 if (strlen(newdir) == 0) {
4222 ok = True;
4223 } else {
4224 ok = vfs_directory_exist(conn,newdir,NULL);
4225 if (ok)
4226 string_set(&conn->connectpath,newdir);
4229 if (!ok) {
4230 END_PROFILE(pathworks_setdir);
4231 return ERROR_DOS(ERRDOS,ERRbadpath);
4234 outsize = set_message(outbuf,0,0,True);
4235 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
4237 DEBUG(3,("setdir %s\n", newdir));
4239 END_PROFILE(pathworks_setdir);
4240 return(outsize);
4243 /****************************************************************************
4244 Get a lock pid, dealing with large count requests.
4245 ****************************************************************************/
4247 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
4249 if(!large_file_format)
4250 return SVAL(data,SMB_LPID_OFFSET(data_offset));
4251 else
4252 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
4255 /****************************************************************************
4256 Get a lock count, dealing with large count requests.
4257 ****************************************************************************/
4259 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4261 SMB_BIG_UINT count = 0;
4263 if(!large_file_format) {
4264 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4265 } else {
4267 #if defined(HAVE_LONGLONG)
4268 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4269 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4270 #else /* HAVE_LONGLONG */
4273 * NT4.x seems to be broken in that it sends large file (64 bit)
4274 * lockingX calls even if the CAP_LARGE_FILES was *not*
4275 * negotiated. For boxes without large unsigned ints truncate the
4276 * lock count by dropping the top 32 bits.
4279 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4280 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4281 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4282 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4283 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4286 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4287 #endif /* HAVE_LONGLONG */
4290 return count;
4293 #if !defined(HAVE_LONGLONG)
4294 /****************************************************************************
4295 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
4296 ****************************************************************************/
4298 static uint32 map_lock_offset(uint32 high, uint32 low)
4300 unsigned int i;
4301 uint32 mask = 0;
4302 uint32 highcopy = high;
4305 * Try and find out how many significant bits there are in high.
4308 for(i = 0; highcopy; i++)
4309 highcopy >>= 1;
4312 * We use 31 bits not 32 here as POSIX
4313 * lock offsets may not be negative.
4316 mask = (~0) << (31 - i);
4318 if(low & mask)
4319 return 0; /* Fail. */
4321 high <<= (31 - i);
4323 return (high|low);
4325 #endif /* !defined(HAVE_LONGLONG) */
4327 /****************************************************************************
4328 Get a lock offset, dealing with large offset requests.
4329 ****************************************************************************/
4331 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4333 SMB_BIG_UINT offset = 0;
4335 *err = False;
4337 if(!large_file_format) {
4338 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4339 } else {
4341 #if defined(HAVE_LONGLONG)
4342 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4343 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4344 #else /* HAVE_LONGLONG */
4347 * NT4.x seems to be broken in that it sends large file (64 bit)
4348 * lockingX calls even if the CAP_LARGE_FILES was *not*
4349 * negotiated. For boxes without large unsigned ints mangle the
4350 * lock offset by mapping the top 32 bits onto the lower 32.
4353 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4354 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4355 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4356 uint32 new_low = 0;
4358 if((new_low = map_lock_offset(high, low)) == 0) {
4359 *err = True;
4360 return (SMB_BIG_UINT)-1;
4363 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4364 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4365 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4366 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4369 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4370 #endif /* HAVE_LONGLONG */
4373 return offset;
4376 /****************************************************************************
4377 Reply to a lockingX request.
4378 ****************************************************************************/
4380 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4382 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4383 unsigned char locktype = CVAL(inbuf,smb_vwv3);
4384 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4385 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4386 uint16 num_locks = SVAL(inbuf,smb_vwv7);
4387 SMB_BIG_UINT count = 0, offset = 0;
4388 uint16 lock_pid;
4389 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4390 int i;
4391 char *data;
4392 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4393 BOOL err;
4394 BOOL my_lock_ctx = False;
4395 NTSTATUS status;
4397 START_PROFILE(SMBlockingX);
4399 CHECK_FSP(fsp,conn);
4401 data = smb_buf(inbuf);
4403 if (locktype & (LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_CHANGE_LOCKTYPE)) {
4404 /* we don't support these - and CANCEL_LOCK makes w2k
4405 and XP reboot so I don't really want to be
4406 compatible! (tridge) */
4407 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
4410 /* Check if this is an oplock break on a file
4411 we have granted an oplock on.
4413 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
4414 /* Client can insist on breaking to none. */
4415 BOOL break_to_none = (oplocklevel == 0);
4417 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4418 (unsigned int)oplocklevel, fsp->fnum ));
4421 * Make sure we have granted an exclusive or batch oplock on this file.
4424 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
4425 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4426 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4428 /* if this is a pure oplock break request then don't send a reply */
4429 if (num_locks == 0 && num_ulocks == 0) {
4430 END_PROFILE(SMBlockingX);
4431 return -1;
4432 } else {
4433 END_PROFILE(SMBlockingX);
4434 return ERROR_DOS(ERRDOS,ERRlock);
4438 if (remove_oplock(fsp, break_to_none) == False) {
4439 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4440 fsp->fsp_name ));
4443 /* if this is a pure oplock break request then don't send a reply */
4444 if (num_locks == 0 && num_ulocks == 0) {
4445 /* Sanity check - ensure a pure oplock break is not a
4446 chained request. */
4447 if(CVAL(inbuf,smb_vwv0) != 0xff)
4448 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4449 (unsigned int)CVAL(inbuf,smb_vwv0) ));
4450 END_PROFILE(SMBlockingX);
4451 return -1;
4456 * We do this check *after* we have checked this is not a oplock break
4457 * response message. JRA.
4460 release_level_2_oplocks_on_change(fsp);
4462 /* Data now points at the beginning of the list
4463 of smb_unlkrng structs */
4464 for(i = 0; i < (int)num_ulocks; i++) {
4465 lock_pid = get_lock_pid( data, i, large_file_format);
4466 count = get_lock_count( data, i, large_file_format);
4467 offset = get_lock_offset( data, i, large_file_format, &err);
4470 * There is no error code marked "stupid client bug".... :-).
4472 if(err) {
4473 END_PROFILE(SMBlockingX);
4474 return ERROR_DOS(ERRDOS,ERRnoaccess);
4477 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4478 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4480 status = do_unlock(fsp,conn,lock_pid,count,offset);
4481 if (NT_STATUS_V(status)) {
4482 END_PROFILE(SMBlockingX);
4483 return ERROR_NT(status);
4487 /* Setup the timeout in seconds. */
4489 lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000);
4491 /* Now do any requested locks */
4492 data += ((large_file_format ? 20 : 10)*num_ulocks);
4494 /* Data now points at the beginning of the list
4495 of smb_lkrng structs */
4497 for(i = 0; i < (int)num_locks; i++) {
4498 lock_pid = get_lock_pid( data, i, large_file_format);
4499 count = get_lock_count( data, i, large_file_format);
4500 offset = get_lock_offset( data, i, large_file_format, &err);
4503 * There is no error code marked "stupid client bug".... :-).
4505 if(err) {
4506 END_PROFILE(SMBlockingX);
4507 return ERROR_DOS(ERRDOS,ERRnoaccess);
4510 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
4511 (double)offset, (double)count, (unsigned int)lock_pid,
4512 fsp->fsp_name, (int)lock_timeout ));
4514 status = do_lock_spin(fsp,conn,lock_pid, count,offset,
4515 ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &my_lock_ctx);
4516 if (NT_STATUS_V(status)) {
4518 * Interesting fact found by IFSTEST /t LockOverlappedTest...
4519 * Even if it's our own lock context, we need to wait here as
4520 * there may be an unlock on the way.
4521 * So I removed a "&& !my_lock_ctx" from the following
4522 * if statement. JRA.
4524 if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
4526 * A blocking lock was requested. Package up
4527 * this smb into a queued request and push it
4528 * onto the blocking lock queue.
4530 if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) {
4531 END_PROFILE(SMBlockingX);
4532 return -1;
4535 break;
4539 /* If any of the above locks failed, then we must unlock
4540 all of the previous locks (X/Open spec). */
4541 if (i != num_locks && num_locks != 0) {
4543 * Ensure we don't do a remove on the lock that just failed,
4544 * as under POSIX rules, if we have a lock already there, we
4545 * will delete it (and we shouldn't) .....
4547 for(i--; i >= 0; i--) {
4548 lock_pid = get_lock_pid( data, i, large_file_format);
4549 count = get_lock_count( data, i, large_file_format);
4550 offset = get_lock_offset( data, i, large_file_format, &err);
4553 * There is no error code marked "stupid client bug".... :-).
4555 if(err) {
4556 END_PROFILE(SMBlockingX);
4557 return ERROR_DOS(ERRDOS,ERRnoaccess);
4560 do_unlock(fsp,conn,lock_pid,count,offset);
4562 END_PROFILE(SMBlockingX);
4563 return ERROR_NT(status);
4566 set_message(outbuf,2,0,True);
4568 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4569 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4571 END_PROFILE(SMBlockingX);
4572 return chain_reply(inbuf,outbuf,length,bufsize);
4575 /****************************************************************************
4576 Reply to a SMBreadbmpx (read block multiplex) request.
4577 ****************************************************************************/
4579 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4581 ssize_t nread = -1;
4582 ssize_t total_read;
4583 char *data;
4584 SMB_OFF_T startpos;
4585 int outsize;
4586 size_t maxcount;
4587 int max_per_packet;
4588 size_t tcount;
4589 int pad;
4590 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4591 START_PROFILE(SMBreadBmpx);
4593 /* this function doesn't seem to work - disable by default */
4594 if (!lp_readbmpx()) {
4595 END_PROFILE(SMBreadBmpx);
4596 return ERROR_DOS(ERRSRV,ERRuseSTD);
4599 outsize = set_message(outbuf,8,0,True);
4601 CHECK_FSP(fsp,conn);
4602 CHECK_READ(fsp);
4604 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
4605 maxcount = SVAL(inbuf,smb_vwv3);
4607 data = smb_buf(outbuf);
4608 pad = ((long)data)%4;
4609 if (pad)
4610 pad = 4 - pad;
4611 data += pad;
4613 max_per_packet = bufsize-(outsize+pad);
4614 tcount = maxcount;
4615 total_read = 0;
4617 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
4618 END_PROFILE(SMBreadBmpx);
4619 return ERROR_DOS(ERRDOS,ERRlock);
4622 do {
4623 size_t N = MIN(max_per_packet,tcount-total_read);
4625 nread = read_file(fsp,data,startpos,N);
4627 if (nread <= 0)
4628 nread = 0;
4630 if (nread < (ssize_t)N)
4631 tcount = total_read + nread;
4633 set_message(outbuf,8,nread,False);
4634 SIVAL(outbuf,smb_vwv0,startpos);
4635 SSVAL(outbuf,smb_vwv2,tcount);
4636 SSVAL(outbuf,smb_vwv6,nread);
4637 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4639 if (!send_smb(smbd_server_fd(),outbuf))
4640 exit_server("reply_readbmpx: send_smb failed.");
4642 total_read += nread;
4643 startpos += nread;
4644 } while (total_read < (ssize_t)tcount);
4646 END_PROFILE(SMBreadBmpx);
4647 return(-1);
4650 /****************************************************************************
4651 Reply to a SMBsetattrE.
4652 ****************************************************************************/
4654 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4656 struct utimbuf unix_times;
4657 int outsize = 0;
4658 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4659 START_PROFILE(SMBsetattrE);
4661 outsize = set_message(outbuf,0,0,True);
4663 if(!fsp || (fsp->conn != conn)) {
4664 END_PROFILE(SMBgetattrE);
4665 return ERROR_DOS(ERRDOS,ERRbadfid);
4669 * Convert the DOS times into unix times. Ignore create
4670 * time as UNIX can't set this.
4673 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4674 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4677 * Patch from Ray Frush <frush@engr.colostate.edu>
4678 * Sometimes times are sent as zero - ignore them.
4681 if ((unix_times.actime == 0) && (unix_times.modtime == 0)) {
4682 /* Ignore request */
4683 if( DEBUGLVL( 3 ) ) {
4684 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4685 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4687 END_PROFILE(SMBsetattrE);
4688 return(outsize);
4689 } else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) {
4690 /* set modify time = to access time if modify time was 0 */
4691 unix_times.modtime = unix_times.actime;
4694 /* Set the date on this file */
4695 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4696 END_PROFILE(SMBsetattrE);
4697 return ERROR_DOS(ERRDOS,ERRnoaccess);
4700 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4701 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4703 END_PROFILE(SMBsetattrE);
4704 return(outsize);
4708 /* Back from the dead for OS/2..... JRA. */
4710 /****************************************************************************
4711 Reply to a SMBwritebmpx (write block multiplex primary) request.
4712 ****************************************************************************/
4714 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4716 size_t numtowrite;
4717 ssize_t nwritten = -1;
4718 int outsize = 0;
4719 SMB_OFF_T startpos;
4720 size_t tcount;
4721 BOOL write_through;
4722 int smb_doff;
4723 char *data;
4724 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4725 START_PROFILE(SMBwriteBmpx);
4727 CHECK_FSP(fsp,conn);
4728 CHECK_WRITE(fsp);
4729 CHECK_ERROR(fsp);
4731 tcount = SVAL(inbuf,smb_vwv1);
4732 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
4733 write_through = BITSETW(inbuf+smb_vwv7,0);
4734 numtowrite = SVAL(inbuf,smb_vwv10);
4735 smb_doff = SVAL(inbuf,smb_vwv11);
4737 data = smb_base(inbuf) + smb_doff;
4739 /* If this fails we need to send an SMBwriteC response,
4740 not an SMBwritebmpx - set this up now so we don't forget */
4741 SCVAL(outbuf,smb_com,SMBwritec);
4743 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK,False)) {
4744 END_PROFILE(SMBwriteBmpx);
4745 return(ERROR_DOS(ERRDOS,ERRlock));
4748 nwritten = write_file(fsp,data,startpos,numtowrite);
4750 if(lp_syncalways(SNUM(conn)) || write_through)
4751 sync_file(conn,fsp);
4753 if(nwritten < (ssize_t)numtowrite) {
4754 END_PROFILE(SMBwriteBmpx);
4755 return(UNIXERROR(ERRHRD,ERRdiskfull));
4758 /* If the maximum to be written to this file
4759 is greater than what we just wrote then set
4760 up a secondary struct to be attached to this
4761 fd, we will use this to cache error messages etc. */
4763 if((ssize_t)tcount > nwritten) {
4764 write_bmpx_struct *wbms;
4765 if(fsp->wbmpx_ptr != NULL)
4766 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4767 else
4768 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
4769 if(!wbms) {
4770 DEBUG(0,("Out of memory in reply_readmpx\n"));
4771 END_PROFILE(SMBwriteBmpx);
4772 return(ERROR_DOS(ERRSRV,ERRnoresource));
4774 wbms->wr_mode = write_through;
4775 wbms->wr_discard = False; /* No errors yet */
4776 wbms->wr_total_written = nwritten;
4777 wbms->wr_errclass = 0;
4778 wbms->wr_error = 0;
4779 fsp->wbmpx_ptr = wbms;
4782 /* We are returning successfully, set the message type back to
4783 SMBwritebmpx */
4784 SCVAL(outbuf,smb_com,SMBwriteBmpx);
4786 outsize = set_message(outbuf,1,0,True);
4788 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
4790 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4791 fsp->fnum, (int)numtowrite, (int)nwritten ) );
4793 if (write_through && tcount==nwritten) {
4794 /* We need to send both a primary and a secondary response */
4795 smb_setlen(outbuf,outsize - 4);
4796 if (!send_smb(smbd_server_fd(),outbuf))
4797 exit_server("reply_writebmpx: send_smb failed.");
4799 /* Now the secondary */
4800 outsize = set_message(outbuf,1,0,True);
4801 SCVAL(outbuf,smb_com,SMBwritec);
4802 SSVAL(outbuf,smb_vwv0,nwritten);
4805 END_PROFILE(SMBwriteBmpx);
4806 return(outsize);
4809 /****************************************************************************
4810 Reply to a SMBwritebs (write block multiplex secondary) request.
4811 ****************************************************************************/
4813 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4815 size_t numtowrite;
4816 ssize_t nwritten = -1;
4817 int outsize = 0;
4818 SMB_OFF_T startpos;
4819 size_t tcount;
4820 BOOL write_through;
4821 int smb_doff;
4822 char *data;
4823 write_bmpx_struct *wbms;
4824 BOOL send_response = False;
4825 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4826 START_PROFILE(SMBwriteBs);
4828 CHECK_FSP(fsp,conn);
4829 CHECK_WRITE(fsp);
4831 tcount = SVAL(inbuf,smb_vwv1);
4832 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
4833 numtowrite = SVAL(inbuf,smb_vwv6);
4834 smb_doff = SVAL(inbuf,smb_vwv7);
4836 data = smb_base(inbuf) + smb_doff;
4838 /* We need to send an SMBwriteC response, not an SMBwritebs */
4839 SCVAL(outbuf,smb_com,SMBwritec);
4841 /* This fd should have an auxiliary struct attached,
4842 check that it does */
4843 wbms = fsp->wbmpx_ptr;
4844 if(!wbms) {
4845 END_PROFILE(SMBwriteBs);
4846 return(-1);
4849 /* If write through is set we can return errors, else we must cache them */
4850 write_through = wbms->wr_mode;
4852 /* Check for an earlier error */
4853 if(wbms->wr_discard) {
4854 END_PROFILE(SMBwriteBs);
4855 return -1; /* Just discard the packet */
4858 nwritten = write_file(fsp,data,startpos,numtowrite);
4860 if(lp_syncalways(SNUM(conn)) || write_through)
4861 sync_file(conn,fsp);
4863 if (nwritten < (ssize_t)numtowrite) {
4864 if(write_through) {
4865 /* We are returning an error - we can delete the aux struct */
4866 if (wbms)
4867 free((char *)wbms);
4868 fsp->wbmpx_ptr = NULL;
4869 END_PROFILE(SMBwriteBs);
4870 return(ERROR_DOS(ERRHRD,ERRdiskfull));
4872 END_PROFILE(SMBwriteBs);
4873 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4876 /* Increment the total written, if this matches tcount
4877 we can discard the auxiliary struct (hurrah !) and return a writeC */
4878 wbms->wr_total_written += nwritten;
4879 if(wbms->wr_total_written >= tcount) {
4880 if (write_through) {
4881 outsize = set_message(outbuf,1,0,True);
4882 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
4883 send_response = True;
4886 free((char *)wbms);
4887 fsp->wbmpx_ptr = NULL;
4890 if(send_response) {
4891 END_PROFILE(SMBwriteBs);
4892 return(outsize);
4895 END_PROFILE(SMBwriteBs);
4896 return(-1);
4899 /****************************************************************************
4900 Reply to a SMBgetattrE.
4901 ****************************************************************************/
4903 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4905 SMB_STRUCT_STAT sbuf;
4906 int outsize = 0;
4907 int mode;
4908 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4909 START_PROFILE(SMBgetattrE);
4911 outsize = set_message(outbuf,11,0,True);
4913 if(!fsp || (fsp->conn != conn)) {
4914 END_PROFILE(SMBgetattrE);
4915 return ERROR_DOS(ERRDOS,ERRbadfid);
4918 /* Do an fstat on this file */
4919 if(fsp_stat(fsp, &sbuf)) {
4920 END_PROFILE(SMBgetattrE);
4921 return(UNIXERROR(ERRDOS,ERRnoaccess));
4924 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4927 * Convert the times into dos times. Set create
4928 * date to be last modify date as UNIX doesn't save
4929 * this.
4932 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4933 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4934 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4936 if (mode & aDIR) {
4937 SIVAL(outbuf,smb_vwv6,0);
4938 SIVAL(outbuf,smb_vwv8,0);
4939 } else {
4940 uint32 allocation_size = get_allocation_size(fsp, &sbuf);
4941 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4942 SIVAL(outbuf,smb_vwv8,allocation_size);
4944 SSVAL(outbuf,smb_vwv10, mode);
4946 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
4948 END_PROFILE(SMBgetattrE);
4949 return(outsize);