Add function next_mb_char_size() that returns a size_t of the number of
[Samba/gebeck_regimport.git] / source3 / smbd / reply.c
blobc470d15645da811bf6c4c082227364ca59cc5ffa
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 BOOL is_unix_charset_unsafe;
38 extern int global_oplock_break;
39 unsigned int smb_echo_count = 0;
41 extern BOOL global_encrypted_passwords_negotiated;
43 /****************************************************************************
44 Ensure we check the path in *exactly* the same way as W2K.
45 We're assuming here that '/' is not the second byte in any multibyte char
46 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
47 set.
48 ****************************************************************************/
50 NTSTATUS check_path_syntax(pstring destname, const pstring srcname)
52 char *d = destname;
53 const char *s = srcname;
54 NTSTATUS ret = NT_STATUS_OK;
56 while (*s) {
57 if (IS_DIRECTORY_SEP(*s)) {
59 * Safe to assume is not the second part of a mb char as this is handled below.
61 /* Eat multiple '/' or '\\' */
62 while (IS_DIRECTORY_SEP(*s)) {
63 s++;
65 if ((d != destname) && (*s != '\0')) {
66 /* We only care about non-leading or trailing '/' or '\\' */
67 *d++ = '/';
69 } else if ((s[0] == '.') && (s[1] == '.') && (IS_DIRECTORY_SEP(s[2]) || s[2] == '\0')) {
70 /* Uh oh - "../" or "..\\" or "..\0" ! */
73 * No mb char starts with '.' so we're safe checking the directory separator here.
76 /* If we just added a '/', delete it. */
78 if ((d > destname) && (*(d-1) == '/')) {
79 *(d-1) = '\0';
80 if (d == (destname + 1)) {
81 d--;
82 } else {
83 d -= 2;
86 /* Are we at the start ? Can't go back further if so. */
87 if (d == destname) {
88 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
90 /* Go back one level... */
91 while (d > destname) {
92 if (*d == '/')
93 break;
94 d--;
96 s += 3;
97 } else if ((s[0] == '.') && IS_DIRECTORY_SEP(s[1])) {
100 * No mb char starts with '.' so we're safe checking the directory separator here.
103 /* "./" or ".\\" fails with a different error depending on where it is... */
105 if (s == srcname) {
106 ret = NT_STATUS_OBJECT_NAME_INVALID;
107 } else {
108 if (s[2] == '\0') {
109 return NT_STATUS_INVALID_PARAMETER;
111 ret = NT_STATUS_OBJECT_PATH_NOT_FOUND;
113 s++;
114 } else {
115 /* Activate this codepath only if we know that Unix charset may contain unsafe '\\' */
116 if ((is_unix_charset_unsafe == True) && ((*s & 0x80) && IS_DIRECTORY_SEP(s[1]))) {
118 * Potential mb char with second char a directory separator.
119 * All the encodings we care about are 2 byte only, so do a
120 * conversion to unicode. If the one byte char converts then
121 * it really is a directory separator following. Otherwise if
122 * the two byte character converts (and it should or our assumption
123 * about character sets is broken and we return an error) then copy both
124 * bytes as it's a MB character, not a directory separator.
127 uint16 ucs2_val;
129 if (convert_string(CH_UNIX, CH_UCS2, s, 1, &ucs2_val, 2, False) == 2) {
131 } else if (convert_string(CH_UNIX, CH_UCS2, s, 2, &ucs2_val, 2, False) == 2) {
132 *d++ = *s++;
133 } else {
134 DEBUG(0,("check_path_syntax: directory separator assumptions invalid !\n"));
135 return NT_STATUS_INVALID_PARAMETER;
138 /* Just copy the char (or the second byte of the mb char). */
139 *d++ = *s++;
142 *d = '\0';
143 return ret;
146 /****************************************************************************
147 Pull a string and check the path - provide for error return.
148 ****************************************************************************/
150 size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags, NTSTATUS *err)
152 pstring tmppath;
153 char *tmppath_ptr = tmppath;
154 size_t ret;
155 #ifdef DEVELOPER
156 SMB_ASSERT(dest_len == sizeof(pstring));
157 #endif
159 if (src_len == 0) {
160 ret = srvstr_pull_buf( inbuf, tmppath_ptr, src, dest_len, flags);
161 } else {
162 ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags);
164 *err = check_path_syntax(dest, tmppath);
165 return ret;
168 /****************************************************************************
169 Reply to a special message.
170 ****************************************************************************/
172 int reply_special(char *inbuf,char *outbuf)
174 int outsize = 4;
175 int msg_type = CVAL(inbuf,0);
176 int msg_flags = CVAL(inbuf,1);
177 fstring name1,name2;
178 char name_type = 0;
180 static BOOL already_got_session = False;
182 *name1 = *name2 = 0;
184 memset(outbuf,'\0',smb_size);
186 smb_setlen(outbuf,0);
188 switch (msg_type) {
189 case 0x81: /* session request */
191 if (already_got_session) {
192 exit_server("multiple session request not permitted");
195 SCVAL(outbuf,0,0x82);
196 SCVAL(outbuf,3,0);
197 if (name_len(inbuf+4) > 50 ||
198 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
199 DEBUG(0,("Invalid name length in session request\n"));
200 return(0);
202 name_extract(inbuf,4,name1);
203 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
204 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
205 name1,name2));
207 set_local_machine_name(name1, True);
208 set_remote_machine_name(name2, True);
210 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
211 get_local_machine_name(), get_remote_machine_name(),
212 name_type));
214 if (name_type == 'R') {
215 /* We are being asked for a pathworks session ---
216 no thanks! */
217 SCVAL(outbuf, 0,0x83);
218 break;
221 /* only add the client's machine name to the list
222 of possibly valid usernames if we are operating
223 in share mode security */
224 if (lp_security() == SEC_SHARE) {
225 add_session_user(get_remote_machine_name());
228 reload_services(True);
229 reopen_logs();
231 claim_connection(NULL,"",0,True,FLAG_MSG_GENERAL|FLAG_MSG_SMBD);
233 already_got_session = True;
234 break;
236 case 0x89: /* session keepalive request
237 (some old clients produce this?) */
238 SCVAL(outbuf,0,SMBkeepalive);
239 SCVAL(outbuf,3,0);
240 break;
242 case 0x82: /* positive session response */
243 case 0x83: /* negative session response */
244 case 0x84: /* retarget session response */
245 DEBUG(0,("Unexpected session response\n"));
246 break;
248 case SMBkeepalive: /* session keepalive */
249 default:
250 return(0);
253 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
254 msg_type, msg_flags));
256 return(outsize);
259 /****************************************************************************
260 Reply to a tcon.
261 ****************************************************************************/
263 int reply_tcon(connection_struct *conn,
264 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
266 const char *service;
267 pstring service_buf;
268 pstring password;
269 pstring dev;
270 int outsize = 0;
271 uint16 vuid = SVAL(inbuf,smb_uid);
272 int pwlen=0;
273 NTSTATUS nt_status;
274 char *p;
275 DATA_BLOB password_blob;
277 START_PROFILE(SMBtcon);
279 *service_buf = *password = *dev = 0;
281 p = smb_buf(inbuf)+1;
282 p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service_buf), STR_TERMINATE) + 1;
283 pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1;
284 p += pwlen;
285 p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1;
287 p = strrchr_m(service_buf,'\\');
288 if (p) {
289 service = p+1;
290 } else {
291 service = service_buf;
294 password_blob = data_blob(password, pwlen+1);
296 conn = make_connection(service,password_blob,dev,vuid,&nt_status);
298 data_blob_clear_free(&password_blob);
300 if (!conn) {
301 END_PROFILE(SMBtcon);
302 return ERROR_NT(nt_status);
305 outsize = set_message(outbuf,2,0,True);
306 SSVAL(outbuf,smb_vwv0,max_recv);
307 SSVAL(outbuf,smb_vwv1,conn->cnum);
308 SSVAL(outbuf,smb_tid,conn->cnum);
310 DEBUG(3,("tcon service=%s cnum=%d\n",
311 service, conn->cnum));
313 END_PROFILE(SMBtcon);
314 return(outsize);
317 /****************************************************************************
318 Reply to a tcon and X.
319 ****************************************************************************/
321 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
323 fstring service;
324 DATA_BLOB password;
326 /* what the cleint thinks the device is */
327 fstring client_devicetype;
328 /* what the server tells the client the share represents */
329 const char *server_devicetype;
330 NTSTATUS nt_status;
331 uint16 vuid = SVAL(inbuf,smb_uid);
332 int passlen = SVAL(inbuf,smb_vwv3);
333 pstring path;
334 char *p, *q;
335 extern BOOL global_encrypted_passwords_negotiated;
337 START_PROFILE(SMBtconX);
339 *service = *client_devicetype = 0;
341 /* we might have to close an old one */
342 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
343 close_cnum(conn,vuid);
346 if (passlen > MAX_PASS_LEN) {
347 return ERROR_DOS(ERRDOS,ERRbuftoosmall);
350 if (global_encrypted_passwords_negotiated) {
351 password = data_blob(smb_buf(inbuf),passlen);
352 } else {
353 password = data_blob(smb_buf(inbuf),passlen+1);
354 /* Ensure correct termination */
355 password.data[passlen]=0;
358 p = smb_buf(inbuf) + passlen;
359 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
362 * the service name can be either: \\server\share
363 * or share directly like on the DELL PowerVault 705
365 if (*path=='\\') {
366 q = strchr_m(path+2,'\\');
367 if (!q) {
368 END_PROFILE(SMBtconX);
369 return(ERROR_DOS(ERRDOS,ERRnosuchshare));
371 fstrcpy(service,q+1);
373 else
374 fstrcpy(service,path);
376 p += srvstr_pull(inbuf, client_devicetype, p, sizeof(client_devicetype), 6, STR_ASCII);
378 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
380 conn = make_connection(service,password,client_devicetype,vuid,&nt_status);
382 data_blob_clear_free(&password);
384 if (!conn) {
385 END_PROFILE(SMBtconX);
386 return ERROR_NT(nt_status);
389 if ( IS_IPC(conn) )
390 server_devicetype = "IPC";
391 else if ( IS_PRINT(conn) )
392 server_devicetype = "LPT1:";
393 else
394 server_devicetype = "A:";
396 if (Protocol < PROTOCOL_NT1) {
397 set_message(outbuf,2,0,True);
398 p = smb_buf(outbuf);
399 p += srvstr_push(outbuf, p, server_devicetype, -1,
400 STR_TERMINATE|STR_ASCII);
401 set_message_end(outbuf,p);
402 } else {
403 /* NT sets the fstype of IPC$ to the null string */
404 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
406 set_message(outbuf,3,0,True);
408 p = smb_buf(outbuf);
409 p += srvstr_push(outbuf, p, server_devicetype, -1,
410 STR_TERMINATE|STR_ASCII);
411 p += srvstr_push(outbuf, p, fstype, -1,
412 STR_TERMINATE);
414 set_message_end(outbuf,p);
416 /* what does setting this bit do? It is set by NT4 and
417 may affect the ability to autorun mounted cdroms */
418 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
419 (lp_csc_policy(SNUM(conn)) << 2));
421 init_dfsroot(conn, inbuf, outbuf);
425 DEBUG(3,("tconX service=%s \n",
426 service));
428 /* set the incoming and outgoing tid to the just created one */
429 SSVAL(inbuf,smb_tid,conn->cnum);
430 SSVAL(outbuf,smb_tid,conn->cnum);
432 END_PROFILE(SMBtconX);
433 return chain_reply(inbuf,outbuf,length,bufsize);
436 /****************************************************************************
437 Reply to an unknown type.
438 ****************************************************************************/
440 int reply_unknown(char *inbuf,char *outbuf)
442 int type;
443 type = CVAL(inbuf,smb_com);
445 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
446 smb_fn_name(type), type, type));
448 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
451 /****************************************************************************
452 Reply to an ioctl.
453 ****************************************************************************/
455 int reply_ioctl(connection_struct *conn,
456 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
458 uint16 device = SVAL(inbuf,smb_vwv1);
459 uint16 function = SVAL(inbuf,smb_vwv2);
460 uint32 ioctl_code = (device << 16) + function;
461 int replysize, outsize;
462 char *p;
463 START_PROFILE(SMBioctl);
465 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
467 switch (ioctl_code) {
468 case IOCTL_QUERY_JOB_INFO:
469 replysize = 32;
470 break;
471 default:
472 END_PROFILE(SMBioctl);
473 return(ERROR_DOS(ERRSRV,ERRnosupport));
476 outsize = set_message(outbuf,8,replysize+1,True);
477 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
478 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
479 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
480 p = smb_buf(outbuf) + 1; /* Allow for alignment */
482 switch (ioctl_code) {
483 case IOCTL_QUERY_JOB_INFO:
485 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
486 if (!fsp) {
487 END_PROFILE(SMBioctl);
488 return(UNIXERROR(ERRDOS,ERRbadfid));
490 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
491 srvstr_push(outbuf, p+2, global_myname(), 15, STR_TERMINATE|STR_ASCII);
492 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
493 break;
497 END_PROFILE(SMBioctl);
498 return outsize;
501 /****************************************************************************
502 Reply to a chkpth.
503 ****************************************************************************/
505 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
507 int outsize = 0;
508 int mode;
509 pstring name;
510 BOOL ok = False;
511 BOOL bad_path = False;
512 SMB_STRUCT_STAT sbuf;
513 NTSTATUS status;
515 START_PROFILE(SMBchkpth);
517 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
518 if (!NT_STATUS_IS_OK(status)) {
519 END_PROFILE(SMBchkpth);
520 return ERROR_NT(status);
523 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
525 unix_convert(name,conn,0,&bad_path,&sbuf);
527 mode = SVAL(inbuf,smb_vwv0);
529 if (check_name(name,conn)) {
530 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,name,&sbuf) == 0)
531 if (!(ok = S_ISDIR(sbuf.st_mode))) {
532 END_PROFILE(SMBchkpth);
533 return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath);
537 if (!ok) {
538 /* We special case this - as when a Windows machine
539 is parsing a path is steps through the components
540 one at a time - if a component fails it expects
541 ERRbadpath, not ERRbadfile.
543 if(errno == ENOENT) {
545 * Windows returns different error codes if
546 * the parent directory is valid but not the
547 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
548 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
549 * if the path is invalid.
551 if (bad_path) {
552 END_PROFILE(SMBchkpth);
553 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
554 } else {
555 END_PROFILE(SMBchkpth);
556 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
558 } else if (errno == ENOTDIR) {
559 END_PROFILE(SMBchkpth);
560 return ERROR_NT(NT_STATUS_NOT_A_DIRECTORY);
563 END_PROFILE(SMBchkpth);
564 return(UNIXERROR(ERRDOS,ERRbadpath));
567 outsize = set_message(outbuf,0,0,True);
569 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
571 END_PROFILE(SMBchkpth);
572 return(outsize);
575 /****************************************************************************
576 Reply to a getatr.
577 ****************************************************************************/
579 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
581 pstring fname;
582 int outsize = 0;
583 SMB_STRUCT_STAT sbuf;
584 BOOL ok = False;
585 int mode=0;
586 SMB_OFF_T size=0;
587 time_t mtime=0;
588 BOOL bad_path = False;
589 char *p;
590 NTSTATUS status;
592 START_PROFILE(SMBgetatr);
594 p = smb_buf(inbuf) + 1;
595 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
596 if (!NT_STATUS_IS_OK(status)) {
597 END_PROFILE(SMBgetatr);
598 return ERROR_NT(status);
601 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
603 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
604 under WfWg - weird! */
605 if (! (*fname)) {
606 mode = aHIDDEN | aDIR;
607 if (!CAN_WRITE(conn))
608 mode |= aRONLY;
609 size = 0;
610 mtime = 0;
611 ok = True;
612 } else {
613 unix_convert(fname,conn,0,&bad_path,&sbuf);
614 if (check_name(fname,conn)) {
615 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,fname,&sbuf) == 0) {
616 mode = dos_mode(conn,fname,&sbuf);
617 size = sbuf.st_size;
618 mtime = sbuf.st_mtime;
619 if (mode & aDIR)
620 size = 0;
621 ok = True;
622 } else {
623 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
628 if (!ok) {
629 END_PROFILE(SMBgetatr);
630 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadfile);
633 outsize = set_message(outbuf,10,0,True);
635 SSVAL(outbuf,smb_vwv0,mode);
636 if(lp_dos_filetime_resolution(SNUM(conn)) )
637 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
638 else
639 put_dos_date3(outbuf,smb_vwv1,mtime);
640 SIVAL(outbuf,smb_vwv3,(uint32)size);
642 if (Protocol >= PROTOCOL_NT1)
643 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
645 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
647 END_PROFILE(SMBgetatr);
648 return(outsize);
651 /****************************************************************************
652 Reply to a setatr.
653 ****************************************************************************/
655 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
657 pstring fname;
658 int outsize = 0;
659 BOOL ok=False;
660 int mode;
661 time_t mtime;
662 SMB_STRUCT_STAT sbuf;
663 BOOL bad_path = False;
664 char *p;
665 NTSTATUS status;
667 START_PROFILE(SMBsetatr);
669 p = smb_buf(inbuf) + 1;
670 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
671 if (!NT_STATUS_IS_OK(status)) {
672 END_PROFILE(SMBsetatr);
673 return ERROR_NT(status);
676 unix_convert(fname,conn,0,&bad_path,&sbuf);
678 mode = SVAL(inbuf,smb_vwv0);
679 mtime = make_unix_date3(inbuf+smb_vwv1);
681 if (mode != FILE_ATTRIBUTE_NORMAL) {
682 if (VALID_STAT_OF_DIR(sbuf))
683 mode |= aDIR;
684 else
685 mode &= ~aDIR;
687 if (check_name(fname,conn))
688 ok = (file_chmod(conn,fname,mode,NULL) == 0);
689 } else {
690 ok = True;
693 if (ok)
694 ok = set_filetime(conn,fname,mtime);
696 if (!ok) {
697 END_PROFILE(SMBsetatr);
698 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
701 outsize = set_message(outbuf,0,0,True);
703 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
705 END_PROFILE(SMBsetatr);
706 return(outsize);
709 /****************************************************************************
710 Reply to a dskattr.
711 ****************************************************************************/
713 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
715 int outsize = 0;
716 SMB_BIG_UINT dfree,dsize,bsize;
717 START_PROFILE(SMBdskattr);
719 SMB_VFS_DISK_FREE(conn,".",True,&bsize,&dfree,&dsize);
721 outsize = set_message(outbuf,5,0,True);
723 if (Protocol <= PROTOCOL_LANMAN2) {
724 double total_space, free_space;
725 /* we need to scale this to a number that DOS6 can handle. We
726 use floating point so we can handle large drives on systems
727 that don't have 64 bit integers
729 we end up displaying a maximum of 2G to DOS systems
731 total_space = dsize * (double)bsize;
732 free_space = dfree * (double)bsize;
734 dsize = (total_space+63*512) / (64*512);
735 dfree = (free_space+63*512) / (64*512);
737 if (dsize > 0xFFFF) dsize = 0xFFFF;
738 if (dfree > 0xFFFF) dfree = 0xFFFF;
740 SSVAL(outbuf,smb_vwv0,dsize);
741 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
742 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
743 SSVAL(outbuf,smb_vwv3,dfree);
744 } else {
745 SSVAL(outbuf,smb_vwv0,dsize);
746 SSVAL(outbuf,smb_vwv1,bsize/512);
747 SSVAL(outbuf,smb_vwv2,512);
748 SSVAL(outbuf,smb_vwv3,dfree);
751 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
753 END_PROFILE(SMBdskattr);
754 return(outsize);
757 /****************************************************************************
758 Reply to a search.
759 Can be called from SMBsearch, SMBffirst or SMBfunique.
760 ****************************************************************************/
762 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
764 pstring mask;
765 pstring directory;
766 pstring fname;
767 SMB_OFF_T size;
768 int mode;
769 time_t date;
770 int dirtype;
771 int outsize = 0;
772 unsigned int numentries = 0;
773 unsigned int maxentries = 0;
774 BOOL finished = False;
775 char *p;
776 BOOL ok = False;
777 int status_len;
778 pstring path;
779 char status[21];
780 int dptr_num= -1;
781 BOOL check_descend = False;
782 BOOL expect_close = False;
783 BOOL can_open = True;
784 BOOL bad_path = False;
785 NTSTATUS nt_status;
786 START_PROFILE(SMBsearch);
788 *mask = *directory = *fname = 0;
790 /* If we were called as SMBffirst then we must expect close. */
791 if(CVAL(inbuf,smb_com) == SMBffirst)
792 expect_close = True;
794 outsize = set_message(outbuf,1,3,True);
795 maxentries = SVAL(inbuf,smb_vwv0);
796 dirtype = SVAL(inbuf,smb_vwv1);
797 p = smb_buf(inbuf) + 1;
798 p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &nt_status);
799 if (!NT_STATUS_IS_OK(nt_status)) {
800 END_PROFILE(SMBsearch);
801 return ERROR_NT(nt_status);
803 p++;
804 status_len = SVAL(p, 0);
805 p += 2;
807 /* dirtype &= ~aDIR; */
809 if (status_len == 0) {
810 SMB_STRUCT_STAT sbuf;
811 pstring dir2;
813 pstrcpy(directory,path);
814 pstrcpy(dir2,path);
815 unix_convert(directory,conn,0,&bad_path,&sbuf);
816 unix_format(dir2);
818 if (!check_name(directory,conn))
819 can_open = False;
821 p = strrchr_m(dir2,'/');
822 if (p == NULL) {
823 pstrcpy(mask,dir2);
824 *dir2 = 0;
825 } else {
826 *p = 0;
827 pstrcpy(mask,p+1);
830 p = strrchr_m(directory,'/');
831 if (!p)
832 *directory = 0;
833 else
834 *p = 0;
836 if (strlen(directory) == 0)
837 pstrcpy(directory,".");
838 memset((char *)status,'\0',21);
839 SCVAL(status,0,(dirtype & 0x1F));
840 } else {
841 int status_dirtype;
843 memcpy(status,p,21);
844 status_dirtype = CVAL(status,0) & 0x1F;
845 if (status_dirtype != (dirtype & 0x1F))
846 dirtype = status_dirtype;
848 conn->dirptr = dptr_fetch(status+12,&dptr_num);
849 if (!conn->dirptr)
850 goto SearchEmpty;
851 string_set(&conn->dirpath,dptr_path(dptr_num));
852 pstrcpy(mask, dptr_wcard(dptr_num));
855 if (can_open) {
856 p = smb_buf(outbuf) + 3;
857 ok = True;
859 if (status_len == 0) {
860 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
861 if (dptr_num < 0) {
862 if(dptr_num == -2) {
863 END_PROFILE(SMBsearch);
864 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnofids);
866 END_PROFILE(SMBsearch);
867 return ERROR_DOS(ERRDOS,ERRnofids);
869 dptr_set_wcard(dptr_num, strdup(mask));
870 dptr_set_attr(dptr_num, dirtype);
871 } else {
872 dirtype = dptr_attr(dptr_num);
875 DEBUG(4,("dptr_num is %d\n",dptr_num));
877 if (ok) {
878 if ((dirtype&0x1F) == aVOLID) {
879 memcpy(p,status,21);
880 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
881 dptr_fill(p+12,dptr_num);
882 if (dptr_zero(p+12) && (status_len==0))
883 numentries = 1;
884 else
885 numentries = 0;
886 p += DIR_STRUCT_SIZE;
887 } else {
888 unsigned int i;
889 maxentries = MIN(maxentries, ((BUFFER_SIZE - (p - outbuf))/DIR_STRUCT_SIZE));
891 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
892 conn->dirpath,lp_dontdescend(SNUM(conn))));
893 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
894 check_descend = True;
896 for (i=numentries;(i<maxentries) && !finished;i++) {
897 finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
898 if (!finished) {
899 memcpy(p,status,21);
900 make_dir_struct(p,mask,fname,size,mode,date);
901 dptr_fill(p+12,dptr_num);
902 numentries++;
904 p += DIR_STRUCT_SIZE;
907 } /* if (ok ) */
911 SearchEmpty:
913 /* If we were called as SMBffirst with smb_search_id == NULL
914 and no entries were found then return error and close dirptr
915 (X/Open spec) */
917 if(ok && expect_close && numentries == 0 && status_len == 0) {
918 if (Protocol < PROTOCOL_NT1) {
919 SCVAL(outbuf,smb_rcls,ERRDOS);
920 SSVAL(outbuf,smb_err,ERRnofiles);
922 /* Also close the dptr - we know it's gone */
923 dptr_close(&dptr_num);
924 } else if (numentries == 0 || !ok) {
925 if (Protocol < PROTOCOL_NT1) {
926 SCVAL(outbuf,smb_rcls,ERRDOS);
927 SSVAL(outbuf,smb_err,ERRnofiles);
929 dptr_close(&dptr_num);
932 /* If we were called as SMBfunique, then we can close the dirptr now ! */
933 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
934 dptr_close(&dptr_num);
936 SSVAL(outbuf,smb_vwv0,numentries);
937 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
938 SCVAL(smb_buf(outbuf),0,5);
939 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
941 if (Protocol >= PROTOCOL_NT1)
942 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
944 outsize += DIR_STRUCT_SIZE*numentries;
945 smb_setlen(outbuf,outsize - 4);
947 if ((! *directory) && dptr_path(dptr_num))
948 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
950 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
951 smb_fn_name(CVAL(inbuf,smb_com)),
952 mask, directory, dirtype, numentries, maxentries ) );
954 END_PROFILE(SMBsearch);
955 return(outsize);
958 /****************************************************************************
959 Reply to a fclose (stop directory search).
960 ****************************************************************************/
962 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
964 int outsize = 0;
965 int status_len;
966 pstring path;
967 char status[21];
968 int dptr_num= -2;
969 char *p;
970 NTSTATUS err;
972 START_PROFILE(SMBfclose);
974 outsize = set_message(outbuf,1,0,True);
975 p = smb_buf(inbuf) + 1;
976 p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err);
977 if (!NT_STATUS_IS_OK(err)) {
978 END_PROFILE(SMBfclose);
979 return ERROR_NT(err);
981 p++;
982 status_len = SVAL(p,0);
983 p += 2;
985 if (status_len == 0) {
986 END_PROFILE(SMBfclose);
987 return ERROR_DOS(ERRSRV,ERRsrverror);
990 memcpy(status,p,21);
992 if(dptr_fetch(status+12,&dptr_num)) {
993 /* Close the dptr - we know it's gone */
994 dptr_close(&dptr_num);
997 SSVAL(outbuf,smb_vwv0,0);
999 DEBUG(3,("search close\n"));
1001 END_PROFILE(SMBfclose);
1002 return(outsize);
1005 /****************************************************************************
1006 Reply to an open.
1007 ****************************************************************************/
1009 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1011 pstring fname;
1012 int outsize = 0;
1013 int fmode=0;
1014 int share_mode;
1015 SMB_OFF_T size = 0;
1016 time_t mtime=0;
1017 mode_t unixmode;
1018 int rmode=0;
1019 SMB_STRUCT_STAT sbuf;
1020 BOOL bad_path = False;
1021 files_struct *fsp;
1022 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1023 NTSTATUS status;
1024 START_PROFILE(SMBopen);
1026 share_mode = SVAL(inbuf,smb_vwv0);
1028 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
1029 if (!NT_STATUS_IS_OK(status)) {
1030 END_PROFILE(SMBopen);
1031 return ERROR_NT(status);
1034 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1036 unix_convert(fname,conn,0,&bad_path,&sbuf);
1038 unixmode = unix_mode(conn,aARCH,fname);
1040 fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1041 unixmode, oplock_request,&rmode,NULL);
1043 if (!fsp) {
1044 END_PROFILE(SMBopen);
1045 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1048 size = sbuf.st_size;
1049 fmode = dos_mode(conn,fname,&sbuf);
1050 mtime = sbuf.st_mtime;
1052 if (fmode & aDIR) {
1053 DEBUG(3,("attempt to open a directory %s\n",fname));
1054 close_file(fsp,False);
1055 END_PROFILE(SMBopen);
1056 return ERROR_DOS(ERRDOS,ERRnoaccess);
1059 outsize = set_message(outbuf,7,0,True);
1060 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1061 SSVAL(outbuf,smb_vwv1,fmode);
1062 if(lp_dos_filetime_resolution(SNUM(conn)) )
1063 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1064 else
1065 put_dos_date3(outbuf,smb_vwv2,mtime);
1066 SIVAL(outbuf,smb_vwv4,(uint32)size);
1067 SSVAL(outbuf,smb_vwv6,rmode);
1069 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1070 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1072 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1073 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1074 END_PROFILE(SMBopen);
1075 return(outsize);
1078 /****************************************************************************
1079 Reply to an open and X.
1080 ****************************************************************************/
1082 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1084 pstring fname;
1085 int smb_mode = SVAL(inbuf,smb_vwv3);
1086 int smb_attr = SVAL(inbuf,smb_vwv5);
1087 /* Breakout the oplock request bits so we can set the
1088 reply bits separately. */
1089 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1090 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1091 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1092 #if 0
1093 int open_flags = SVAL(inbuf,smb_vwv2);
1094 int smb_sattr = SVAL(inbuf,smb_vwv4);
1095 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1096 #endif
1097 int smb_ofun = SVAL(inbuf,smb_vwv8);
1098 mode_t unixmode;
1099 SMB_OFF_T size=0;
1100 int fmode=0,mtime=0,rmode=0;
1101 SMB_STRUCT_STAT sbuf;
1102 int smb_action = 0;
1103 BOOL bad_path = False;
1104 files_struct *fsp;
1105 NTSTATUS status;
1106 START_PROFILE(SMBopenX);
1108 /* If it's an IPC, pass off the pipe handler. */
1109 if (IS_IPC(conn)) {
1110 if (lp_nt_pipe_support()) {
1111 END_PROFILE(SMBopenX);
1112 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1113 } else {
1114 END_PROFILE(SMBopenX);
1115 return ERROR_DOS(ERRSRV,ERRaccess);
1119 /* XXXX we need to handle passed times, sattr and flags */
1120 srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status);
1121 if (!NT_STATUS_IS_OK(status)) {
1122 END_PROFILE(SMBopenX);
1123 return ERROR_NT(status);
1126 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1128 unix_convert(fname,conn,0,&bad_path,&sbuf);
1130 unixmode = unix_mode(conn,smb_attr | aARCH, fname);
1132 fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,unixmode,
1133 oplock_request, &rmode,&smb_action);
1135 if (!fsp) {
1136 END_PROFILE(SMBopenX);
1137 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1140 size = sbuf.st_size;
1141 fmode = dos_mode(conn,fname,&sbuf);
1142 mtime = sbuf.st_mtime;
1143 if (fmode & aDIR) {
1144 close_file(fsp,False);
1145 END_PROFILE(SMBopenX);
1146 return ERROR_DOS(ERRDOS,ERRnoaccess);
1149 /* If the caller set the extended oplock request bit
1150 and we granted one (by whatever means) - set the
1151 correct bit for extended oplock reply.
1154 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn)))
1155 smb_action |= EXTENDED_OPLOCK_GRANTED;
1157 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1158 smb_action |= EXTENDED_OPLOCK_GRANTED;
1160 /* If the caller set the core oplock request bit
1161 and we granted one (by whatever means) - set the
1162 correct bit for core oplock reply.
1165 if (core_oplock_request && lp_fake_oplocks(SNUM(conn)))
1166 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1168 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1169 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1171 set_message(outbuf,15,0,True);
1172 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1173 SSVAL(outbuf,smb_vwv3,fmode);
1174 if(lp_dos_filetime_resolution(SNUM(conn)) )
1175 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1176 else
1177 put_dos_date3(outbuf,smb_vwv4,mtime);
1178 SIVAL(outbuf,smb_vwv6,(uint32)size);
1179 SSVAL(outbuf,smb_vwv8,rmode);
1180 SSVAL(outbuf,smb_vwv11,smb_action);
1182 END_PROFILE(SMBopenX);
1183 return chain_reply(inbuf,outbuf,length,bufsize);
1186 /****************************************************************************
1187 Reply to a SMBulogoffX.
1188 ****************************************************************************/
1190 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1192 uint16 vuid = SVAL(inbuf,smb_uid);
1193 user_struct *vuser = get_valid_user_struct(vuid);
1194 START_PROFILE(SMBulogoffX);
1196 if(vuser == 0)
1197 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1199 /* in user level security we are supposed to close any files
1200 open by this user */
1201 if ((vuser != 0) && (lp_security() != SEC_SHARE))
1202 file_close_user(vuid);
1204 invalidate_vuid(vuid);
1206 set_message(outbuf,2,0,True);
1208 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1210 END_PROFILE(SMBulogoffX);
1211 return chain_reply(inbuf,outbuf,length,bufsize);
1214 /****************************************************************************
1215 Reply to a mknew or a create.
1216 ****************************************************************************/
1218 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1220 pstring fname;
1221 int com;
1222 int outsize = 0;
1223 int createmode;
1224 mode_t unixmode;
1225 int ofun = 0;
1226 BOOL bad_path = False;
1227 files_struct *fsp;
1228 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1229 SMB_STRUCT_STAT sbuf;
1230 NTSTATUS status;
1231 START_PROFILE(SMBcreate);
1233 com = SVAL(inbuf,smb_com);
1235 createmode = SVAL(inbuf,smb_vwv0);
1236 srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status);
1237 if (!NT_STATUS_IS_OK(status)) {
1238 END_PROFILE(SMBcreate);
1239 return ERROR_NT(status);
1242 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1244 unix_convert(fname,conn,0,&bad_path,&sbuf);
1246 if (createmode & aVOLID)
1247 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1249 unixmode = unix_mode(conn,createmode,fname);
1251 if(com == SMBmknew) {
1252 /* We should fail if file exists. */
1253 ofun = FILE_CREATE_IF_NOT_EXIST;
1254 } else {
1255 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1256 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1259 /* Open file in dos compatibility share mode. */
1260 fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1261 ofun, unixmode, oplock_request, NULL, NULL);
1263 if (!fsp) {
1264 END_PROFILE(SMBcreate);
1265 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1268 outsize = set_message(outbuf,1,0,True);
1269 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1271 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1272 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1274 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1275 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1277 DEBUG( 2, ( "new file %s\n", fname ) );
1278 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n", fname, fsp->fd, createmode, (int)unixmode ) );
1280 END_PROFILE(SMBcreate);
1281 return(outsize);
1284 /****************************************************************************
1285 Reply to a create temporary file.
1286 ****************************************************************************/
1288 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1290 pstring fname;
1291 int outsize = 0;
1292 int createmode;
1293 mode_t unixmode;
1294 BOOL bad_path = False;
1295 files_struct *fsp;
1296 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1297 int tmpfd;
1298 SMB_STRUCT_STAT sbuf;
1299 char *p, *s;
1300 NTSTATUS status;
1302 START_PROFILE(SMBctemp);
1304 createmode = SVAL(inbuf,smb_vwv0);
1305 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
1306 if (!NT_STATUS_IS_OK(status)) {
1307 END_PROFILE(SMBctemp);
1308 return ERROR_NT(status);
1310 pstrcat(fname,"\\TMXXXXXX");
1312 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1314 unix_convert(fname,conn,0,&bad_path,&sbuf);
1316 unixmode = unix_mode(conn,createmode,fname);
1318 tmpfd = smb_mkstemp(fname);
1319 if (tmpfd == -1) {
1320 END_PROFILE(SMBctemp);
1321 return(UNIXERROR(ERRDOS,ERRnoaccess));
1324 SMB_VFS_STAT(conn,fname,&sbuf);
1326 /* Open file in dos compatibility share mode. */
1327 /* We should fail if file does not exist. */
1328 fsp = open_file_shared(conn,fname,&sbuf,
1329 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1330 FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
1331 unixmode, oplock_request, NULL, NULL);
1333 /* close fd from smb_mkstemp() */
1334 close(tmpfd);
1336 if (!fsp) {
1337 END_PROFILE(SMBctemp);
1338 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1341 outsize = set_message(outbuf,1,0,True);
1342 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1344 /* the returned filename is relative to the directory */
1345 s = strrchr_m(fname, '/');
1346 if (!s)
1347 s = fname;
1348 else
1349 s++;
1351 p = smb_buf(outbuf);
1352 SSVALS(p, 0, -1); /* what is this? not in spec */
1353 SSVAL(p, 2, strlen(s));
1354 p += 4;
1355 p += srvstr_push(outbuf, p, s, -1, STR_ASCII);
1356 outsize = set_message_end(outbuf, p);
1358 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1359 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1361 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1362 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1364 DEBUG( 2, ( "created temp file %s\n", fname ) );
1365 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1366 fname, fsp->fd, createmode, (int)unixmode ) );
1368 END_PROFILE(SMBctemp);
1369 return(outsize);
1372 /*******************************************************************
1373 Check if a user is allowed to rename a file.
1374 ********************************************************************/
1376 static NTSTATUS can_rename(char *fname,connection_struct *conn, SMB_STRUCT_STAT *pst)
1378 int smb_action;
1379 int access_mode;
1380 files_struct *fsp;
1382 if (!CAN_WRITE(conn))
1383 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1385 if (S_ISDIR(pst->st_mode))
1386 return NT_STATUS_OK;
1388 /* We need a better way to return NT status codes from open... */
1389 unix_ERR_class = 0;
1390 unix_ERR_code = 0;
1392 fsp = open_file_shared1(conn, fname, pst, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1393 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
1395 if (!fsp) {
1396 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1397 if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1398 ret = NT_STATUS_SHARING_VIOLATION;
1399 unix_ERR_class = 0;
1400 unix_ERR_code = 0;
1401 unix_ERR_ntstatus = NT_STATUS_OK;
1402 return ret;
1404 close_file(fsp,False);
1405 return NT_STATUS_OK;
1408 /*******************************************************************
1409 Check if a user is allowed to delete a file.
1410 ********************************************************************/
1412 static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype, BOOL bad_path)
1414 SMB_STRUCT_STAT sbuf;
1415 int fmode;
1416 int smb_action;
1417 int access_mode;
1418 files_struct *fsp;
1420 DEBUG(10,("can_delete: %s, dirtype = %d\n",
1421 fname, dirtype ));
1423 if (!CAN_WRITE(conn))
1424 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1426 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
1427 if(errno == ENOENT) {
1428 if (bad_path)
1429 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1430 else
1431 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1433 return map_nt_error_from_unix(errno);
1436 fmode = dos_mode(conn,fname,&sbuf);
1438 /* Can't delete a directory. */
1439 if (fmode & aDIR)
1440 return NT_STATUS_FILE_IS_A_DIRECTORY;
1441 #if 0 /* JRATEST */
1442 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
1443 return NT_STATUS_OBJECT_NAME_INVALID;
1444 #endif /* JRATEST */
1446 if (!lp_delete_readonly(SNUM(conn))) {
1447 if (fmode & aRONLY)
1448 return NT_STATUS_CANNOT_DELETE;
1450 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1451 return NT_STATUS_NO_SUCH_FILE;
1453 /* We need a better way to return NT status codes from open... */
1454 unix_ERR_class = 0;
1455 unix_ERR_code = 0;
1457 fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1458 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
1460 if (!fsp) {
1461 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1462 if (!NT_STATUS_IS_OK(unix_ERR_ntstatus))
1463 ret = unix_ERR_ntstatus;
1464 else if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1465 ret = NT_STATUS_SHARING_VIOLATION;
1466 unix_ERR_class = 0;
1467 unix_ERR_code = 0;
1468 unix_ERR_ntstatus = NT_STATUS_OK;
1469 return ret;
1471 close_file(fsp,False);
1472 return NT_STATUS_OK;
1475 /****************************************************************************
1476 The guts of the unlink command, split out so it may be called by the NT SMB
1477 code.
1478 ****************************************************************************/
1480 NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
1482 pstring directory;
1483 pstring mask;
1484 char *p;
1485 int count=0;
1486 NTSTATUS error = NT_STATUS_OK;
1487 BOOL has_wild;
1488 BOOL bad_path = False;
1489 BOOL rc = True;
1490 SMB_STRUCT_STAT sbuf;
1492 *directory = *mask = 0;
1494 /* We must check for wildcards in the name given
1495 * directly by the client - before any unmangling.
1496 * This prevents an unmangling of a UNIX name containing
1497 * a DOS wildcard like '*' or '?' from unmangling into
1498 * a wildcard delete which was not intended.
1499 * FIX for #226. JRA.
1502 has_wild = ms_has_wild(name);
1504 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1506 p = strrchr_m(name,'/');
1507 if (!p) {
1508 pstrcpy(directory,".");
1509 pstrcpy(mask,name);
1510 } else {
1511 *p = 0;
1512 pstrcpy(directory,name);
1513 pstrcpy(mask,p+1);
1517 * We should only check the mangled cache
1518 * here if unix_convert failed. This means
1519 * that the path in 'mask' doesn't exist
1520 * on the file system and so we need to look
1521 * for a possible mangle. This patch from
1522 * Tine Smukavec <valentin.smukavec@hermes.si>.
1525 if (!rc && mangle_is_mangled(mask))
1526 mangle_check_cache( mask );
1528 if (!has_wild) {
1529 pstrcat(directory,"/");
1530 pstrcat(directory,mask);
1531 error = can_delete(directory,conn,dirtype,bad_path);
1532 if (!NT_STATUS_IS_OK(error))
1533 return error;
1535 if (SMB_VFS_UNLINK(conn,directory) == 0) {
1536 count++;
1538 } else {
1539 void *dirptr = NULL;
1540 const char *dname;
1542 if (check_name(directory,conn))
1543 dirptr = OpenDir(conn, directory, True);
1545 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1546 the pattern matches against the long name, otherwise the short name
1547 We don't implement this yet XXXX
1550 if (dirptr) {
1551 error = NT_STATUS_NO_SUCH_FILE;
1553 if (strequal(mask,"????????.???"))
1554 pstrcpy(mask,"*");
1556 while ((dname = ReadDirName(dirptr))) {
1557 pstring fname;
1558 BOOL sys_direntry = False;
1559 pstrcpy(fname,dname);
1561 /* Quick check for "." and ".." */
1562 if (fname[0] == '.') {
1563 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
1564 if ((dirtype & aDIR)) {
1565 sys_direntry = True;
1566 } else {
1567 continue;
1572 if(!mask_match(fname, mask, case_sensitive))
1573 continue;
1575 if (sys_direntry) {
1576 error = NT_STATUS_OBJECT_NAME_INVALID;
1577 continue;
1580 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1581 error = can_delete(fname,conn,dirtype,bad_path);
1582 if (!NT_STATUS_IS_OK(error))
1583 continue;
1584 if (SMB_VFS_UNLINK(conn,fname) == 0)
1585 count++;
1586 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
1588 CloseDir(dirptr);
1592 if (count == 0 && NT_STATUS_IS_OK(error)) {
1593 error = map_nt_error_from_unix(errno);
1596 return error;
1599 /****************************************************************************
1600 Reply to a unlink
1601 ****************************************************************************/
1603 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
1604 int dum_buffsize)
1606 int outsize = 0;
1607 pstring name;
1608 int dirtype;
1609 NTSTATUS status;
1610 START_PROFILE(SMBunlink);
1612 dirtype = SVAL(inbuf,smb_vwv0);
1614 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
1615 if (!NT_STATUS_IS_OK(status)) {
1616 END_PROFILE(SMBunlink);
1617 return ERROR_NT(status);
1620 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1622 DEBUG(3,("reply_unlink : %s\n",name));
1624 status = unlink_internals(conn, dirtype, name);
1625 if (!NT_STATUS_IS_OK(status))
1626 return ERROR_NT(status);
1629 * Win2k needs a changenotify request response before it will
1630 * update after a rename..
1632 process_pending_change_notify_queue((time_t)0);
1634 outsize = set_message(outbuf,0,0,True);
1636 END_PROFILE(SMBunlink);
1637 return outsize;
1640 /****************************************************************************
1641 Fail for readbraw.
1642 ****************************************************************************/
1644 void fail_readraw(void)
1646 pstring errstr;
1647 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
1648 strerror(errno) );
1649 exit_server(errstr);
1652 /****************************************************************************
1653 Use sendfile in readbraw.
1654 ****************************************************************************/
1656 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
1657 ssize_t mincount, char *outbuf)
1659 ssize_t ret=0;
1661 #if defined(WITH_SENDFILE)
1663 * We can only use sendfile on a non-chained packet and on a file
1664 * that is exclusively oplocked. reply_readbraw has already checked the length.
1667 if ((nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) &&
1668 EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && lp_use_sendfile(SNUM(conn)) ) {
1669 DATA_BLOB header;
1671 _smb_setlen(outbuf,nread);
1672 header.data = outbuf;
1673 header.length = 4;
1674 header.free = NULL;
1676 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) {
1678 * Special hack for broken Linux with no 64 bit clean sendfile. If we
1679 * return ENOSYS then pretend we just got a normal read.
1681 if (errno == ENOSYS)
1682 goto normal_read;
1684 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
1685 fsp->fsp_name, strerror(errno) ));
1686 exit_server("send_file_readbraw sendfile failed");
1691 normal_read:
1692 #endif
1694 if (nread > 0) {
1695 ret = read_file(fsp,outbuf+4,startpos,nread);
1696 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1697 if (ret < mincount)
1698 ret = 0;
1699 #else
1700 if (ret < nread)
1701 ret = 0;
1702 #endif
1705 _smb_setlen(outbuf,ret);
1706 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
1707 fail_readraw();
1710 /****************************************************************************
1711 Reply to a readbraw (core+ protocol).
1712 ****************************************************************************/
1714 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
1716 extern struct current_user current_user;
1717 ssize_t maxcount,mincount;
1718 size_t nread = 0;
1719 SMB_OFF_T startpos;
1720 char *header = outbuf;
1721 files_struct *fsp;
1722 START_PROFILE(SMBreadbraw);
1724 if (srv_is_signing_active()) {
1725 exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
1729 * Special check if an oplock break has been issued
1730 * and the readraw request croses on the wire, we must
1731 * return a zero length response here.
1734 if(global_oplock_break) {
1735 _smb_setlen(header,0);
1736 if (write_data(smbd_server_fd(),header,4) != 4)
1737 fail_readraw();
1738 DEBUG(5,("readbraw - oplock break finished\n"));
1739 END_PROFILE(SMBreadbraw);
1740 return -1;
1743 fsp = file_fsp(inbuf,smb_vwv0);
1745 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1747 * fsp could be NULL here so use the value from the packet. JRA.
1749 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
1750 _smb_setlen(header,0);
1751 if (write_data(smbd_server_fd(),header,4) != 4)
1752 fail_readraw();
1753 END_PROFILE(SMBreadbraw);
1754 return(-1);
1757 CHECK_FSP(fsp,conn);
1759 flush_write_cache(fsp, READRAW_FLUSH);
1761 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
1762 if(CVAL(inbuf,smb_wct) == 10) {
1764 * This is a large offset (64 bit) read.
1766 #ifdef LARGE_SMB_OFF_T
1768 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
1770 #else /* !LARGE_SMB_OFF_T */
1773 * Ensure we haven't been sent a >32 bit offset.
1776 if(IVAL(inbuf,smb_vwv8) != 0) {
1777 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
1778 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
1779 _smb_setlen(header,0);
1780 if (write_data(smbd_server_fd(),header,4) != 4)
1781 fail_readraw();
1782 END_PROFILE(SMBreadbraw);
1783 return(-1);
1786 #endif /* LARGE_SMB_OFF_T */
1788 if(startpos < 0) {
1789 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
1790 _smb_setlen(header,0);
1791 if (write_data(smbd_server_fd(),header,4) != 4)
1792 fail_readraw();
1793 END_PROFILE(SMBreadbraw);
1794 return(-1);
1797 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
1798 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
1800 /* ensure we don't overrun the packet size */
1801 maxcount = MIN(65535,maxcount);
1803 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1804 SMB_OFF_T size = fsp->size;
1805 SMB_OFF_T sizeneeded = startpos + maxcount;
1807 if (size < sizeneeded) {
1808 SMB_STRUCT_STAT st;
1809 if (SMB_VFS_FSTAT(fsp,fsp->fd,&st) == 0)
1810 size = st.st_size;
1811 if (!fsp->can_write)
1812 fsp->size = size;
1815 if (startpos >= size)
1816 nread = 0;
1817 else
1818 nread = MIN(maxcount,(size - startpos));
1821 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1822 if (nread < mincount)
1823 nread = 0;
1824 #endif
1826 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
1827 (int)maxcount, (int)mincount, (int)nread ) );
1829 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf);
1831 DEBUG(5,("readbraw finished\n"));
1832 END_PROFILE(SMBreadbraw);
1833 return -1;
1836 /****************************************************************************
1837 Reply to a lockread (core+ protocol).
1838 ****************************************************************************/
1840 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
1842 ssize_t nread = -1;
1843 char *data;
1844 int outsize = 0;
1845 SMB_OFF_T startpos;
1846 size_t numtoread;
1847 NTSTATUS status;
1848 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1849 BOOL my_lock_ctx = False;
1850 START_PROFILE(SMBlockread);
1852 CHECK_FSP(fsp,conn);
1853 CHECK_READ(fsp);
1855 release_level_2_oplocks_on_change(fsp);
1857 numtoread = SVAL(inbuf,smb_vwv1);
1858 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
1860 outsize = set_message(outbuf,5,3,True);
1861 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1862 data = smb_buf(outbuf) + 3;
1865 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
1866 * protocol request that predates the read/write lock concept.
1867 * Thus instead of asking for a read lock here we need to ask
1868 * for a write lock. JRA.
1869 * Note that the requested lock size is unaffected by max_recv.
1872 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid),
1873 (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, &my_lock_ctx);
1875 if (NT_STATUS_V(status)) {
1876 #if 0
1878 * We used to make lockread a blocking lock. It turns out
1879 * that this isn't on W2k. Found by the Samba 4 RAW-READ torture
1880 * tester. JRA.
1883 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
1885 * A blocking lock was requested. Package up
1886 * this smb into a queued request and push it
1887 * onto the blocking lock queue.
1889 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)startpos,
1890 (SMB_BIG_UINT)numtoread)) {
1891 END_PROFILE(SMBlockread);
1892 return -1;
1895 #endif
1896 END_PROFILE(SMBlockread);
1897 return ERROR_NT(status);
1901 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
1904 if (numtoread > max_recv) {
1905 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
1906 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
1907 (unsigned int)numtoread, (unsigned int)max_recv ));
1908 numtoread = MIN(numtoread,max_recv);
1910 nread = read_file(fsp,data,startpos,numtoread);
1912 if (nread < 0) {
1913 END_PROFILE(SMBlockread);
1914 return(UNIXERROR(ERRDOS,ERRnoaccess));
1917 outsize += nread;
1918 SSVAL(outbuf,smb_vwv0,nread);
1919 SSVAL(outbuf,smb_vwv5,nread+3);
1920 SSVAL(smb_buf(outbuf),1,nread);
1922 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
1923 fsp->fnum, (int)numtoread, (int)nread));
1925 END_PROFILE(SMBlockread);
1926 return(outsize);
1929 /****************************************************************************
1930 Reply to a read.
1931 ****************************************************************************/
1933 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
1935 size_t numtoread;
1936 ssize_t nread = 0;
1937 char *data;
1938 SMB_OFF_T startpos;
1939 int outsize = 0;
1940 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1941 START_PROFILE(SMBread);
1943 CHECK_FSP(fsp,conn);
1944 CHECK_READ(fsp);
1946 numtoread = SVAL(inbuf,smb_vwv1);
1947 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
1949 outsize = set_message(outbuf,5,3,True);
1950 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1952 * The requested read size cannot be greater than max_recv. JRA.
1954 if (numtoread > max_recv) {
1955 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
1956 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
1957 (unsigned int)numtoread, (unsigned int)max_recv ));
1958 numtoread = MIN(numtoread,max_recv);
1961 data = smb_buf(outbuf) + 3;
1963 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1964 END_PROFILE(SMBread);
1965 return ERROR_DOS(ERRDOS,ERRlock);
1968 if (numtoread > 0)
1969 nread = read_file(fsp,data,startpos,numtoread);
1971 if (nread < 0) {
1972 END_PROFILE(SMBread);
1973 return(UNIXERROR(ERRDOS,ERRnoaccess));
1976 outsize += nread;
1977 SSVAL(outbuf,smb_vwv0,nread);
1978 SSVAL(outbuf,smb_vwv5,nread+3);
1979 SCVAL(smb_buf(outbuf),0,1);
1980 SSVAL(smb_buf(outbuf),1,nread);
1982 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
1983 fsp->fnum, (int)numtoread, (int)nread ) );
1985 END_PROFILE(SMBread);
1986 return(outsize);
1989 /****************************************************************************
1990 Reply to a read and X - possibly using sendfile.
1991 ****************************************************************************/
1993 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length,
1994 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
1996 ssize_t nread = -1;
1997 char *data = smb_buf(outbuf);
1999 #if defined(WITH_SENDFILE)
2001 * We can only use sendfile on a non-chained packet and on a file
2002 * that is exclusively oplocked.
2005 if ((CVAL(inbuf,smb_vwv0) == 0xFF) && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) &&
2006 lp_use_sendfile(SNUM(conn)) && (lp_write_cache_size(SNUM(conn)) == 0) ) {
2007 SMB_STRUCT_STAT sbuf;
2008 DATA_BLOB header;
2010 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1)
2011 return(UNIXERROR(ERRDOS,ERRnoaccess));
2013 if (startpos > sbuf.st_size)
2014 goto normal_read;
2016 if (smb_maxcnt > (sbuf.st_size - startpos))
2017 smb_maxcnt = (sbuf.st_size - startpos);
2019 if (smb_maxcnt == 0)
2020 goto normal_read;
2023 * Set up the packet header before send. We
2024 * assume here the sendfile will work (get the
2025 * correct amount of data).
2028 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2029 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
2030 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2031 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
2032 SCVAL(outbuf,smb_vwv0,0xFF);
2033 set_message(outbuf,12,smb_maxcnt,False);
2034 header.data = outbuf;
2035 header.length = data - outbuf;
2036 header.free = NULL;
2038 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt) == -1) {
2040 * Special hack for broken Linux with no 64 bit clean sendfile. If we
2041 * return ENOSYS then pretend we just got a normal read.
2043 if (errno == ENOSYS)
2044 goto normal_read;
2046 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2047 fsp->fsp_name, strerror(errno) ));
2048 exit_server("send_file_readX sendfile failed");
2051 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2052 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2053 return -1;
2056 normal_read:
2058 #endif
2060 nread = read_file(fsp,data,startpos,smb_maxcnt);
2062 if (nread < 0) {
2063 END_PROFILE(SMBreadX);
2064 return(UNIXERROR(ERRDOS,ERRnoaccess));
2067 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2068 SSVAL(outbuf,smb_vwv5,nread);
2069 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2070 SSVAL(smb_buf(outbuf),-2,nread);
2072 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2073 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2075 return nread;
2078 /****************************************************************************
2079 Reply to a read and X.
2080 ****************************************************************************/
2082 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2084 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2085 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2086 ssize_t nread = -1;
2087 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2088 #if 0
2089 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2090 #endif
2092 START_PROFILE(SMBreadX);
2094 /* If it's an IPC, pass off the pipe handler. */
2095 if (IS_IPC(conn)) {
2096 END_PROFILE(SMBreadX);
2097 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2100 CHECK_FSP(fsp,conn);
2101 CHECK_READ(fsp);
2103 set_message(outbuf,12,0,True);
2105 if(CVAL(inbuf,smb_wct) == 12) {
2106 #ifdef LARGE_SMB_OFF_T
2108 * This is a large offset (64 bit) read.
2110 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2112 #else /* !LARGE_SMB_OFF_T */
2115 * Ensure we haven't been sent a >32 bit offset.
2118 if(IVAL(inbuf,smb_vwv10) != 0) {
2119 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2120 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2121 END_PROFILE(SMBreadX);
2122 return ERROR_DOS(ERRDOS,ERRbadaccess);
2125 #endif /* LARGE_SMB_OFF_T */
2129 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
2130 END_PROFILE(SMBreadX);
2131 return ERROR_DOS(ERRDOS,ERRlock);
2134 nread = send_file_readX(conn, inbuf, outbuf, length, fsp, startpos, smb_maxcnt);
2135 if (nread != -1)
2136 nread = chain_reply(inbuf,outbuf,length,bufsize);
2138 END_PROFILE(SMBreadX);
2139 return nread;
2142 /****************************************************************************
2143 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2144 ****************************************************************************/
2146 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2148 ssize_t nwritten=0;
2149 ssize_t total_written=0;
2150 size_t numtowrite=0;
2151 size_t tcount;
2152 SMB_OFF_T startpos;
2153 char *data=NULL;
2154 BOOL write_through;
2155 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2156 int outsize = 0;
2157 START_PROFILE(SMBwritebraw);
2159 if (srv_is_signing_active()) {
2160 exit_server("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2163 CHECK_FSP(fsp,conn);
2164 CHECK_WRITE(fsp);
2166 tcount = IVAL(inbuf,smb_vwv1);
2167 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2168 write_through = BITSETW(inbuf+smb_vwv7,0);
2170 /* We have to deal with slightly different formats depending
2171 on whether we are using the core+ or lanman1.0 protocol */
2173 if(Protocol <= PROTOCOL_COREPLUS) {
2174 numtowrite = SVAL(smb_buf(inbuf),-2);
2175 data = smb_buf(inbuf);
2176 } else {
2177 numtowrite = SVAL(inbuf,smb_vwv10);
2178 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2181 /* force the error type */
2182 SCVAL(inbuf,smb_com,SMBwritec);
2183 SCVAL(outbuf,smb_com,SMBwritec);
2185 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2186 END_PROFILE(SMBwritebraw);
2187 return(ERROR_DOS(ERRDOS,ERRlock));
2190 if (numtowrite>0)
2191 nwritten = write_file(fsp,data,startpos,numtowrite);
2193 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2194 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2196 if (nwritten < (ssize_t)numtowrite) {
2197 END_PROFILE(SMBwritebraw);
2198 return(UNIXERROR(ERRHRD,ERRdiskfull));
2201 total_written = nwritten;
2203 /* Return a message to the redirector to tell it to send more bytes */
2204 SCVAL(outbuf,smb_com,SMBwritebraw);
2205 SSVALS(outbuf,smb_vwv0,-1);
2206 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2207 if (!send_smb(smbd_server_fd(),outbuf))
2208 exit_server("reply_writebraw: send_smb failed.");
2210 /* Now read the raw data into the buffer and write it */
2211 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2212 exit_server("secondary writebraw failed");
2215 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2216 numtowrite = smb_len(inbuf);
2218 /* Set up outbuf to return the correct return */
2219 outsize = set_message(outbuf,1,0,True);
2220 SCVAL(outbuf,smb_com,SMBwritec);
2221 SSVAL(outbuf,smb_vwv0,total_written);
2223 if (numtowrite != 0) {
2225 if (numtowrite > BUFFER_SIZE) {
2226 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2227 (unsigned int)numtowrite ));
2228 exit_server("secondary writebraw failed");
2231 if (tcount > nwritten+numtowrite) {
2232 DEBUG(3,("Client overestimated the write %d %d %d\n",
2233 (int)tcount,(int)nwritten,(int)numtowrite));
2236 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2237 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2238 strerror(errno) ));
2239 exit_server("secondary writebraw failed");
2242 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2244 if (nwritten < (ssize_t)numtowrite) {
2245 SCVAL(outbuf,smb_rcls,ERRHRD);
2246 SSVAL(outbuf,smb_err,ERRdiskfull);
2249 if (nwritten > 0)
2250 total_written += nwritten;
2253 if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn)))
2254 sync_file(conn,fsp);
2256 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2257 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2259 /* we won't return a status if write through is not selected - this follows what WfWg does */
2260 END_PROFILE(SMBwritebraw);
2261 if (!write_through && total_written==tcount) {
2263 #if RABBIT_PELLET_FIX
2265 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2266 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2268 if (!send_keepalive(smbd_server_fd()))
2269 exit_server("reply_writebraw: send of keepalive failed");
2270 #endif
2271 return(-1);
2274 return(outsize);
2277 /****************************************************************************
2278 Reply to a writeunlock (core+).
2279 ****************************************************************************/
2281 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
2282 int size, int dum_buffsize)
2284 ssize_t nwritten = -1;
2285 size_t numtowrite;
2286 SMB_OFF_T startpos;
2287 char *data;
2288 NTSTATUS status = NT_STATUS_OK;
2289 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2290 int outsize = 0;
2291 START_PROFILE(SMBwriteunlock);
2293 CHECK_FSP(fsp,conn);
2294 CHECK_WRITE(fsp);
2296 numtowrite = SVAL(inbuf,smb_vwv1);
2297 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2298 data = smb_buf(inbuf) + 3;
2300 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos,
2301 WRITE_LOCK,False)) {
2302 END_PROFILE(SMBwriteunlock);
2303 return ERROR_DOS(ERRDOS,ERRlock);
2306 /* The special X/Open SMB protocol handling of
2307 zero length writes is *NOT* done for
2308 this call */
2309 if(numtowrite == 0)
2310 nwritten = 0;
2311 else
2312 nwritten = write_file(fsp,data,startpos,numtowrite);
2314 if (lp_syncalways(SNUM(conn)))
2315 sync_file(conn,fsp);
2317 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2318 END_PROFILE(SMBwriteunlock);
2319 return(UNIXERROR(ERRHRD,ERRdiskfull));
2322 if (numtowrite) {
2323 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite,
2324 (SMB_BIG_UINT)startpos);
2325 if (NT_STATUS_V(status)) {
2326 END_PROFILE(SMBwriteunlock);
2327 return ERROR_NT(status);
2331 outsize = set_message(outbuf,1,0,True);
2333 SSVAL(outbuf,smb_vwv0,nwritten);
2335 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2336 fsp->fnum, (int)numtowrite, (int)nwritten));
2338 END_PROFILE(SMBwriteunlock);
2339 return outsize;
2342 /****************************************************************************
2343 Reply to a write.
2344 ****************************************************************************/
2346 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2348 size_t numtowrite;
2349 ssize_t nwritten = -1;
2350 SMB_OFF_T startpos;
2351 char *data;
2352 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2353 int outsize = 0;
2354 START_PROFILE(SMBwrite);
2356 /* If it's an IPC, pass off the pipe handler. */
2357 if (IS_IPC(conn)) {
2358 END_PROFILE(SMBwrite);
2359 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2362 CHECK_FSP(fsp,conn);
2363 CHECK_WRITE(fsp);
2365 numtowrite = SVAL(inbuf,smb_vwv1);
2366 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2367 data = smb_buf(inbuf) + 3;
2369 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2370 END_PROFILE(SMBwrite);
2371 return ERROR_DOS(ERRDOS,ERRlock);
2375 * X/Open SMB protocol says that if smb_vwv1 is
2376 * zero then the file size should be extended or
2377 * truncated to the size given in smb_vwv[2-3].
2380 if(numtowrite == 0) {
2382 * This is actually an allocate call, and set EOF. JRA.
2384 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2385 if (nwritten < 0) {
2386 END_PROFILE(SMBwrite);
2387 return ERROR_NT(NT_STATUS_DISK_FULL);
2389 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2390 if (nwritten < 0) {
2391 END_PROFILE(SMBwrite);
2392 return ERROR_NT(NT_STATUS_DISK_FULL);
2394 } else
2395 nwritten = write_file(fsp,data,startpos,numtowrite);
2397 if (lp_syncalways(SNUM(conn)))
2398 sync_file(conn,fsp);
2400 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2401 END_PROFILE(SMBwrite);
2402 return(UNIXERROR(ERRHRD,ERRdiskfull));
2405 outsize = set_message(outbuf,1,0,True);
2407 SSVAL(outbuf,smb_vwv0,nwritten);
2409 if (nwritten < (ssize_t)numtowrite) {
2410 SCVAL(outbuf,smb_rcls,ERRHRD);
2411 SSVAL(outbuf,smb_err,ERRdiskfull);
2414 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2416 END_PROFILE(SMBwrite);
2417 return(outsize);
2420 /****************************************************************************
2421 Reply to a write and X.
2422 ****************************************************************************/
2424 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2426 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2427 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2428 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2429 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2430 ssize_t nwritten = -1;
2431 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2432 unsigned int smblen = smb_len(inbuf);
2433 char *data;
2434 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2435 START_PROFILE(SMBwriteX);
2437 /* If it's an IPC, pass off the pipe handler. */
2438 if (IS_IPC(conn)) {
2439 END_PROFILE(SMBwriteX);
2440 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2443 CHECK_FSP(fsp,conn);
2444 CHECK_WRITE(fsp);
2446 /* Deal with possible LARGE_WRITEX */
2447 if (large_writeX)
2448 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2450 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2451 END_PROFILE(SMBwriteX);
2452 return ERROR_DOS(ERRDOS,ERRbadmem);
2455 data = smb_base(inbuf) + smb_doff;
2457 if(CVAL(inbuf,smb_wct) == 14) {
2458 #ifdef LARGE_SMB_OFF_T
2460 * This is a large offset (64 bit) write.
2462 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2464 #else /* !LARGE_SMB_OFF_T */
2467 * Ensure we haven't been sent a >32 bit offset.
2470 if(IVAL(inbuf,smb_vwv12) != 0) {
2471 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2472 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2473 END_PROFILE(SMBwriteX);
2474 return ERROR_DOS(ERRDOS,ERRbadaccess);
2477 #endif /* LARGE_SMB_OFF_T */
2480 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2481 END_PROFILE(SMBwriteX);
2482 return ERROR_DOS(ERRDOS,ERRlock);
2485 /* X/Open SMB protocol says that, unlike SMBwrite
2486 if the length is zero then NO truncation is
2487 done, just a write of zero. To truncate a file,
2488 use SMBwrite. */
2490 if(numtowrite == 0)
2491 nwritten = 0;
2492 else
2493 nwritten = write_file(fsp,data,startpos,numtowrite);
2495 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2496 END_PROFILE(SMBwriteX);
2497 return(UNIXERROR(ERRHRD,ERRdiskfull));
2500 set_message(outbuf,6,0,True);
2502 SSVAL(outbuf,smb_vwv2,nwritten);
2503 if (large_writeX)
2504 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2506 if (nwritten < (ssize_t)numtowrite) {
2507 SCVAL(outbuf,smb_rcls,ERRHRD);
2508 SSVAL(outbuf,smb_err,ERRdiskfull);
2511 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2512 fsp->fnum, (int)numtowrite, (int)nwritten));
2514 if (lp_syncalways(SNUM(conn)) || write_through)
2515 sync_file(conn,fsp);
2517 END_PROFILE(SMBwriteX);
2518 return chain_reply(inbuf,outbuf,length,bufsize);
2521 /****************************************************************************
2522 Reply to a lseek.
2523 ****************************************************************************/
2525 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2527 SMB_OFF_T startpos;
2528 SMB_OFF_T res= -1;
2529 int mode,umode;
2530 int outsize = 0;
2531 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2532 START_PROFILE(SMBlseek);
2534 CHECK_FSP(fsp,conn);
2536 flush_write_cache(fsp, SEEK_FLUSH);
2538 mode = SVAL(inbuf,smb_vwv1) & 3;
2539 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
2540 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
2542 switch (mode) {
2543 case 0:
2544 umode = SEEK_SET;
2545 res = startpos;
2546 break;
2547 case 1:
2548 umode = SEEK_CUR;
2549 res = fsp->pos + startpos;
2550 break;
2551 case 2:
2552 umode = SEEK_END;
2553 break;
2554 default:
2555 umode = SEEK_SET;
2556 res = startpos;
2557 break;
2560 if (umode == SEEK_END) {
2561 if((res = SMB_VFS_LSEEK(fsp,fsp->fd,startpos,umode)) == -1) {
2562 if(errno == EINVAL) {
2563 SMB_OFF_T current_pos = startpos;
2564 SMB_STRUCT_STAT sbuf;
2566 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) {
2567 END_PROFILE(SMBlseek);
2568 return(UNIXERROR(ERRDOS,ERRnoaccess));
2571 current_pos += sbuf.st_size;
2572 if(current_pos < 0)
2573 res = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_SET);
2577 if(res == -1) {
2578 END_PROFILE(SMBlseek);
2579 return(UNIXERROR(ERRDOS,ERRnoaccess));
2583 fsp->pos = res;
2585 outsize = set_message(outbuf,2,0,True);
2586 SIVAL(outbuf,smb_vwv0,res);
2588 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2589 fsp->fnum, (double)startpos, (double)res, mode));
2591 END_PROFILE(SMBlseek);
2592 return(outsize);
2595 /****************************************************************************
2596 Reply to a flush.
2597 ****************************************************************************/
2599 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2601 int outsize = set_message(outbuf,0,0,True);
2602 uint16 fnum = SVAL(inbuf,smb_vwv0);
2603 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2604 START_PROFILE(SMBflush);
2606 if (fnum != 0xFFFF)
2607 CHECK_FSP(fsp,conn);
2609 if (!fsp) {
2610 file_sync_all(conn);
2611 } else {
2612 sync_file(conn,fsp);
2615 DEBUG(3,("flush\n"));
2616 END_PROFILE(SMBflush);
2617 return(outsize);
2620 /****************************************************************************
2621 Reply to a exit.
2622 ****************************************************************************/
2624 int reply_exit(connection_struct *conn,
2625 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2627 int outsize;
2628 START_PROFILE(SMBexit);
2630 file_close_pid(SVAL(inbuf,smb_pid));
2632 outsize = set_message(outbuf,0,0,True);
2634 DEBUG(3,("exit\n"));
2636 END_PROFILE(SMBexit);
2637 return(outsize);
2640 /****************************************************************************
2641 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2642 ****************************************************************************/
2644 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2645 int dum_buffsize)
2647 extern struct current_user current_user;
2648 int outsize = 0;
2649 time_t mtime;
2650 int32 eclass = 0, err = 0;
2651 files_struct *fsp = NULL;
2652 START_PROFILE(SMBclose);
2654 outsize = set_message(outbuf,0,0,True);
2656 /* If it's an IPC, pass off to the pipe handler. */
2657 if (IS_IPC(conn)) {
2658 END_PROFILE(SMBclose);
2659 return reply_pipe_close(conn, inbuf,outbuf);
2662 fsp = file_fsp(inbuf,smb_vwv0);
2665 * We can only use CHECK_FSP if we know it's not a directory.
2668 if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
2669 END_PROFILE(SMBclose);
2670 return ERROR_DOS(ERRDOS,ERRbadfid);
2673 if(fsp->is_directory) {
2675 * Special case - close NT SMB directory handle.
2677 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2678 close_file(fsp,True);
2679 } else {
2681 * Close ordinary file.
2683 int close_err;
2684 pstring file_name;
2686 /* Save the name for time set in close. */
2687 pstrcpy( file_name, fsp->fsp_name);
2689 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2690 fsp->fd, fsp->fnum,
2691 conn->num_files_open));
2694 * close_file() returns the unix errno if an error
2695 * was detected on close - normally this is due to
2696 * a disk full error. If not then it was probably an I/O error.
2699 if((close_err = close_file(fsp,True)) != 0) {
2700 errno = close_err;
2701 END_PROFILE(SMBclose);
2702 return (UNIXERROR(ERRHRD,ERRgeneral));
2706 * Now take care of any time sent in the close.
2709 mtime = make_unix_date3(inbuf+smb_vwv1);
2711 /* try and set the date */
2712 set_filetime(conn, file_name, mtime);
2716 /* We have a cached error */
2717 if(eclass || err) {
2718 END_PROFILE(SMBclose);
2719 return ERROR_DOS(eclass,err);
2722 END_PROFILE(SMBclose);
2723 return(outsize);
2726 /****************************************************************************
2727 Reply to a writeclose (Core+ protocol).
2728 ****************************************************************************/
2730 int reply_writeclose(connection_struct *conn,
2731 char *inbuf,char *outbuf, int size, int dum_buffsize)
2733 size_t numtowrite;
2734 ssize_t nwritten = -1;
2735 int outsize = 0;
2736 int close_err = 0;
2737 SMB_OFF_T startpos;
2738 char *data;
2739 time_t mtime;
2740 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2741 START_PROFILE(SMBwriteclose);
2743 CHECK_FSP(fsp,conn);
2744 CHECK_WRITE(fsp);
2746 numtowrite = SVAL(inbuf,smb_vwv1);
2747 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2748 mtime = make_unix_date3(inbuf+smb_vwv4);
2749 data = smb_buf(inbuf) + 1;
2751 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2752 END_PROFILE(SMBwriteclose);
2753 return ERROR_DOS(ERRDOS,ERRlock);
2756 nwritten = write_file(fsp,data,startpos,numtowrite);
2758 set_filetime(conn, fsp->fsp_name,mtime);
2761 * More insanity. W2K only closes the file if writelen > 0.
2762 * JRA.
2765 if (numtowrite) {
2766 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
2767 fsp->fsp_name ));
2768 close_err = close_file(fsp,True);
2771 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2772 fsp->fnum, (int)numtowrite, (int)nwritten,
2773 conn->num_files_open));
2775 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2776 END_PROFILE(SMBwriteclose);
2777 return(UNIXERROR(ERRHRD,ERRdiskfull));
2780 if(close_err != 0) {
2781 errno = close_err;
2782 END_PROFILE(SMBwriteclose);
2783 return(UNIXERROR(ERRHRD,ERRgeneral));
2786 outsize = set_message(outbuf,1,0,True);
2788 SSVAL(outbuf,smb_vwv0,nwritten);
2789 END_PROFILE(SMBwriteclose);
2790 return(outsize);
2793 /****************************************************************************
2794 Reply to a lock.
2795 ****************************************************************************/
2797 int reply_lock(connection_struct *conn,
2798 char *inbuf,char *outbuf, int length, int dum_buffsize)
2800 int outsize = set_message(outbuf,0,0,True);
2801 SMB_BIG_UINT count,offset;
2802 NTSTATUS status;
2803 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2804 BOOL my_lock_ctx = False;
2806 START_PROFILE(SMBlock);
2808 CHECK_FSP(fsp,conn);
2810 release_level_2_oplocks_on_change(fsp);
2812 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2813 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2815 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2816 fsp->fd, fsp->fnum, (double)offset, (double)count));
2818 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &my_lock_ctx);
2819 if (NT_STATUS_V(status)) {
2820 #if 0
2821 /* Tests using Samba4 against W2K show this call never creates a blocking lock. */
2822 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
2824 * A blocking lock was requested. Package up
2825 * this smb into a queued request and push it
2826 * onto the blocking lock queue.
2828 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), offset, count)) {
2829 END_PROFILE(SMBlock);
2830 return -1;
2833 #endif
2834 END_PROFILE(SMBlock);
2835 return ERROR_NT(status);
2838 END_PROFILE(SMBlock);
2839 return(outsize);
2842 /****************************************************************************
2843 Reply to a unlock.
2844 ****************************************************************************/
2846 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
2847 int dum_buffsize)
2849 int outsize = set_message(outbuf,0,0,True);
2850 SMB_BIG_UINT count,offset;
2851 NTSTATUS status;
2852 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2853 START_PROFILE(SMBunlock);
2855 CHECK_FSP(fsp,conn);
2857 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2858 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2860 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
2861 if (NT_STATUS_V(status)) {
2862 END_PROFILE(SMBunlock);
2863 return ERROR_NT(status);
2866 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2867 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
2869 END_PROFILE(SMBunlock);
2870 return(outsize);
2873 /****************************************************************************
2874 Reply to a tdis.
2875 ****************************************************************************/
2877 int reply_tdis(connection_struct *conn,
2878 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2880 int outsize = set_message(outbuf,0,0,True);
2881 uint16 vuid;
2882 START_PROFILE(SMBtdis);
2884 vuid = SVAL(inbuf,smb_uid);
2886 if (!conn) {
2887 DEBUG(4,("Invalid connection in tdis\n"));
2888 END_PROFILE(SMBtdis);
2889 return ERROR_DOS(ERRSRV,ERRinvnid);
2892 conn->used = False;
2894 close_cnum(conn,vuid);
2896 END_PROFILE(SMBtdis);
2897 return outsize;
2900 /****************************************************************************
2901 Reply to a echo.
2902 ****************************************************************************/
2904 int reply_echo(connection_struct *conn,
2905 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2907 int smb_reverb = SVAL(inbuf,smb_vwv0);
2908 int seq_num;
2909 unsigned int data_len = smb_buflen(inbuf);
2910 int outsize = set_message(outbuf,1,data_len,True);
2911 START_PROFILE(SMBecho);
2913 if (data_len > BUFFER_SIZE) {
2914 DEBUG(0,("reply_echo: data_len too large.\n"));
2915 END_PROFILE(SMBecho);
2916 return -1;
2919 /* copy any incoming data back out */
2920 if (data_len > 0)
2921 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2923 if (smb_reverb > 100) {
2924 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2925 smb_reverb = 100;
2928 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
2929 SSVAL(outbuf,smb_vwv0,seq_num);
2931 smb_setlen(outbuf,outsize - 4);
2933 if (!send_smb(smbd_server_fd(),outbuf))
2934 exit_server("reply_echo: send_smb failed.");
2937 DEBUG(3,("echo %d times\n", smb_reverb));
2939 smb_echo_count++;
2941 END_PROFILE(SMBecho);
2942 return -1;
2945 /****************************************************************************
2946 Reply to a printopen.
2947 ****************************************************************************/
2949 int reply_printopen(connection_struct *conn,
2950 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2952 int outsize = 0;
2953 files_struct *fsp;
2954 START_PROFILE(SMBsplopen);
2956 if (!CAN_PRINT(conn)) {
2957 END_PROFILE(SMBsplopen);
2958 return ERROR_DOS(ERRDOS,ERRnoaccess);
2961 /* Open for exclusive use, write only. */
2962 fsp = print_fsp_open(conn, NULL);
2964 if (!fsp) {
2965 END_PROFILE(SMBsplopen);
2966 return(UNIXERROR(ERRDOS,ERRnoaccess));
2969 outsize = set_message(outbuf,1,0,True);
2970 SSVAL(outbuf,smb_vwv0,fsp->fnum);
2972 DEBUG(3,("openprint fd=%d fnum=%d\n",
2973 fsp->fd, fsp->fnum));
2975 END_PROFILE(SMBsplopen);
2976 return(outsize);
2979 /****************************************************************************
2980 Reply to a printclose.
2981 ****************************************************************************/
2983 int reply_printclose(connection_struct *conn,
2984 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2986 int outsize = set_message(outbuf,0,0,True);
2987 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2988 int close_err = 0;
2989 START_PROFILE(SMBsplclose);
2991 CHECK_FSP(fsp,conn);
2993 if (!CAN_PRINT(conn)) {
2994 END_PROFILE(SMBsplclose);
2995 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
2998 DEBUG(3,("printclose fd=%d fnum=%d\n",
2999 fsp->fd,fsp->fnum));
3001 close_err = close_file(fsp,True);
3003 if(close_err != 0) {
3004 errno = close_err;
3005 END_PROFILE(SMBsplclose);
3006 return(UNIXERROR(ERRHRD,ERRgeneral));
3009 END_PROFILE(SMBsplclose);
3010 return(outsize);
3013 /****************************************************************************
3014 Reply to a printqueue.
3015 ****************************************************************************/
3017 int reply_printqueue(connection_struct *conn,
3018 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3020 int outsize = set_message(outbuf,2,3,True);
3021 int max_count = SVAL(inbuf,smb_vwv0);
3022 int start_index = SVAL(inbuf,smb_vwv1);
3023 START_PROFILE(SMBsplretq);
3025 /* we used to allow the client to get the cnum wrong, but that
3026 is really quite gross and only worked when there was only
3027 one printer - I think we should now only accept it if they
3028 get it right (tridge) */
3029 if (!CAN_PRINT(conn)) {
3030 END_PROFILE(SMBsplretq);
3031 return ERROR_DOS(ERRDOS,ERRnoaccess);
3034 SSVAL(outbuf,smb_vwv0,0);
3035 SSVAL(outbuf,smb_vwv1,0);
3036 SCVAL(smb_buf(outbuf),0,1);
3037 SSVAL(smb_buf(outbuf),1,0);
3039 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3040 start_index, max_count));
3043 print_queue_struct *queue = NULL;
3044 print_status_struct status;
3045 char *p = smb_buf(outbuf) + 3;
3046 int count = print_queue_status(SNUM(conn), &queue, &status);
3047 int num_to_get = ABS(max_count);
3048 int first = (max_count>0?start_index:start_index+max_count+1);
3049 int i;
3051 if (first >= count)
3052 num_to_get = 0;
3053 else
3054 num_to_get = MIN(num_to_get,count-first);
3057 for (i=first;i<first+num_to_get;i++) {
3058 put_dos_date2(p,0,queue[i].time);
3059 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
3060 SSVAL(p,5, queue[i].job);
3061 SIVAL(p,7,queue[i].size);
3062 SCVAL(p,11,0);
3063 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
3064 p += 28;
3067 if (count > 0) {
3068 outsize = set_message(outbuf,2,28*count+3,False);
3069 SSVAL(outbuf,smb_vwv0,count);
3070 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3071 SCVAL(smb_buf(outbuf),0,1);
3072 SSVAL(smb_buf(outbuf),1,28*count);
3075 SAFE_FREE(queue);
3077 DEBUG(3,("%d entries returned in queue\n",count));
3080 END_PROFILE(SMBsplretq);
3081 return(outsize);
3084 /****************************************************************************
3085 Reply to a printwrite.
3086 ****************************************************************************/
3088 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3090 int numtowrite;
3091 int outsize = set_message(outbuf,0,0,True);
3092 char *data;
3093 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3095 START_PROFILE(SMBsplwr);
3097 if (!CAN_PRINT(conn)) {
3098 END_PROFILE(SMBsplwr);
3099 return ERROR_DOS(ERRDOS,ERRnoaccess);
3102 CHECK_FSP(fsp,conn);
3103 CHECK_WRITE(fsp);
3105 numtowrite = SVAL(smb_buf(inbuf),1);
3106 data = smb_buf(inbuf) + 3;
3108 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3109 END_PROFILE(SMBsplwr);
3110 return(UNIXERROR(ERRHRD,ERRdiskfull));
3113 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3115 END_PROFILE(SMBsplwr);
3116 return(outsize);
3119 /****************************************************************************
3120 The guts of the mkdir command, split out so it may be called by the NT SMB
3121 code.
3122 ****************************************************************************/
3124 NTSTATUS mkdir_internal(connection_struct *conn, pstring directory)
3126 BOOL bad_path = False;
3127 SMB_STRUCT_STAT sbuf;
3128 int ret= -1;
3130 unix_convert(directory,conn,0,&bad_path,&sbuf);
3132 if( strchr_m(directory, ':')) {
3133 return NT_STATUS_NOT_A_DIRECTORY;
3136 if (ms_has_wild(directory)) {
3137 return NT_STATUS_OBJECT_NAME_INVALID;
3140 if (check_name(directory, conn))
3141 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory));
3143 if (ret == -1) {
3144 if(errno == ENOENT) {
3145 if (bad_path)
3146 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3147 else
3148 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3150 return map_nt_error_from_unix(errno);
3153 return NT_STATUS_OK;
3156 /****************************************************************************
3157 Reply to a mkdir.
3158 ****************************************************************************/
3160 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3162 pstring directory;
3163 int outsize;
3164 NTSTATUS status;
3165 START_PROFILE(SMBmkdir);
3167 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
3168 if (!NT_STATUS_IS_OK(status)) {
3169 END_PROFILE(SMBmkdir);
3170 return ERROR_NT(status);
3173 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
3175 status = mkdir_internal(conn, directory);
3176 if (!NT_STATUS_IS_OK(status)) {
3177 END_PROFILE(SMBmkdir);
3178 return ERROR_NT(status);
3181 outsize = set_message(outbuf,0,0,True);
3183 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3185 END_PROFILE(SMBmkdir);
3186 return(outsize);
3189 /****************************************************************************
3190 Static function used by reply_rmdir to delete an entire directory
3191 tree recursively. Return False on ok, True on fail.
3192 ****************************************************************************/
3194 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3196 const char *dname = NULL;
3197 BOOL ret = False;
3198 void *dirptr = OpenDir(conn, directory, False);
3200 if(dirptr == NULL)
3201 return True;
3203 while((dname = ReadDirName(dirptr))) {
3204 pstring fullname;
3205 SMB_STRUCT_STAT st;
3207 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3208 continue;
3210 /* Construct the full name. */
3211 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3212 errno = ENOMEM;
3213 ret = True;
3214 break;
3217 pstrcpy(fullname, directory);
3218 pstrcat(fullname, "/");
3219 pstrcat(fullname, dname);
3221 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
3222 ret = True;
3223 break;
3226 if(st.st_mode & S_IFDIR) {
3227 if(recursive_rmdir(conn, fullname)!=0) {
3228 ret = True;
3229 break;
3231 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
3232 ret = True;
3233 break;
3235 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
3236 ret = True;
3237 break;
3240 CloseDir(dirptr);
3241 return ret;
3244 /****************************************************************************
3245 The internals of the rmdir code - called elsewhere.
3246 ****************************************************************************/
3248 BOOL rmdir_internals(connection_struct *conn, char *directory)
3250 BOOL ok;
3252 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3253 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3255 * Check to see if the only thing in this directory are
3256 * vetoed files/directories. If so then delete them and
3257 * retry. If we fail to delete any of them (and we *don't*
3258 * do a recursive delete) then fail the rmdir.
3260 BOOL all_veto_files = True;
3261 const char *dname;
3262 void *dirptr = OpenDir(conn, directory, False);
3264 if(dirptr != NULL) {
3265 int dirpos = TellDir(dirptr);
3266 while ((dname = ReadDirName(dirptr))) {
3267 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3268 continue;
3269 if(!IS_VETO_PATH(conn, dname)) {
3270 all_veto_files = False;
3271 break;
3275 if(all_veto_files) {
3276 SeekDir(dirptr,dirpos);
3277 while ((dname = ReadDirName(dirptr))) {
3278 pstring fullname;
3279 SMB_STRUCT_STAT st;
3281 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3282 continue;
3284 /* Construct the full name. */
3285 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3286 errno = ENOMEM;
3287 break;
3290 pstrcpy(fullname, directory);
3291 pstrcat(fullname, "/");
3292 pstrcat(fullname, dname);
3294 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
3295 break;
3296 if(st.st_mode & S_IFDIR) {
3297 if(lp_recursive_veto_delete(SNUM(conn))) {
3298 if(recursive_rmdir(conn, fullname) != 0)
3299 break;
3301 if(SMB_VFS_RMDIR(conn,fullname) != 0)
3302 break;
3303 } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
3304 break;
3306 CloseDir(dirptr);
3307 /* Retry the rmdir */
3308 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3309 } else {
3310 CloseDir(dirptr);
3312 } else {
3313 errno = ENOTEMPTY;
3317 if (!ok)
3318 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
3320 return ok;
3323 /****************************************************************************
3324 Reply to a rmdir.
3325 ****************************************************************************/
3327 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3329 pstring directory;
3330 int outsize = 0;
3331 BOOL ok = False;
3332 BOOL bad_path = False;
3333 SMB_STRUCT_STAT sbuf;
3334 NTSTATUS status;
3335 START_PROFILE(SMBrmdir);
3337 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
3338 if (!NT_STATUS_IS_OK(status)) {
3339 END_PROFILE(SMBrmdir);
3340 return ERROR_NT(status);
3343 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3345 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3347 if (check_name(directory,conn)) {
3348 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3349 ok = rmdir_internals(conn, directory);
3352 if (!ok) {
3353 END_PROFILE(SMBrmdir);
3354 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRbadpath);
3357 outsize = set_message(outbuf,0,0,True);
3359 DEBUG( 3, ( "rmdir %s\n", directory ) );
3361 END_PROFILE(SMBrmdir);
3362 return(outsize);
3365 /*******************************************************************
3366 Resolve wildcards in a filename rename.
3367 Note that name is in UNIX charset and thus potentially can be more
3368 than fstring buffer (255 bytes) especially in default UTF-8 case.
3369 Therefore, we use pstring inside and all calls should ensure that
3370 name2 is at least pstring-long (they do already)
3371 ********************************************************************/
3373 static BOOL resolve_wildcards(const char *name1, char *name2)
3375 pstring root1,root2;
3376 pstring ext1,ext2;
3377 char *p,*p2, *pname1, *pname2;
3378 int available_space, actual_space;
3381 pname1 = strrchr_m(name1,'/');
3382 pname2 = strrchr_m(name2,'/');
3384 if (!pname1 || !pname2)
3385 return(False);
3387 pstrcpy(root1,pname1);
3388 pstrcpy(root2,pname2);
3389 p = strrchr_m(root1,'.');
3390 if (p) {
3391 *p = 0;
3392 pstrcpy(ext1,p+1);
3393 } else {
3394 pstrcpy(ext1,"");
3396 p = strrchr_m(root2,'.');
3397 if (p) {
3398 *p = 0;
3399 pstrcpy(ext2,p+1);
3400 } else {
3401 pstrcpy(ext2,"");
3404 p = root1;
3405 p2 = root2;
3406 while (*p2) {
3407 if (*p2 == '?') {
3408 *p2 = *p;
3409 p2++;
3410 } else {
3411 p2++;
3413 if (*p)
3414 p++;
3417 p = ext1;
3418 p2 = ext2;
3419 while (*p2) {
3420 if (*p2 == '?') {
3421 *p2 = *p;
3422 p2++;
3423 } else {
3424 p2++;
3426 if (*p)
3427 p++;
3430 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
3432 if (ext2[0]) {
3433 actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
3434 if (actual_space >= available_space - 1) {
3435 DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
3436 actual_space - available_space));
3438 } else {
3439 pstrcpy_base(pname2, root2, name2);
3442 return(True);
3445 /****************************************************************************
3446 Ensure open files have their names updates.
3447 ****************************************************************************/
3449 static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode, char *newname)
3451 files_struct *fsp;
3452 BOOL did_rename = False;
3454 for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
3455 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
3456 fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
3457 fsp->fsp_name, newname ));
3458 string_set(&fsp->fsp_name, newname);
3459 did_rename = True;
3462 if (!did_rename)
3463 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
3464 (unsigned int)dev, (double)inode, newname ));
3467 /****************************************************************************
3468 Rename an open file - given an fsp.
3469 ****************************************************************************/
3471 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, BOOL replace_if_exists)
3473 SMB_STRUCT_STAT sbuf;
3474 BOOL bad_path = False;
3475 pstring newname_last_component;
3476 NTSTATUS error = NT_STATUS_OK;
3477 BOOL dest_exists;
3478 BOOL rcdest = True;
3480 ZERO_STRUCT(sbuf);
3481 rcdest = unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf);
3483 /* Quick check for "." and ".." */
3484 if (!bad_path && newname_last_component[0] == '.') {
3485 if (!newname_last_component[1] || (newname_last_component[1] == '.' && !newname_last_component[2])) {
3486 return NT_STATUS_ACCESS_DENIED;
3489 if (!rcdest && bad_path) {
3490 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3493 /* Ensure newname contains a '/' */
3494 if(strrchr_m(newname,'/') == 0) {
3495 pstring tmpstr;
3497 pstrcpy(tmpstr, "./");
3498 pstrcat(tmpstr, newname);
3499 pstrcpy(newname, tmpstr);
3503 * Check for special case with case preserving and not
3504 * case sensitive. If the old last component differs from the original
3505 * last component only by case, then we should allow
3506 * the rename (user is trying to change the case of the
3507 * filename).
3510 if((case_sensitive == False) && (case_preserve == True) &&
3511 strequal(newname, fsp->fsp_name)) {
3512 char *p;
3513 pstring newname_modified_last_component;
3516 * Get the last component of the modified name.
3517 * Note that we guarantee that newname contains a '/'
3518 * character above.
3520 p = strrchr_m(newname,'/');
3521 pstrcpy(newname_modified_last_component,p+1);
3523 if(strcsequal(newname_modified_last_component,
3524 newname_last_component) == False) {
3526 * Replace the modified last component with
3527 * the original.
3529 pstrcpy(p+1, newname_last_component);
3534 * If the src and dest names are identical - including case,
3535 * don't do the rename, just return success.
3538 if (strcsequal(fsp->fsp_name, newname)) {
3539 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
3540 newname));
3541 return NT_STATUS_OK;
3544 dest_exists = vfs_object_exist(conn,newname,NULL);
3546 if(!replace_if_exists && dest_exists) {
3547 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
3548 fsp->fsp_name,newname));
3549 return NT_STATUS_OBJECT_NAME_COLLISION;
3552 error = can_rename(newname,conn,&sbuf);
3554 if (dest_exists && !NT_STATUS_IS_OK(error)) {
3555 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3556 nt_errstr(error), fsp->fsp_name,newname));
3557 if (NT_STATUS_EQUAL(error,NT_STATUS_SHARING_VIOLATION))
3558 error = NT_STATUS_ACCESS_DENIED;
3559 return error;
3562 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
3563 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
3564 fsp->fsp_name,newname));
3565 rename_open_files(conn, fsp->dev, fsp->inode, newname);
3566 return NT_STATUS_OK;
3569 if (errno == ENOTDIR || errno == EISDIR)
3570 error = NT_STATUS_OBJECT_NAME_COLLISION;
3571 else
3572 error = map_nt_error_from_unix(errno);
3574 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
3575 nt_errstr(error), fsp->fsp_name,newname));
3577 return error;
3580 /****************************************************************************
3581 The guts of the rename command, split out so it may be called by the NT SMB
3582 code.
3583 ****************************************************************************/
3585 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, uint16 attrs, BOOL replace_if_exists)
3587 pstring directory;
3588 pstring mask;
3589 pstring last_component_src;
3590 pstring last_component_dest;
3591 char *p;
3592 BOOL has_wild;
3593 BOOL bad_path_src = False;
3594 BOOL bad_path_dest = False;
3595 int count=0;
3596 NTSTATUS error = NT_STATUS_OK;
3597 BOOL rc = True;
3598 BOOL rcdest = True;
3599 SMB_STRUCT_STAT sbuf1, sbuf2;
3601 *directory = *mask = 0;
3603 ZERO_STRUCT(sbuf1);
3604 ZERO_STRUCT(sbuf2);
3606 rc = unix_convert(name,conn,last_component_src,&bad_path_src,&sbuf1);
3607 if (!rc && bad_path_src) {
3608 if (ms_has_wild(last_component_src))
3609 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3610 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3613 /* Quick check for "." and ".." */
3614 if (last_component_src[0] == '.') {
3615 if (!last_component_src[1] || (last_component_src[1] == '.' && !last_component_src[2])) {
3616 return NT_STATUS_OBJECT_NAME_INVALID;
3620 rcdest = unix_convert(newname,conn,last_component_dest,&bad_path_dest,&sbuf2);
3622 /* Quick check for "." and ".." */
3623 if (last_component_dest[0] == '.') {
3624 if (!last_component_dest[1] || (last_component_dest[1] == '.' && !last_component_dest[2])) {
3625 return NT_STATUS_OBJECT_NAME_INVALID;
3630 * Split the old name into directory and last component
3631 * strings. Note that unix_convert may have stripped off a
3632 * leading ./ from both name and newname if the rename is
3633 * at the root of the share. We need to make sure either both
3634 * name and newname contain a / character or neither of them do
3635 * as this is checked in resolve_wildcards().
3638 p = strrchr_m(name,'/');
3639 if (!p) {
3640 pstrcpy(directory,".");
3641 pstrcpy(mask,name);
3642 } else {
3643 *p = 0;
3644 pstrcpy(directory,name);
3645 pstrcpy(mask,p+1);
3646 *p = '/'; /* Replace needed for exceptional test below. */
3650 * We should only check the mangled cache
3651 * here if unix_convert failed. This means
3652 * that the path in 'mask' doesn't exist
3653 * on the file system and so we need to look
3654 * for a possible mangle. This patch from
3655 * Tine Smukavec <valentin.smukavec@hermes.si>.
3658 if (!rc && mangle_is_mangled(mask))
3659 mangle_check_cache( mask );
3661 has_wild = ms_has_wild(mask);
3663 if (!has_wild) {
3665 * No wildcards - just process the one file.
3667 BOOL is_short_name = mangle_is_8_3(name, True);
3669 /* Add a terminating '/' to the directory name. */
3670 pstrcat(directory,"/");
3671 pstrcat(directory,mask);
3673 /* Ensure newname contains a '/' also */
3674 if(strrchr_m(newname,'/') == 0) {
3675 pstring tmpstr;
3677 pstrcpy(tmpstr, "./");
3678 pstrcat(tmpstr, newname);
3679 pstrcpy(newname, tmpstr);
3682 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
3683 directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
3684 case_sensitive, case_preserve, short_case_preserve, directory,
3685 newname, last_component_dest, is_short_name));
3688 * Check for special case with case preserving and not
3689 * case sensitive, if directory and newname are identical,
3690 * and the old last component differs from the original
3691 * last component only by case, then we should allow
3692 * the rename (user is trying to change the case of the
3693 * filename).
3695 if((case_sensitive == False) &&
3696 (((case_preserve == True) &&
3697 (is_short_name == False)) ||
3698 ((short_case_preserve == True) &&
3699 (is_short_name == True))) &&
3700 strcsequal(directory, newname)) {
3701 pstring modified_last_component;
3704 * Get the last component of the modified name.
3705 * Note that we guarantee that newname contains a '/'
3706 * character above.
3708 p = strrchr_m(newname,'/');
3709 pstrcpy(modified_last_component,p+1);
3711 if(strcsequal(modified_last_component,
3712 last_component_dest) == False) {
3714 * Replace the modified last component with
3715 * the original.
3717 pstrcpy(p+1, last_component_dest);
3721 resolve_wildcards(directory,newname);
3724 * The source object must exist.
3727 if (!vfs_object_exist(conn, directory, &sbuf1)) {
3728 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
3729 directory,newname));
3731 if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
3733 * Must return different errors depending on whether the parent
3734 * directory existed or not.
3737 p = strrchr_m(directory, '/');
3738 if (!p)
3739 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3740 *p = '\0';
3741 if (vfs_object_exist(conn, directory, NULL))
3742 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3743 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3745 error = map_nt_error_from_unix(errno);
3746 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3747 nt_errstr(error), directory,newname));
3749 return error;
3752 if (!rcdest && bad_path_dest) {
3753 if (ms_has_wild(last_component_dest))
3754 return NT_STATUS_OBJECT_NAME_INVALID;
3755 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3758 error = can_rename(directory,conn,&sbuf1);
3760 if (!NT_STATUS_IS_OK(error)) {
3761 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3762 nt_errstr(error), directory,newname));
3763 return error;
3767 * If the src and dest names are identical - including case,
3768 * don't do the rename, just return success.
3771 if (strcsequal(directory, newname)) {
3772 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3773 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
3774 return NT_STATUS_OK;
3777 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
3778 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
3779 directory,newname));
3780 return NT_STATUS_OBJECT_NAME_COLLISION;
3783 if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
3784 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
3785 directory,newname));
3786 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3787 return NT_STATUS_OK;
3790 if (errno == ENOTDIR || errno == EISDIR)
3791 error = NT_STATUS_OBJECT_NAME_COLLISION;
3792 else
3793 error = map_nt_error_from_unix(errno);
3795 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3796 nt_errstr(error), directory,newname));
3798 return error;
3799 } else {
3801 * Wildcards - process each file that matches.
3803 void *dirptr = NULL;
3804 const char *dname;
3805 pstring destname;
3807 if (check_name(directory,conn))
3808 dirptr = OpenDir(conn, directory, True);
3810 if (dirptr) {
3811 error = NT_STATUS_NO_SUCH_FILE;
3812 /* Was error = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */
3814 if (strequal(mask,"????????.???"))
3815 pstrcpy(mask,"*");
3817 while ((dname = ReadDirName(dirptr))) {
3818 pstring fname;
3819 BOOL sysdir_entry = False;
3821 pstrcpy(fname,dname);
3823 /* Quick check for "." and ".." */
3824 if (fname[0] == '.') {
3825 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
3826 if (attrs & aDIR) {
3827 sysdir_entry = True;
3828 } else {
3829 continue;
3834 if(!mask_match(fname, mask, case_sensitive))
3835 continue;
3837 if (sysdir_entry) {
3838 error = NT_STATUS_OBJECT_NAME_INVALID;
3839 continue;
3842 error = NT_STATUS_ACCESS_DENIED;
3843 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3844 if (!vfs_object_exist(conn, fname, &sbuf1)) {
3845 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3846 DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
3847 continue;
3849 error = can_rename(fname,conn,&sbuf1);
3850 if (!NT_STATUS_IS_OK(error)) {
3851 DEBUG(6,("rename %s refused\n", fname));
3852 continue;
3854 pstrcpy(destname,newname);
3856 if (!resolve_wildcards(fname,destname)) {
3857 DEBUG(6,("resolve_wildcards %s %s failed\n",
3858 fname, destname));
3859 continue;
3862 if (!replace_if_exists &&
3863 vfs_file_exist(conn,destname, NULL)) {
3864 DEBUG(6,("file_exist %s\n", destname));
3865 error = NT_STATUS_OBJECT_NAME_COLLISION;
3866 continue;
3869 if (!SMB_VFS_RENAME(conn,fname,destname)) {
3870 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3871 count++;
3872 error = NT_STATUS_OK;
3874 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3876 CloseDir(dirptr);
3879 if (!NT_STATUS_EQUAL(error,NT_STATUS_NO_SUCH_FILE)) {
3880 if (!rcdest && bad_path_dest) {
3881 if (ms_has_wild(last_component_dest))
3882 return NT_STATUS_OBJECT_NAME_INVALID;
3883 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3888 if (count == 0 && NT_STATUS_IS_OK(error)) {
3889 error = map_nt_error_from_unix(errno);
3892 return error;
3895 /****************************************************************************
3896 Reply to a mv.
3897 ****************************************************************************/
3899 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
3900 int dum_buffsize)
3902 int outsize = 0;
3903 pstring name;
3904 pstring newname;
3905 char *p;
3906 uint16 attrs = SVAL(inbuf,smb_vwv0);
3907 NTSTATUS status;
3909 START_PROFILE(SMBmv);
3911 p = smb_buf(inbuf) + 1;
3912 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status);
3913 if (!NT_STATUS_IS_OK(status)) {
3914 END_PROFILE(SMBmv);
3915 return ERROR_NT(status);
3917 p++;
3918 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status);
3919 if (!NT_STATUS_IS_OK(status)) {
3920 END_PROFILE(SMBmv);
3921 return ERROR_NT(status);
3924 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3925 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3927 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3929 status = rename_internals(conn, name, newname, attrs, False);
3930 if (!NT_STATUS_IS_OK(status)) {
3931 END_PROFILE(SMBmv);
3932 return ERROR_NT(status);
3936 * Win2k needs a changenotify request response before it will
3937 * update after a rename..
3939 process_pending_change_notify_queue((time_t)0);
3940 outsize = set_message(outbuf,0,0,True);
3942 END_PROFILE(SMBmv);
3943 return(outsize);
3946 /*******************************************************************
3947 Copy a file as part of a reply_copy.
3948 ******************************************************************/
3950 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3951 int count,BOOL target_is_directory, int *err_ret)
3953 int Access,action;
3954 SMB_STRUCT_STAT src_sbuf, sbuf2;
3955 SMB_OFF_T ret=-1;
3956 files_struct *fsp1,*fsp2;
3957 pstring dest;
3959 *err_ret = 0;
3961 pstrcpy(dest,dest1);
3962 if (target_is_directory) {
3963 char *p = strrchr_m(src,'/');
3964 if (p)
3965 p++;
3966 else
3967 p = src;
3968 pstrcat(dest,"/");
3969 pstrcat(dest,p);
3972 if (!vfs_file_exist(conn,src,&src_sbuf))
3973 return(False);
3975 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
3976 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
3978 if (!fsp1)
3979 return(False);
3981 if (!target_is_directory && count)
3982 ofun = FILE_EXISTS_OPEN;
3984 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1)
3985 ZERO_STRUCTP(&sbuf2);
3987 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
3988 ofun,src_sbuf.st_mode,0,&Access,&action);
3990 if (!fsp2) {
3991 close_file(fsp1,False);
3992 return(False);
3995 if ((ofun&3) == 1) {
3996 if(SMB_VFS_LSEEK(fsp2,fsp2->fd,0,SEEK_END) == -1) {
3997 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
3999 * Stop the copy from occurring.
4001 ret = -1;
4002 src_sbuf.st_size = 0;
4006 if (src_sbuf.st_size)
4007 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
4009 close_file(fsp1,False);
4011 /* Ensure the modtime is set correctly on the destination file. */
4012 fsp2->pending_modtime = src_sbuf.st_mtime;
4015 * As we are opening fsp1 read-only we only expect
4016 * an error on close on fsp2 if we are out of space.
4017 * Thus we don't look at the error return from the
4018 * close of fsp1.
4020 *err_ret = close_file(fsp2,False);
4022 return(ret == (SMB_OFF_T)src_sbuf.st_size);
4025 /****************************************************************************
4026 Reply to a file copy.
4027 ****************************************************************************/
4029 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4031 int outsize = 0;
4032 pstring name;
4033 pstring directory;
4034 pstring mask,newname;
4035 char *p;
4036 int count=0;
4037 int error = ERRnoaccess;
4038 int err = 0;
4039 BOOL has_wild;
4040 BOOL exists=False;
4041 int tid2 = SVAL(inbuf,smb_vwv0);
4042 int ofun = SVAL(inbuf,smb_vwv1);
4043 int flags = SVAL(inbuf,smb_vwv2);
4044 BOOL target_is_directory=False;
4045 BOOL bad_path1 = False;
4046 BOOL bad_path2 = False;
4047 BOOL rc = True;
4048 SMB_STRUCT_STAT sbuf1, sbuf2;
4049 NTSTATUS status;
4051 START_PROFILE(SMBcopy);
4053 *directory = *mask = 0;
4055 p = smb_buf(inbuf);
4056 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status);
4057 if (!NT_STATUS_IS_OK(status)) {
4058 END_PROFILE(SMBcopy);
4059 return ERROR_NT(status);
4061 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status);
4062 if (!NT_STATUS_IS_OK(status)) {
4063 END_PROFILE(SMBcopy);
4064 return ERROR_NT(status);
4067 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
4069 if (tid2 != conn->cnum) {
4070 /* can't currently handle inter share copies XXXX */
4071 DEBUG(3,("Rejecting inter-share copy\n"));
4072 END_PROFILE(SMBcopy);
4073 return ERROR_DOS(ERRSRV,ERRinvdevice);
4076 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
4077 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4079 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
4080 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
4082 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
4084 if ((flags&1) && target_is_directory) {
4085 END_PROFILE(SMBcopy);
4086 return ERROR_DOS(ERRDOS,ERRbadfile);
4089 if ((flags&2) && !target_is_directory) {
4090 END_PROFILE(SMBcopy);
4091 return ERROR_DOS(ERRDOS,ERRbadpath);
4094 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
4095 /* wants a tree copy! XXXX */
4096 DEBUG(3,("Rejecting tree copy\n"));
4097 END_PROFILE(SMBcopy);
4098 return ERROR_DOS(ERRSRV,ERRerror);
4101 p = strrchr_m(name,'/');
4102 if (!p) {
4103 pstrcpy(directory,"./");
4104 pstrcpy(mask,name);
4105 } else {
4106 *p = 0;
4107 pstrcpy(directory,name);
4108 pstrcpy(mask,p+1);
4112 * We should only check the mangled cache
4113 * here if unix_convert failed. This means
4114 * that the path in 'mask' doesn't exist
4115 * on the file system and so we need to look
4116 * for a possible mangle. This patch from
4117 * Tine Smukavec <valentin.smukavec@hermes.si>.
4120 if (!rc && mangle_is_mangled(mask))
4121 mangle_check_cache( mask );
4123 has_wild = ms_has_wild(mask);
4125 if (!has_wild) {
4126 pstrcat(directory,"/");
4127 pstrcat(directory,mask);
4128 if (resolve_wildcards(directory,newname) &&
4129 copy_file(directory,newname,conn,ofun, count,target_is_directory,&err))
4130 count++;
4131 if(!count && err) {
4132 errno = err;
4133 END_PROFILE(SMBcopy);
4134 return(UNIXERROR(ERRHRD,ERRgeneral));
4136 if (!count) {
4137 exists = vfs_file_exist(conn,directory,NULL);
4139 } else {
4140 void *dirptr = NULL;
4141 const char *dname;
4142 pstring destname;
4144 if (check_name(directory,conn))
4145 dirptr = OpenDir(conn, directory, True);
4147 if (dirptr) {
4148 error = ERRbadfile;
4150 if (strequal(mask,"????????.???"))
4151 pstrcpy(mask,"*");
4153 while ((dname = ReadDirName(dirptr))) {
4154 pstring fname;
4155 pstrcpy(fname,dname);
4157 if(!mask_match(fname, mask, case_sensitive))
4158 continue;
4160 error = ERRnoaccess;
4161 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
4162 pstrcpy(destname,newname);
4163 if (resolve_wildcards(fname,destname) &&
4164 copy_file(fname,destname,conn,ofun,
4165 count,target_is_directory,&err))
4166 count++;
4167 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
4169 CloseDir(dirptr);
4173 if (count == 0) {
4174 if(err) {
4175 /* Error on close... */
4176 errno = err;
4177 END_PROFILE(SMBcopy);
4178 return(UNIXERROR(ERRHRD,ERRgeneral));
4181 if (exists) {
4182 END_PROFILE(SMBcopy);
4183 return ERROR_DOS(ERRDOS,error);
4184 } else {
4185 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
4186 unix_ERR_class = ERRDOS;
4187 unix_ERR_code = ERRbadpath;
4189 END_PROFILE(SMBcopy);
4190 return(UNIXERROR(ERRDOS,error));
4194 outsize = set_message(outbuf,1,0,True);
4195 SSVAL(outbuf,smb_vwv0,count);
4197 END_PROFILE(SMBcopy);
4198 return(outsize);
4201 /****************************************************************************
4202 Reply to a setdir.
4203 ****************************************************************************/
4205 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4207 int snum;
4208 int outsize = 0;
4209 BOOL ok = False;
4210 pstring newdir;
4211 NTSTATUS status;
4213 START_PROFILE(pathworks_setdir);
4215 snum = SNUM(conn);
4216 if (!CAN_SETDIR(snum)) {
4217 END_PROFILE(pathworks_setdir);
4218 return ERROR_DOS(ERRDOS,ERRnoaccess);
4221 srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status);
4222 if (!NT_STATUS_IS_OK(status)) {
4223 END_PROFILE(pathworks_setdir);
4224 return ERROR_NT(status);
4227 if (strlen(newdir) == 0) {
4228 ok = True;
4229 } else {
4230 ok = vfs_directory_exist(conn,newdir,NULL);
4231 if (ok)
4232 string_set(&conn->connectpath,newdir);
4235 if (!ok) {
4236 END_PROFILE(pathworks_setdir);
4237 return ERROR_DOS(ERRDOS,ERRbadpath);
4240 outsize = set_message(outbuf,0,0,True);
4241 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
4243 DEBUG(3,("setdir %s\n", newdir));
4245 END_PROFILE(pathworks_setdir);
4246 return(outsize);
4249 /****************************************************************************
4250 Get a lock pid, dealing with large count requests.
4251 ****************************************************************************/
4253 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
4255 if(!large_file_format)
4256 return SVAL(data,SMB_LPID_OFFSET(data_offset));
4257 else
4258 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
4261 /****************************************************************************
4262 Get a lock count, dealing with large count requests.
4263 ****************************************************************************/
4265 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4267 SMB_BIG_UINT count = 0;
4269 if(!large_file_format) {
4270 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4271 } else {
4273 #if defined(HAVE_LONGLONG)
4274 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4275 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4276 #else /* HAVE_LONGLONG */
4279 * NT4.x seems to be broken in that it sends large file (64 bit)
4280 * lockingX calls even if the CAP_LARGE_FILES was *not*
4281 * negotiated. For boxes without large unsigned ints truncate the
4282 * lock count by dropping the top 32 bits.
4285 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4286 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4287 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4288 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4289 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4292 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4293 #endif /* HAVE_LONGLONG */
4296 return count;
4299 #if !defined(HAVE_LONGLONG)
4300 /****************************************************************************
4301 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
4302 ****************************************************************************/
4304 static uint32 map_lock_offset(uint32 high, uint32 low)
4306 unsigned int i;
4307 uint32 mask = 0;
4308 uint32 highcopy = high;
4311 * Try and find out how many significant bits there are in high.
4314 for(i = 0; highcopy; i++)
4315 highcopy >>= 1;
4318 * We use 31 bits not 32 here as POSIX
4319 * lock offsets may not be negative.
4322 mask = (~0) << (31 - i);
4324 if(low & mask)
4325 return 0; /* Fail. */
4327 high <<= (31 - i);
4329 return (high|low);
4331 #endif /* !defined(HAVE_LONGLONG) */
4333 /****************************************************************************
4334 Get a lock offset, dealing with large offset requests.
4335 ****************************************************************************/
4337 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4339 SMB_BIG_UINT offset = 0;
4341 *err = False;
4343 if(!large_file_format) {
4344 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4345 } else {
4347 #if defined(HAVE_LONGLONG)
4348 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4349 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4350 #else /* HAVE_LONGLONG */
4353 * NT4.x seems to be broken in that it sends large file (64 bit)
4354 * lockingX calls even if the CAP_LARGE_FILES was *not*
4355 * negotiated. For boxes without large unsigned ints mangle the
4356 * lock offset by mapping the top 32 bits onto the lower 32.
4359 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4360 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4361 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4362 uint32 new_low = 0;
4364 if((new_low = map_lock_offset(high, low)) == 0) {
4365 *err = True;
4366 return (SMB_BIG_UINT)-1;
4369 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4370 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4371 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4372 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4375 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4376 #endif /* HAVE_LONGLONG */
4379 return offset;
4382 /****************************************************************************
4383 Reply to a lockingX request.
4384 ****************************************************************************/
4386 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4388 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4389 unsigned char locktype = CVAL(inbuf,smb_vwv3);
4390 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4391 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4392 uint16 num_locks = SVAL(inbuf,smb_vwv7);
4393 SMB_BIG_UINT count = 0, offset = 0;
4394 uint16 lock_pid;
4395 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4396 int i;
4397 char *data;
4398 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4399 BOOL err;
4400 BOOL my_lock_ctx = False;
4401 NTSTATUS status;
4403 START_PROFILE(SMBlockingX);
4405 CHECK_FSP(fsp,conn);
4407 data = smb_buf(inbuf);
4409 if (locktype & (LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_CHANGE_LOCKTYPE)) {
4410 /* we don't support these - and CANCEL_LOCK makes w2k
4411 and XP reboot so I don't really want to be
4412 compatible! (tridge) */
4413 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
4416 /* Check if this is an oplock break on a file
4417 we have granted an oplock on.
4419 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
4420 /* Client can insist on breaking to none. */
4421 BOOL break_to_none = (oplocklevel == 0);
4423 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4424 (unsigned int)oplocklevel, fsp->fnum ));
4427 * Make sure we have granted an exclusive or batch oplock on this file.
4430 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
4431 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4432 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4434 /* if this is a pure oplock break request then don't send a reply */
4435 if (num_locks == 0 && num_ulocks == 0) {
4436 END_PROFILE(SMBlockingX);
4437 return -1;
4438 } else {
4439 END_PROFILE(SMBlockingX);
4440 return ERROR_DOS(ERRDOS,ERRlock);
4444 if (remove_oplock(fsp, break_to_none) == False) {
4445 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4446 fsp->fsp_name ));
4449 /* if this is a pure oplock break request then don't send a reply */
4450 if (num_locks == 0 && num_ulocks == 0) {
4451 /* Sanity check - ensure a pure oplock break is not a
4452 chained request. */
4453 if(CVAL(inbuf,smb_vwv0) != 0xff)
4454 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4455 (unsigned int)CVAL(inbuf,smb_vwv0) ));
4456 END_PROFILE(SMBlockingX);
4457 return -1;
4462 * We do this check *after* we have checked this is not a oplock break
4463 * response message. JRA.
4466 release_level_2_oplocks_on_change(fsp);
4468 /* Data now points at the beginning of the list
4469 of smb_unlkrng structs */
4470 for(i = 0; i < (int)num_ulocks; i++) {
4471 lock_pid = get_lock_pid( data, i, large_file_format);
4472 count = get_lock_count( data, i, large_file_format);
4473 offset = get_lock_offset( data, i, large_file_format, &err);
4476 * There is no error code marked "stupid client bug".... :-).
4478 if(err) {
4479 END_PROFILE(SMBlockingX);
4480 return ERROR_DOS(ERRDOS,ERRnoaccess);
4483 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4484 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4486 status = do_unlock(fsp,conn,lock_pid,count,offset);
4487 if (NT_STATUS_V(status)) {
4488 END_PROFILE(SMBlockingX);
4489 return ERROR_NT(status);
4493 /* Setup the timeout in seconds. */
4495 lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000);
4497 /* Now do any requested locks */
4498 data += ((large_file_format ? 20 : 10)*num_ulocks);
4500 /* Data now points at the beginning of the list
4501 of smb_lkrng structs */
4503 for(i = 0; i < (int)num_locks; i++) {
4504 lock_pid = get_lock_pid( data, i, large_file_format);
4505 count = get_lock_count( data, i, large_file_format);
4506 offset = get_lock_offset( data, i, large_file_format, &err);
4509 * There is no error code marked "stupid client bug".... :-).
4511 if(err) {
4512 END_PROFILE(SMBlockingX);
4513 return ERROR_DOS(ERRDOS,ERRnoaccess);
4516 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
4517 (double)offset, (double)count, (unsigned int)lock_pid,
4518 fsp->fsp_name, (int)lock_timeout ));
4520 status = do_lock_spin(fsp,conn,lock_pid, count,offset,
4521 ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &my_lock_ctx);
4522 if (NT_STATUS_V(status)) {
4524 * Interesting fact found by IFSTEST /t LockOverlappedTest...
4525 * Even if it's our own lock context, we need to wait here as
4526 * there may be an unlock on the way.
4527 * So I removed a "&& !my_lock_ctx" from the following
4528 * if statement. JRA.
4530 if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
4532 * A blocking lock was requested. Package up
4533 * this smb into a queued request and push it
4534 * onto the blocking lock queue.
4536 if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) {
4537 END_PROFILE(SMBlockingX);
4538 return -1;
4541 break;
4545 /* If any of the above locks failed, then we must unlock
4546 all of the previous locks (X/Open spec). */
4547 if (i != num_locks && num_locks != 0) {
4549 * Ensure we don't do a remove on the lock that just failed,
4550 * as under POSIX rules, if we have a lock already there, we
4551 * will delete it (and we shouldn't) .....
4553 for(i--; i >= 0; i--) {
4554 lock_pid = get_lock_pid( data, i, large_file_format);
4555 count = get_lock_count( data, i, large_file_format);
4556 offset = get_lock_offset( data, i, large_file_format, &err);
4559 * There is no error code marked "stupid client bug".... :-).
4561 if(err) {
4562 END_PROFILE(SMBlockingX);
4563 return ERROR_DOS(ERRDOS,ERRnoaccess);
4566 do_unlock(fsp,conn,lock_pid,count,offset);
4568 END_PROFILE(SMBlockingX);
4569 return ERROR_NT(status);
4572 set_message(outbuf,2,0,True);
4574 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4575 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4577 END_PROFILE(SMBlockingX);
4578 return chain_reply(inbuf,outbuf,length,bufsize);
4581 /****************************************************************************
4582 Reply to a SMBreadbmpx (read block multiplex) request.
4583 ****************************************************************************/
4585 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4587 ssize_t nread = -1;
4588 ssize_t total_read;
4589 char *data;
4590 SMB_OFF_T startpos;
4591 int outsize;
4592 size_t maxcount;
4593 int max_per_packet;
4594 size_t tcount;
4595 int pad;
4596 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4597 START_PROFILE(SMBreadBmpx);
4599 /* this function doesn't seem to work - disable by default */
4600 if (!lp_readbmpx()) {
4601 END_PROFILE(SMBreadBmpx);
4602 return ERROR_DOS(ERRSRV,ERRuseSTD);
4605 outsize = set_message(outbuf,8,0,True);
4607 CHECK_FSP(fsp,conn);
4608 CHECK_READ(fsp);
4610 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
4611 maxcount = SVAL(inbuf,smb_vwv3);
4613 data = smb_buf(outbuf);
4614 pad = ((long)data)%4;
4615 if (pad)
4616 pad = 4 - pad;
4617 data += pad;
4619 max_per_packet = bufsize-(outsize+pad);
4620 tcount = maxcount;
4621 total_read = 0;
4623 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
4624 END_PROFILE(SMBreadBmpx);
4625 return ERROR_DOS(ERRDOS,ERRlock);
4628 do {
4629 size_t N = MIN(max_per_packet,tcount-total_read);
4631 nread = read_file(fsp,data,startpos,N);
4633 if (nread <= 0)
4634 nread = 0;
4636 if (nread < (ssize_t)N)
4637 tcount = total_read + nread;
4639 set_message(outbuf,8,nread,False);
4640 SIVAL(outbuf,smb_vwv0,startpos);
4641 SSVAL(outbuf,smb_vwv2,tcount);
4642 SSVAL(outbuf,smb_vwv6,nread);
4643 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4645 if (!send_smb(smbd_server_fd(),outbuf))
4646 exit_server("reply_readbmpx: send_smb failed.");
4648 total_read += nread;
4649 startpos += nread;
4650 } while (total_read < (ssize_t)tcount);
4652 END_PROFILE(SMBreadBmpx);
4653 return(-1);
4656 /****************************************************************************
4657 Reply to a SMBsetattrE.
4658 ****************************************************************************/
4660 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4662 struct utimbuf unix_times;
4663 int outsize = 0;
4664 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4665 START_PROFILE(SMBsetattrE);
4667 outsize = set_message(outbuf,0,0,True);
4669 if(!fsp || (fsp->conn != conn)) {
4670 END_PROFILE(SMBgetattrE);
4671 return ERROR_DOS(ERRDOS,ERRbadfid);
4675 * Convert the DOS times into unix times. Ignore create
4676 * time as UNIX can't set this.
4679 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4680 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4683 * Patch from Ray Frush <frush@engr.colostate.edu>
4684 * Sometimes times are sent as zero - ignore them.
4687 if ((unix_times.actime == 0) && (unix_times.modtime == 0)) {
4688 /* Ignore request */
4689 if( DEBUGLVL( 3 ) ) {
4690 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4691 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4693 END_PROFILE(SMBsetattrE);
4694 return(outsize);
4695 } else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) {
4696 /* set modify time = to access time if modify time was 0 */
4697 unix_times.modtime = unix_times.actime;
4700 /* Set the date on this file */
4701 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4702 END_PROFILE(SMBsetattrE);
4703 return ERROR_DOS(ERRDOS,ERRnoaccess);
4706 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4707 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4709 END_PROFILE(SMBsetattrE);
4710 return(outsize);
4714 /* Back from the dead for OS/2..... JRA. */
4716 /****************************************************************************
4717 Reply to a SMBwritebmpx (write block multiplex primary) request.
4718 ****************************************************************************/
4720 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4722 size_t numtowrite;
4723 ssize_t nwritten = -1;
4724 int outsize = 0;
4725 SMB_OFF_T startpos;
4726 size_t tcount;
4727 BOOL write_through;
4728 int smb_doff;
4729 char *data;
4730 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4731 START_PROFILE(SMBwriteBmpx);
4733 CHECK_FSP(fsp,conn);
4734 CHECK_WRITE(fsp);
4735 CHECK_ERROR(fsp);
4737 tcount = SVAL(inbuf,smb_vwv1);
4738 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
4739 write_through = BITSETW(inbuf+smb_vwv7,0);
4740 numtowrite = SVAL(inbuf,smb_vwv10);
4741 smb_doff = SVAL(inbuf,smb_vwv11);
4743 data = smb_base(inbuf) + smb_doff;
4745 /* If this fails we need to send an SMBwriteC response,
4746 not an SMBwritebmpx - set this up now so we don't forget */
4747 SCVAL(outbuf,smb_com,SMBwritec);
4749 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK,False)) {
4750 END_PROFILE(SMBwriteBmpx);
4751 return(ERROR_DOS(ERRDOS,ERRlock));
4754 nwritten = write_file(fsp,data,startpos,numtowrite);
4756 if(lp_syncalways(SNUM(conn)) || write_through)
4757 sync_file(conn,fsp);
4759 if(nwritten < (ssize_t)numtowrite) {
4760 END_PROFILE(SMBwriteBmpx);
4761 return(UNIXERROR(ERRHRD,ERRdiskfull));
4764 /* If the maximum to be written to this file
4765 is greater than what we just wrote then set
4766 up a secondary struct to be attached to this
4767 fd, we will use this to cache error messages etc. */
4769 if((ssize_t)tcount > nwritten) {
4770 write_bmpx_struct *wbms;
4771 if(fsp->wbmpx_ptr != NULL)
4772 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4773 else
4774 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
4775 if(!wbms) {
4776 DEBUG(0,("Out of memory in reply_readmpx\n"));
4777 END_PROFILE(SMBwriteBmpx);
4778 return(ERROR_DOS(ERRSRV,ERRnoresource));
4780 wbms->wr_mode = write_through;
4781 wbms->wr_discard = False; /* No errors yet */
4782 wbms->wr_total_written = nwritten;
4783 wbms->wr_errclass = 0;
4784 wbms->wr_error = 0;
4785 fsp->wbmpx_ptr = wbms;
4788 /* We are returning successfully, set the message type back to
4789 SMBwritebmpx */
4790 SCVAL(outbuf,smb_com,SMBwriteBmpx);
4792 outsize = set_message(outbuf,1,0,True);
4794 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
4796 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4797 fsp->fnum, (int)numtowrite, (int)nwritten ) );
4799 if (write_through && tcount==nwritten) {
4800 /* We need to send both a primary and a secondary response */
4801 smb_setlen(outbuf,outsize - 4);
4802 if (!send_smb(smbd_server_fd(),outbuf))
4803 exit_server("reply_writebmpx: send_smb failed.");
4805 /* Now the secondary */
4806 outsize = set_message(outbuf,1,0,True);
4807 SCVAL(outbuf,smb_com,SMBwritec);
4808 SSVAL(outbuf,smb_vwv0,nwritten);
4811 END_PROFILE(SMBwriteBmpx);
4812 return(outsize);
4815 /****************************************************************************
4816 Reply to a SMBwritebs (write block multiplex secondary) request.
4817 ****************************************************************************/
4819 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4821 size_t numtowrite;
4822 ssize_t nwritten = -1;
4823 int outsize = 0;
4824 SMB_OFF_T startpos;
4825 size_t tcount;
4826 BOOL write_through;
4827 int smb_doff;
4828 char *data;
4829 write_bmpx_struct *wbms;
4830 BOOL send_response = False;
4831 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4832 START_PROFILE(SMBwriteBs);
4834 CHECK_FSP(fsp,conn);
4835 CHECK_WRITE(fsp);
4837 tcount = SVAL(inbuf,smb_vwv1);
4838 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
4839 numtowrite = SVAL(inbuf,smb_vwv6);
4840 smb_doff = SVAL(inbuf,smb_vwv7);
4842 data = smb_base(inbuf) + smb_doff;
4844 /* We need to send an SMBwriteC response, not an SMBwritebs */
4845 SCVAL(outbuf,smb_com,SMBwritec);
4847 /* This fd should have an auxiliary struct attached,
4848 check that it does */
4849 wbms = fsp->wbmpx_ptr;
4850 if(!wbms) {
4851 END_PROFILE(SMBwriteBs);
4852 return(-1);
4855 /* If write through is set we can return errors, else we must cache them */
4856 write_through = wbms->wr_mode;
4858 /* Check for an earlier error */
4859 if(wbms->wr_discard) {
4860 END_PROFILE(SMBwriteBs);
4861 return -1; /* Just discard the packet */
4864 nwritten = write_file(fsp,data,startpos,numtowrite);
4866 if(lp_syncalways(SNUM(conn)) || write_through)
4867 sync_file(conn,fsp);
4869 if (nwritten < (ssize_t)numtowrite) {
4870 if(write_through) {
4871 /* We are returning an error - we can delete the aux struct */
4872 if (wbms)
4873 free((char *)wbms);
4874 fsp->wbmpx_ptr = NULL;
4875 END_PROFILE(SMBwriteBs);
4876 return(ERROR_DOS(ERRHRD,ERRdiskfull));
4878 END_PROFILE(SMBwriteBs);
4879 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4882 /* Increment the total written, if this matches tcount
4883 we can discard the auxiliary struct (hurrah !) and return a writeC */
4884 wbms->wr_total_written += nwritten;
4885 if(wbms->wr_total_written >= tcount) {
4886 if (write_through) {
4887 outsize = set_message(outbuf,1,0,True);
4888 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
4889 send_response = True;
4892 free((char *)wbms);
4893 fsp->wbmpx_ptr = NULL;
4896 if(send_response) {
4897 END_PROFILE(SMBwriteBs);
4898 return(outsize);
4901 END_PROFILE(SMBwriteBs);
4902 return(-1);
4905 /****************************************************************************
4906 Reply to a SMBgetattrE.
4907 ****************************************************************************/
4909 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4911 SMB_STRUCT_STAT sbuf;
4912 int outsize = 0;
4913 int mode;
4914 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4915 START_PROFILE(SMBgetattrE);
4917 outsize = set_message(outbuf,11,0,True);
4919 if(!fsp || (fsp->conn != conn)) {
4920 END_PROFILE(SMBgetattrE);
4921 return ERROR_DOS(ERRDOS,ERRbadfid);
4924 /* Do an fstat on this file */
4925 if(fsp_stat(fsp, &sbuf)) {
4926 END_PROFILE(SMBgetattrE);
4927 return(UNIXERROR(ERRDOS,ERRnoaccess));
4930 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4933 * Convert the times into dos times. Set create
4934 * date to be last modify date as UNIX doesn't save
4935 * this.
4938 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4939 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4940 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4942 if (mode & aDIR) {
4943 SIVAL(outbuf,smb_vwv6,0);
4944 SIVAL(outbuf,smb_vwv8,0);
4945 } else {
4946 uint32 allocation_size = get_allocation_size(fsp, &sbuf);
4947 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4948 SIVAL(outbuf,smb_vwv8,allocation_size);
4950 SSVAL(outbuf,smb_vwv10, mode);
4952 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
4954 END_PROFILE(SMBgetattrE);
4955 return(outsize);