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. 7 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. 12 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. 17 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. 21*/ 22/* 23 This file handles most of the reply_ calls that the server 24 makes to handle specific protocols 25*/ 26 27#include "includes.h" 28 29/* look in server.c for some explanation of these variables */ 30extern enum protocol_types Protocol; 31extern int max_send; 32extern int max_recv; 33extern char magic_char; 34extern int global_oplock_break; 35unsigned int smb_echo_count = 0; 36extern uint32 global_client_caps; 37 38extern BOOL global_encrypted_passwords_negotiated; 39 40/**************************************************************************** 41 Ensure we check the path in *exactly* the same way as W2K. 42 We're assuming here that '/' is not the second byte in any multibyte char 43 set (a safe assumption). '\\' *may* be the second byte in a multibyte char 44 set. 45****************************************************************************/ 46 47NTSTATUS check_path_syntax(pstring destname, const pstring srcname, BOOL allow_wcard_names) 48{ 49 char *d = destname; 50 const char *s = srcname; 51 NTSTATUS ret = NT_STATUS_OK; 52 BOOL start_of_name_component = True; 53 unsigned int num_bad_components = 0; 54 55 while (*s) { 56 if (IS_DIRECTORY_SEP(*s)) { 57 /* 58 * Safe to assume is not the second part of a mb char as this is handled below. 59 */ 60 /* Eat multiple '/' or '\\' */ 61 while (IS_DIRECTORY_SEP(*s)) { 62 s++; 63 } 64 if ((d != destname) && (*s != '\0')) { 65 /* We only care about non-leading or trailing '/' or '\\' */ 66 *d++ = '/'; 67 } 68 69 start_of_name_component = True; 70 continue; 71 } 72 73 if (start_of_name_component) { 74 if ((s[0] == '.') && (s[1] == '.') && (IS_DIRECTORY_SEP(s[2]) || s[2] == '\0')) { 75 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */ 76 77 /* 78 * No mb char starts with '.' so we're safe checking the directory separator here. 79 */ 80 81 /* If we just added a '/' - delete it */ 82 if ((d > destname) && (*(d-1) == '/')) { 83 *(d-1) = '\0'; 84 d--; 85 } 86 87 /* Are we at the start ? Can't go back further if so. */ 88 if (d <= destname) { 89 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD; 90 break; 91 } 92 /* Go back one level... */ 93 /* We know this is safe as '/' cannot be part of a mb sequence. */ 94 /* NOTE - if this assumption is invalid we are not in good shape... */ 95 /* Decrement d first as d points to the *next* char to write into. */ 96 for (d--; d > destname; d--) { 97 if (*d == '/') 98 break; 99 } 100 s += 2; /* Else go past the .. */ 101 /* We're still at the start of a name component, just the previous one. */ 102 103 if (num_bad_components) { 104 /* Hmmm. Should we only decrement the bad_components if 105 we're removing a bad component ? Need to check this. JRA. */ 106 num_bad_components--; 107 } 108 109 continue; 110 111 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_DIRECTORY_SEP(s[1]))) { 112 /* Component of pathname can't be "." only. */ 113 ret = NT_STATUS_OBJECT_NAME_INVALID; 114 num_bad_components++; 115 *d++ = *s++; 116 continue; 117 } 118 } 119 120 if (!(*s & 0x80)) { 121 if (allow_wcard_names) { 122 *d++ = *s++; 123 } else { 124 switch (*s) { 125 case '*': 126 case '?': 127 case '<': 128 case '>': 129 case '"': 130 return NT_STATUS_OBJECT_NAME_INVALID; 131 default: 132 *d++ = *s++; 133 break; 134 } 135 } 136 } else { 137 switch(next_mb_char_size(s)) { 138 case 4: 139 *d++ = *s++; 140 case 3: 141 *d++ = *s++; 142 case 2: 143 *d++ = *s++; 144 case 1: 145 *d++ = *s++; 146 break; 147 default: 148 DEBUG(0,("check_path_syntax: character length assumptions invalid !\n")); 149 *d = '\0'; 150 return NT_STATUS_INVALID_PARAMETER; 151 } 152 } 153 if (start_of_name_component && num_bad_components) { 154 num_bad_components++; 155 } 156 start_of_name_component = False; 157 } 158 159 if (NT_STATUS_EQUAL(ret, NT_STATUS_OBJECT_NAME_INVALID)) { 160 /* For some strange reason being called from findfirst changes 161 the num_components number to cause the error return to change. JRA. */ 162 if (allow_wcard_names) { 163 if (num_bad_components > 2) { 164 ret = NT_STATUS_OBJECT_PATH_NOT_FOUND; 165 } 166 } else { 167 if (num_bad_components > 1) { 168 ret = NT_STATUS_OBJECT_PATH_NOT_FOUND; 169 } 170 } 171 } 172 173 *d = '\0'; 174 return ret; 175} 176 177/**************************************************************************** 178 Pull a string and check the path - provide for error return. 179****************************************************************************/ 180 181size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags, NTSTATUS *err, BOOL allow_wcard_names) 182{ 183 pstring tmppath; 184 char *tmppath_ptr = tmppath; 185 size_t ret; 186#ifdef DEVELOPER 187 SMB_ASSERT(dest_len == sizeof(pstring)); 188#endif 189 190 if (src_len == 0) { 191 ret = srvstr_pull_buf( inbuf, tmppath_ptr, src, dest_len, flags); 192 } else { 193 ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags); 194 } 195 *err = check_path_syntax(dest, tmppath, allow_wcard_names); 196 return ret; 197} 198 199/**************************************************************************** 200 Reply to a special message. 201****************************************************************************/ 202 203int reply_special(char *inbuf,char *outbuf) 204{ 205 int outsize = 4; 206 int msg_type = CVAL(inbuf,0); 207 int msg_flags = CVAL(inbuf,1); 208 fstring name1,name2; 209 char name_type = 0; 210 211 static BOOL already_got_session = False; 212 213 *name1 = *name2 = 0; 214 215 memset(outbuf,'\0',smb_size); 216 217 smb_setlen(outbuf,0); 218 219 switch (msg_type) { 220 case 0x81: /* session request */ 221 222 if (already_got_session) { 223 exit_server("multiple session request not permitted"); 224 } 225 226 SCVAL(outbuf,0,0x82); 227 SCVAL(outbuf,3,0); 228 if (name_len(inbuf+4) > 50 || 229 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) { 230 DEBUG(0,("Invalid name length in session request\n")); 231 return(0); 232 } 233 name_extract(inbuf,4,name1); 234 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2); 235 DEBUG(2,("netbios connect: name1=%s name2=%s\n", 236 name1,name2)); 237 238 set_local_machine_name(name1, True); 239 set_remote_machine_name(name2, True); 240 241 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n", 242 get_local_machine_name(), get_remote_machine_name(), 243 name_type)); 244 245 if (name_type == 'R') { 246 /* We are being asked for a pathworks session --- 247 no thanks! */ 248 SCVAL(outbuf, 0,0x83); 249 break; 250 } 251 252 /* only add the client's machine name to the list 253 of possibly valid usernames if we are operating 254 in share mode security */ 255 if (lp_security() == SEC_SHARE) { 256 add_session_user(get_remote_machine_name()); 257 } 258 259 reload_services(True); 260 reopen_logs(); 261 262 already_got_session = True; 263 break; 264 265 case 0x89: /* session keepalive request 266 (some old clients produce this?) */ 267 SCVAL(outbuf,0,SMBkeepalive); 268 SCVAL(outbuf,3,0); 269 break; 270 271 case 0x82: /* positive session response */ 272 case 0x83: /* negative session response */ 273 case 0x84: /* retarget session response */ 274 DEBUG(0,("Unexpected session response\n")); 275 break; 276 277 case SMBkeepalive: /* session keepalive */ 278 default: 279 return(0); 280 } 281 282 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n", 283 msg_type, msg_flags)); 284 285 return(outsize); 286} 287 288/**************************************************************************** 289 Reply to a tcon. 290****************************************************************************/ 291 292int reply_tcon(connection_struct *conn, 293 char *inbuf,char *outbuf, int dum_size, int dum_buffsize) 294{ 295 const char *service; 296 pstring service_buf; 297 pstring password; 298 pstring dev; 299 int outsize = 0; 300 uint16 vuid = SVAL(inbuf,smb_uid); 301 int pwlen=0; 302 NTSTATUS nt_status; 303 char *p; 304 DATA_BLOB password_blob; 305 306 START_PROFILE(SMBtcon); 307 308 *service_buf = *password = *dev = 0; 309 310 p = smb_buf(inbuf)+1; 311 p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service_buf), STR_TERMINATE) + 1; 312 pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1; 313 p += pwlen; 314 p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1; 315 316 p = strrchr_m(service_buf,'\\'); 317 if (p) { 318 service = p+1; 319 } else { 320 service = service_buf; 321 } 322 323 password_blob = data_blob(password, pwlen+1); 324 325 conn = make_connection(service,password_blob,dev,vuid,&nt_status); 326 327 data_blob_clear_free(&password_blob); 328 329 if (!conn) { 330 END_PROFILE(SMBtcon); 331 return ERROR_NT(nt_status); 332 } 333 334 outsize = set_message(outbuf,2,0,True); 335 SSVAL(outbuf,smb_vwv0,max_recv); 336 SSVAL(outbuf,smb_vwv1,conn->cnum); 337 SSVAL(outbuf,smb_tid,conn->cnum); 338 339 DEBUG(3,("tcon service=%s cnum=%d\n", 340 service, conn->cnum)); 341 342 END_PROFILE(SMBtcon); 343 return(outsize); 344} 345 346/**************************************************************************** 347 Reply to a tcon and X. 348****************************************************************************/ 349 350int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) 351{ 352 fstring service; 353 DATA_BLOB password; 354 355 /* what the cleint thinks the device is */ 356 fstring client_devicetype; 357 /* what the server tells the client the share represents */ 358 const char *server_devicetype; 359 NTSTATUS nt_status; 360 uint16 vuid = SVAL(inbuf,smb_uid); 361 int passlen = SVAL(inbuf,smb_vwv3); 362 pstring path; 363 char *p, *q; 364 extern BOOL global_encrypted_passwords_negotiated; 365 366 START_PROFILE(SMBtconX); 367 368 *service = *client_devicetype = 0; 369 370 /* we might have to close an old one */ 371 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) { 372 close_cnum(conn,vuid); 373 } 374 375 if (passlen > MAX_PASS_LEN) { 376 return ERROR_DOS(ERRDOS,ERRbuftoosmall); 377 } 378 379 if (global_encrypted_passwords_negotiated) { 380 password = data_blob(smb_buf(inbuf),passlen); 381 } else { 382 password = data_blob(smb_buf(inbuf),passlen+1); 383 /* Ensure correct termination */ 384 password.data[passlen]=0; 385 } 386 387 p = smb_buf(inbuf) + passlen; 388 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE); 389 390 /* 391 * the service name can be either: \\server\share 392 * or share directly like on the DELL PowerVault 705 393 */ 394 if (*path=='\\') { 395 q = strchr_m(path+2,'\\'); 396 if (!q) { 397 END_PROFILE(SMBtconX); 398 return(ERROR_DOS(ERRDOS,ERRnosuchshare)); 399 } 400 fstrcpy(service,q+1); 401 } 402 else 403 fstrcpy(service,path); 404 405 p += srvstr_pull(inbuf, client_devicetype, p, sizeof(client_devicetype), 6, STR_ASCII); 406 407 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service)); 408 409 conn = make_connection(service,password,client_devicetype,vuid,&nt_status); 410 411 data_blob_clear_free(&password); 412 413 if (!conn) { 414 END_PROFILE(SMBtconX); 415 return ERROR_NT(nt_status); 416 } 417 418 if ( IS_IPC(conn) ) 419 server_devicetype = "IPC"; 420 else if ( IS_PRINT(conn) ) 421 server_devicetype = "LPT1:"; 422 else 423 server_devicetype = "A:"; 424 425 if (Protocol < PROTOCOL_NT1) { 426 set_message(outbuf,2,0,True); 427 p = smb_buf(outbuf); 428 p += srvstr_push(outbuf, p, server_devicetype, -1, 429 STR_TERMINATE|STR_ASCII); 430 set_message_end(outbuf,p); 431 } else { 432 /* NT sets the fstype of IPC$ to the null string */ 433 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn)); 434 435 set_message(outbuf,3,0,True); 436 437 p = smb_buf(outbuf); 438 p += srvstr_push(outbuf, p, server_devicetype, -1, 439 STR_TERMINATE|STR_ASCII); 440 p += srvstr_push(outbuf, p, fstype, -1, 441 STR_TERMINATE); 442 443 set_message_end(outbuf,p); 444 445 /* what does setting this bit do? It is set by NT4 and 446 may affect the ability to autorun mounted cdroms */ 447 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS| 448 (lp_csc_policy(SNUM(conn)) << 2)); 449 450 init_dfsroot(conn, inbuf, outbuf); 451 } 452 453 454 DEBUG(3,("tconX service=%s \n", 455 service)); 456 457 /* set the incoming and outgoing tid to the just created one */ 458 SSVAL(inbuf,smb_tid,conn->cnum); 459 SSVAL(outbuf,smb_tid,conn->cnum); 460 461 END_PROFILE(SMBtconX); 462 return chain_reply(inbuf,outbuf,length,bufsize); 463} 464 465/**************************************************************************** 466 Reply to an unknown type. 467****************************************************************************/ 468 469int reply_unknown(char *inbuf,char *outbuf) 470{ 471 int type; 472 type = CVAL(inbuf,smb_com); 473 474 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n", 475 smb_fn_name(type), type, type)); 476 477 return(ERROR_DOS(ERRSRV,ERRunknownsmb)); 478} 479 480/**************************************************************************** 481 Reply to an ioctl. 482****************************************************************************/ 483 484int reply_ioctl(connection_struct *conn, 485 char *inbuf,char *outbuf, int dum_size, int dum_buffsize) 486{ 487 uint16 device = SVAL(inbuf,smb_vwv1); 488 uint16 function = SVAL(inbuf,smb_vwv2); 489 uint32 ioctl_code = (device << 16) + function; 490 int replysize, outsize; 491 char *p; 492 START_PROFILE(SMBioctl); 493 494 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code)); 495 496 switch (ioctl_code) { 497 case IOCTL_QUERY_JOB_INFO: 498 replysize = 32; 499 break; 500 default: 501 END_PROFILE(SMBioctl); 502 return(ERROR_DOS(ERRSRV,ERRnosupport)); 503 } 504 505 outsize = set_message(outbuf,8,replysize+1,True); 506 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */ 507 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */ 508 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */ 509 p = smb_buf(outbuf) + 1; /* Allow for alignment */ 510 511 switch (ioctl_code) { 512 case IOCTL_QUERY_JOB_INFO: 513 { 514 files_struct *fsp = file_fsp(inbuf,smb_vwv0); 515 if (!fsp) { 516 END_PROFILE(SMBioctl); 517 return(UNIXERROR(ERRDOS,ERRbadfid)); 518 } 519 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */ 520 srvstr_push(outbuf, p+2, global_myname(), 15, STR_TERMINATE|STR_ASCII); 521 if (conn) { 522 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII); 523 } 524 break; 525 } 526 } 527 528 END_PROFILE(SMBioctl); 529 return outsize; 530} 531 532/**************************************************************************** 533 Reply to a chkpth. 534****************************************************************************/ 535 536int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) 537{ 538 int outsize = 0; 539 pstring name; 540 BOOL ok = False; 541 BOOL bad_path = False; 542 SMB_STRUCT_STAT sbuf; 543 NTSTATUS status; 544 545 START_PROFILE(SMBchkpth); 546 547 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, False); 548 if (!NT_STATUS_IS_OK(status)) { 549 END_PROFILE(SMBchkpth); 550 return ERROR_NT(status); 551 } 552 553 RESOLVE_DFSPATH(name, conn, inbuf, outbuf); 554 555 unix_convert(name,conn,0,&bad_path,&sbuf); 556 if (bad_path) { 557 END_PROFILE(SMBchkpth); 558 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); 559 } 560 561 if (check_name(name,conn)) { 562 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,name,&sbuf) == 0) 563 if (!(ok = S_ISDIR(sbuf.st_mode))) { 564 END_PROFILE(SMBchkpth); 565 return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath); 566 } 567 } 568 569 if (!ok) { 570 /* We special case this - as when a Windows machine 571 is parsing a path is steps through the components 572 one at a time - if a component fails it expects 573 ERRbadpath, not ERRbadfile. 574 */ 575 if(errno == ENOENT) { 576 /* 577 * Windows returns different error codes if 578 * the parent directory is valid but not the 579 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND 580 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND 581 * if the path is invalid. This is different from set_bad_path_error() 582 * in the non-NT error case. 583 */ 584 END_PROFILE(SMBchkpth); 585 return ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpath); 586 } 587 588 END_PROFILE(SMBchkpth); 589 return(UNIXERROR(ERRDOS,ERRbadpath)); 590 } 591 592 outsize = set_message(outbuf,0,0,True); 593 DEBUG(3,("chkpth %s mode=%d\n", name, (int)SVAL(inbuf,smb_vwv0))); 594 595 END_PROFILE(SMBchkpth); 596 return(outsize); 597} 598 599/**************************************************************************** 600 Reply to a getatr. 601****************************************************************************/ 602 603int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) 604{ 605 pstring fname; 606 int outsize = 0; 607 SMB_STRUCT_STAT sbuf; 608 BOOL ok = False; 609 int mode=0; 610 SMB_OFF_T size=0; 611 time_t mtime=0; 612 BOOL bad_path = False; 613 char *p; 614 NTSTATUS status; 615 616 START_PROFILE(SMBgetatr); 617 618 p = smb_buf(inbuf) + 1; 619 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status, False); 620 if (!NT_STATUS_IS_OK(status)) { 621 END_PROFILE(SMBgetatr); 622 return ERROR_NT(status); 623 } 624 625 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); 626 627 /* dos smetimes asks for a stat of "" - it returns a "hidden directory" 628 under WfWg - weird! */ 629 if (! (*fname)) { 630 mode = aHIDDEN | aDIR; 631 if (!CAN_WRITE(conn)) 632 mode |= aRONLY; 633 size = 0; 634 mtime = 0; 635 ok = True; 636 } else { 637 unix_convert(fname,conn,0,&bad_path,&sbuf); 638 if (bad_path) { 639 END_PROFILE(SMBgetatr); 640 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); 641 } 642 if (check_name(fname,conn)) { 643 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,fname,&sbuf) == 0) { 644 mode = dos_mode(conn,fname,&sbuf); 645 size = sbuf.st_size; 646 mtime = sbuf.st_mtime; 647 if (mode & aDIR) 648 size = 0; 649 ok = True; 650 } else { 651 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno))); 652 } 653 } 654 } 655 656 if (!ok) { 657 END_PROFILE(SMBgetatr); 658 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadfile); 659 } 660 661 outsize = set_message(outbuf,10,0,True); 662 663 SSVAL(outbuf,smb_vwv0,mode); 664 if(lp_dos_filetime_resolution(SNUM(conn)) ) 665 put_dos_date3(outbuf,smb_vwv1,mtime & ~1); 666 else 667 put_dos_date3(outbuf,smb_vwv1,mtime); 668 SIVAL(outbuf,smb_vwv3,(uint32)size); 669 670 if (Protocol >= PROTOCOL_NT1) 671 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME); 672 673 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) ); 674 675 END_PROFILE(SMBgetatr); 676 return(outsize); 677} 678 679/**************************************************************************** 680 Reply to a setatr. 681****************************************************************************/ 682 683int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) 684{ 685 pstring fname; 686 int outsize = 0; 687 BOOL ok=False; 688 int mode; 689 time_t mtime; 690 SMB_STRUCT_STAT sbuf; 691 BOOL bad_path = False; 692 char *p; 693 NTSTATUS status; 694 695 START_PROFILE(SMBsetatr); 696 697 p = smb_buf(inbuf) + 1; 698 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status, False); 699 if (!NT_STATUS_IS_OK(status)) { 700 END_PROFILE(SMBsetatr); 701 return ERROR_NT(status); 702 } 703 704 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); 705 706 unix_convert(fname,conn,0,&bad_path,&sbuf); 707 if (bad_path) { 708 END_PROFILE(SMBsetatr); 709 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); 710 } 711 712 mode = SVAL(inbuf,smb_vwv0); 713 mtime = make_unix_date3(inbuf+smb_vwv1); 714 715 if (mode != FILE_ATTRIBUTE_NORMAL) { 716 if (VALID_STAT_OF_DIR(sbuf)) 717 mode |= aDIR; 718 else 719 mode &= ~aDIR; 720 721 if (check_name(fname,conn)) { 722 ok = (file_set_dosmode(conn,fname,mode,&sbuf,False) == 0); 723 } 724 } else { 725 ok = True; 726 } 727 728 if (ok) 729 ok = set_filetime(conn,fname,mtime); 730 731 if (!ok) { 732 END_PROFILE(SMBsetatr); 733 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess); 734 } 735 736 outsize = set_message(outbuf,0,0,True); 737 738 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) ); 739 740 END_PROFILE(SMBsetatr); 741 return(outsize); 742} 743 744/**************************************************************************** 745 Reply to a dskattr. 746****************************************************************************/ 747 748int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) 749{ 750 int outsize = 0; 751 SMB_BIG_UINT dfree,dsize,bsize; 752 START_PROFILE(SMBdskattr); 753 754 if (SMB_VFS_DISK_FREE(conn,".",True,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) { 755 END_PROFILE(SMBdskattr); 756 return(UNIXERROR(ERRHRD,ERRgeneral)); 757 } 758 759 outsize = set_message(outbuf,5,0,True); 760 761 if (Protocol <= PROTOCOL_LANMAN2) { 762 double total_space, free_space; 763 /* we need to scale this to a number that DOS6 can handle. We 764 use floating point so we can handle large drives on systems 765 that don't have 64 bit integers 766 767 we end up displaying a maximum of 2G to DOS systems 768 */ 769 total_space = dsize * (double)bsize; 770 free_space = dfree * (double)bsize; 771 772 dsize = (total_space+63*512) / (64*512); 773 dfree = (free_space+63*512) / (64*512); 774 775 if (dsize > 0xFFFF) dsize = 0xFFFF; 776 if (dfree > 0xFFFF) dfree = 0xFFFF; 777 778 SSVAL(outbuf,smb_vwv0,dsize); 779 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */ 780 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */ 781 SSVAL(outbuf,smb_vwv3,dfree); 782 } else { 783 SSVAL(outbuf,smb_vwv0,dsize); 784 SSVAL(outbuf,smb_vwv1,bsize/512); 785 SSVAL(outbuf,smb_vwv2,512); 786 SSVAL(outbuf,smb_vwv3,dfree); 787 } 788 789 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree)); 790 791 END_PROFILE(SMBdskattr); 792 return(outsize); 793} 794 795/**************************************************************************** 796 Reply to a search. 797 Can be called from SMBsearch, SMBffirst or SMBfunique. 798****************************************************************************/ 799 800int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) 801{ 802 pstring mask; 803 pstring directory; 804 pstring fname; 805 SMB_OFF_T size; 806 int mode; 807 time_t date; 808 int dirtype; 809 int outsize = 0; 810 unsigned int numentries = 0; 811 unsigned int maxentries = 0; 812 BOOL finished = False; 813 char *p; 814 BOOL ok = False; 815 int status_len; 816 pstring path; 817 char status[21]; 818 int dptr_num= -1; 819 BOOL check_descend = False; 820 BOOL expect_close = False; 821 BOOL can_open = True; 822 BOOL bad_path = False; 823 NTSTATUS nt_status; 824 START_PROFILE(SMBsearch); 825 826 *mask = *directory = *fname = 0; 827 828 /* If we were called as SMBffirst then we must expect close. */ 829 if(CVAL(inbuf,smb_com) == SMBffirst) 830 expect_close = True; 831 832 outsize = set_message(outbuf,1,3,True); 833 maxentries = SVAL(inbuf,smb_vwv0); 834 dirtype = SVAL(inbuf,smb_vwv1); 835 p = smb_buf(inbuf) + 1; 836 p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &nt_status, True); 837 if (!NT_STATUS_IS_OK(nt_status)) { 838 END_PROFILE(SMBsearch); 839 return ERROR_NT(nt_status); 840 } 841 842 RESOLVE_DFSPATH(path, conn, inbuf, outbuf); 843 844 p++; 845 status_len = SVAL(p, 0); 846 p += 2; 847 848 /* dirtype &= ~aDIR; */ 849 850 if (status_len == 0) { 851 SMB_STRUCT_STAT sbuf; 852 pstring dir2; 853 854 pstrcpy(directory,path); 855 pstrcpy(dir2,path); 856 unix_convert(directory,conn,0,&bad_path,&sbuf); 857 unix_format(dir2); 858 859 if (!check_name(directory,conn)) 860 can_open = False; 861 862 p = strrchr_m(dir2,'/'); 863 if (p == NULL) { 864 pstrcpy(mask,dir2); 865 *dir2 = 0; 866 } else { 867 *p = 0; 868 pstrcpy(mask,p+1); 869 } 870 871 p = strrchr_m(directory,'/'); 872 if (!p) 873 *directory = 0; 874 else 875 *p = 0; 876 877 if (strlen(directory) == 0) 878 pstrcpy(directory,"."); 879 memset((char *)status,'\0',21); 880 SCVAL(status,0,(dirtype & 0x1F)); 881 } else { 882 int status_dirtype; 883 884 memcpy(status,p,21); 885 status_dirtype = CVAL(status,0) & 0x1F; 886 if (status_dirtype != (dirtype & 0x1F)) 887 dirtype = status_dirtype; 888 889 conn->dirptr = dptr_fetch(status+12,&dptr_num); 890 if (!conn->dirptr) 891 goto SearchEmpty; 892 string_set(&conn->dirpath,dptr_path(dptr_num)); 893 pstrcpy(mask, dptr_wcard(dptr_num)); 894 } 895 896 if (can_open) { 897 p = smb_buf(outbuf) + 3; 898 ok = True; 899 900 if (status_len == 0) { 901 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid)); 902 if (dptr_num < 0) { 903 if(dptr_num == -2) { 904 END_PROFILE(SMBsearch); 905 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnofids); 906 } 907 END_PROFILE(SMBsearch); 908 return ERROR_DOS(ERRDOS,ERRnofids); 909 } 910 if (!dptr_set_wcard_and_attributes(dptr_num, mask, dirtype)) { 911 END_PROFILE(SMBsearch); 912 return ERROR_DOS(ERRDOS,ERRnomem); 913 } 914 } else { 915 dirtype = dptr_attr(dptr_num); 916 } 917 918 DEBUG(4,("dptr_num is %d\n",dptr_num)); 919 920 if (ok) { 921 if ((dirtype&0x1F) == aVOLID) { 922 memcpy(p,status,21); 923 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0); 924 dptr_fill(p+12,dptr_num); 925 if (dptr_zero(p+12) && (status_len==0)) 926 numentries = 1; 927 else 928 numentries = 0; 929 p += DIR_STRUCT_SIZE; 930 } else { 931 unsigned int i; 932 maxentries = MIN(maxentries, ((BUFFER_SIZE - (p - outbuf))/DIR_STRUCT_SIZE)); 933 934 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", 935 conn->dirpath,lp_dontdescend(SNUM(conn)))); 936 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) 937 check_descend = True; 938 939 for (i=numentries;(i<maxentries) && !finished;i++) { 940 finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend); 941 if (!finished) { 942 memcpy(p,status,21); 943 make_dir_struct(p,mask,fname,size,mode,date); 944 dptr_fill(p+12,dptr_num); 945 numentries++; 946 p += DIR_STRUCT_SIZE; 947 } 948 } 949 } 950 } /* if (ok ) */ 951 } 952 953 954 SearchEmpty: 955 956 /* If we were called as SMBffirst with smb_search_id == NULL 957 and no entries were found then return error and close dirptr 958 (X/Open spec) */ 959 960 if (numentries == 0 || !ok) { 961 dptr_close(&dptr_num); 962 } else if(ok && expect_close && status_len == 0) { 963 /* Close the dptr - we know it's gone */ 964 dptr_close(&dptr_num); 965 } 966 967 /* If we were called as SMBfunique, then we can close the dirptr now ! */ 968 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique) { 969 dptr_close(&dptr_num); 970 } 971 972 if ((numentries == 0) && !ms_has_wild(mask)) { 973 return ERROR_BOTH(STATUS_NO_MORE_FILES,ERRDOS,ERRnofiles); 974 } 975 976 SSVAL(outbuf,smb_vwv0,numentries); 977 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE); 978 SCVAL(smb_buf(outbuf),0,5); 979 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE); 980 981 if (Protocol >= PROTOCOL_NT1) 982 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME); 983 984 outsize += DIR_STRUCT_SIZE*numentries; 985 smb_setlen(outbuf,outsize - 4); 986 987 if ((! *directory) && dptr_path(dptr_num)) 988 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num)); 989 990 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n", 991 smb_fn_name(CVAL(inbuf,smb_com)), 992 mask, directory, dirtype, numentries, maxentries ) ); 993 994 END_PROFILE(SMBsearch); 995 return(outsize); 996} 997 998/**************************************************************************** 999 Reply to a fclose (stop directory search). 1000****************************************************************************/ 1001 1002int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) 1003{ 1004 int outsize = 0; 1005 int status_len; 1006 pstring path; 1007 char status[21]; 1008 int dptr_num= -2; 1009 char *p; 1010 NTSTATUS err; 1011 1012 START_PROFILE(SMBfclose); 1013 1014 outsize = set_message(outbuf,1,0,True); 1015 p = smb_buf(inbuf) + 1; 1016 p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err, True); 1017 if (!NT_STATUS_IS_OK(err)) { 1018 END_PROFILE(SMBfclose); 1019 return ERROR_NT(err); 1020 } 1021 p++; 1022 status_len = SVAL(p,0); 1023 p += 2; 1024 1025 if (status_len == 0) { 1026 END_PROFILE(SMBfclose); 1027 return ERROR_DOS(ERRSRV,ERRsrverror); 1028 } 1029 1030 memcpy(status,p,21); 1031 1032 if(dptr_fetch(status+12,&dptr_num)) { 1033 /* Close the dptr - we know it's gone */ 1034 dptr_close(&dptr_num); 1035 } 1036 1037 SSVAL(outbuf,smb_vwv0,0); 1038 1039 DEBUG(3,("search close\n")); 1040 1041 END_PROFILE(SMBfclose); 1042 return(outsize); 1043} 1044 1045/**************************************************************************** 1046 Reply to an open. 1047****************************************************************************/ 1048 1049int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) 1050{ 1051 pstring fname; 1052 int outsize = 0; 1053 int fmode=0; 1054 int share_mode; 1055 SMB_OFF_T size = 0; 1056 time_t mtime=0; 1057 int rmode=0; 1058 SMB_STRUCT_STAT sbuf; 1059 BOOL bad_path = False; 1060 files_struct *fsp; 1061 int oplock_request = CORE_OPLOCK_REQUEST(inbuf); 1062 uint16 dos_attr = SVAL(inbuf,smb_vwv1); 1063 NTSTATUS status; 1064 START_PROFILE(SMBopen); 1065 1066 share_mode = SVAL(inbuf,smb_vwv0); 1067 1068 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status, False); 1069 if (!NT_STATUS_IS_OK(status)) { 1070 END_PROFILE(SMBopen); 1071 return ERROR_NT(status); 1072 } 1073 1074 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); 1075 1076 unix_convert(fname,conn,0,&bad_path,&sbuf); 1077 if (bad_path) { 1078 END_PROFILE(SMBopen); 1079 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); 1080 } 1081 1082 fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 1083 (uint32)dos_attr, oplock_request,&rmode,NULL); 1084 1085 if (!fsp) { 1086 END_PROFILE(SMBopen); 1087 if (open_was_deferred(SVAL(inbuf,smb_mid))) { 1088 /* We have re-scheduled this call. */ 1089 clear_cached_errors(); 1090 return -1; 1091 } 1092 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess); 1093 } 1094 1095 size = sbuf.st_size; 1096 fmode = dos_mode(conn,fname,&sbuf); 1097 mtime = sbuf.st_mtime; 1098 1099 if (fmode & aDIR) { 1100 DEBUG(3,("attempt to open a directory %s\n",fname)); 1101 close_file(fsp,False); 1102 END_PROFILE(SMBopen); 1103 return ERROR_DOS(ERRDOS,ERRnoaccess); 1104 } 1105 1106 outsize = set_message(outbuf,7,0,True); 1107 SSVAL(outbuf,smb_vwv0,fsp->fnum); 1108 SSVAL(outbuf,smb_vwv1,fmode); 1109 if(lp_dos_filetime_resolution(SNUM(conn)) ) 1110 put_dos_date3(outbuf,smb_vwv2,mtime & ~1); 1111 else 1112 put_dos_date3(outbuf,smb_vwv2,mtime); 1113 SIVAL(outbuf,smb_vwv4,(uint32)size); 1114 SSVAL(outbuf,smb_vwv6,rmode); 1115 1116 if (oplock_request && lp_fake_oplocks(SNUM(conn))) 1117 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED); 1118 1119 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) 1120 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED); 1121 END_PROFILE(SMBopen); 1122 return(outsize); 1123} 1124 1125/**************************************************************************** 1126 Reply to an open and X. 1127****************************************************************************/ 1128 1129int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) 1130{ 1131 pstring fname; 1132 int smb_mode = SVAL(inbuf,smb_vwv3); 1133 int smb_attr = SVAL(inbuf,smb_vwv5); 1134 /* Breakout the oplock request bits so we can set the 1135 reply bits separately. */ 1136 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf); 1137 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf); 1138 BOOL oplock_request = ex_oplock_request | core_oplock_request; 1139#if 0 1140 int open_flags = SVAL(inbuf,smb_vwv2); 1141 int smb_sattr = SVAL(inbuf,smb_vwv4); 1142 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6); 1143#endif 1144 int smb_ofun = SVAL(inbuf,smb_vwv8); 1145 SMB_OFF_T size=0; 1146 int fmode=0,mtime=0,rmode=0; 1147 SMB_STRUCT_STAT sbuf; 1148 int smb_action = 0; 1149 BOOL bad_path = False; 1150 files_struct *fsp; 1151 NTSTATUS status; 1152 START_PROFILE(SMBopenX); 1153 1154 /* If it's an IPC, pass off the pipe handler. */ 1155 if (IS_IPC(conn)) { 1156 if (lp_nt_pipe_support()) { 1157 END_PROFILE(SMBopenX); 1158 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize); 1159 } else { 1160 END_PROFILE(SMBopenX); 1161 return ERROR_DOS(ERRSRV,ERRaccess); 1162 } 1163 } 1164 1165 /* XXXX we need to handle passed times, sattr and flags */ 1166 srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status, False); 1167 if (!NT_STATUS_IS_OK(status)) { 1168 END_PROFILE(SMBopenX); 1169 return ERROR_NT(status); 1170 } 1171 1172 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); 1173 1174 unix_convert(fname,conn,0,&bad_path,&sbuf); 1175 if (bad_path) { 1176 END_PROFILE(SMBopenX); 1177 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); 1178 } 1179 1180 fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,(uint32)smb_attr, 1181 oplock_request, &rmode,&smb_action); 1182 1183 if (!fsp) { 1184 END_PROFILE(SMBopenX); 1185 if (open_was_deferred(SVAL(inbuf,smb_mid))) { 1186 /* We have re-scheduled this call. */ 1187 clear_cached_errors(); 1188 return -1; 1189 } 1190 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess); 1191 } 1192 1193 size = sbuf.st_size; 1194 fmode = dos_mode(conn,fname,&sbuf); 1195 mtime = sbuf.st_mtime; 1196 if (fmode & aDIR) { 1197 close_file(fsp,False); 1198 END_PROFILE(SMBopenX); 1199 return ERROR_DOS(ERRDOS,ERRnoaccess); 1200 } 1201 1202 /* If the caller set the extended oplock request bit 1203 and we granted one (by whatever means) - set the 1204 correct bit for extended oplock reply. 1205 */ 1206 1207 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) 1208 smb_action |= EXTENDED_OPLOCK_GRANTED; 1209 1210 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) 1211 smb_action |= EXTENDED_OPLOCK_GRANTED; 1212 1213 /* If the caller set the core oplock request bit 1214 and we granted one (by whatever means) - set the 1215 correct bit for core oplock reply. 1216 */ 1217 1218 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) 1219 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED); 1220 1221 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) 1222 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED); 1223 1224 set_message(outbuf,15,0,True); 1225 SSVAL(outbuf,smb_vwv2,fsp->fnum); 1226 SSVAL(outbuf,smb_vwv3,fmode); 1227 if(lp_dos_filetime_resolution(SNUM(conn)) ) 1228 put_dos_date3(outbuf,smb_vwv4,mtime & ~1); 1229 else 1230 put_dos_date3(outbuf,smb_vwv4,mtime); 1231 SIVAL(outbuf,smb_vwv6,(uint32)size); 1232 SSVAL(outbuf,smb_vwv8,rmode); 1233 SSVAL(outbuf,smb_vwv11,smb_action); 1234 1235 END_PROFILE(SMBopenX); 1236 return chain_reply(inbuf,outbuf,length,bufsize); 1237} 1238 1239/**************************************************************************** 1240 Reply to a SMBulogoffX. 1241****************************************************************************/ 1242 1243int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) 1244{ 1245 uint16 vuid = SVAL(inbuf,smb_uid); 1246 user_struct *vuser = get_valid_user_struct(vuid); 1247 START_PROFILE(SMBulogoffX); 1248 1249 if(vuser == 0) 1250 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid)); 1251 1252 /* in user level security we are supposed to close any files 1253 open by this user */ 1254 if ((vuser != 0) && (lp_security() != SEC_SHARE)) 1255 file_close_user(vuid); 1256 1257 invalidate_vuid(vuid); 1258 1259 set_message(outbuf,2,0,True); 1260 1261 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) ); 1262 1263 END_PROFILE(SMBulogoffX); 1264 return chain_reply(inbuf,outbuf,length,bufsize); 1265} 1266 1267/**************************************************************************** 1268 Reply to a mknew or a create. 1269****************************************************************************/ 1270 1271int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) 1272{ 1273 pstring fname; 1274 int com; 1275 int outsize = 0; 1276 int createmode; 1277 int ofun = 0; 1278 BOOL bad_path = False; 1279 files_struct *fsp; 1280 int oplock_request = CORE_OPLOCK_REQUEST(inbuf); 1281 SMB_STRUCT_STAT sbuf; 1282 NTSTATUS status; 1283 START_PROFILE(SMBcreate); 1284 1285 com = SVAL(inbuf,smb_com); 1286 1287 createmode = SVAL(inbuf,smb_vwv0); 1288 srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status, False); 1289 if (!NT_STATUS_IS_OK(status)) { 1290 END_PROFILE(SMBcreate); 1291 return ERROR_NT(status); 1292 } 1293 1294 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); 1295 1296 unix_convert(fname,conn,0,&bad_path,&sbuf); 1297 if (bad_path) { 1298 END_PROFILE(SMBcreate); 1299 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); 1300 } 1301 1302 if (createmode & aVOLID) 1303 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname)); 1304 1305 if(com == SMBmknew) { 1306 /* We should fail if file exists. */ 1307 ofun = FILE_CREATE_IF_NOT_EXIST; 1308 } else { 1309 /* SMBcreate - Create if file doesn't exist, truncate if it does. */ 1310 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE; 1311 } 1312 1313 /* Open file in dos compatibility share mode. */ 1314 fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB), 1315 ofun, (uint32)createmode, oplock_request, NULL, NULL); 1316 1317 if (!fsp) { 1318 END_PROFILE(SMBcreate); 1319 if (open_was_deferred(SVAL(inbuf,smb_mid))) { 1320 /* We have re-scheduled this call. */ 1321 clear_cached_errors(); 1322 return -1; 1323 } 1324 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess); 1325 } 1326 1327 outsize = set_message(outbuf,1,0,True); 1328 SSVAL(outbuf,smb_vwv0,fsp->fnum); 1329 1330 if (oplock_request && lp_fake_oplocks(SNUM(conn))) 1331 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED); 1332 1333 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) 1334 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED); 1335 1336 DEBUG( 2, ( "new file %s\n", fname ) ); 1337 DEBUG( 3, ( "mknew %s fd=%d dmode=%d\n", fname, fsp->fd, createmode ) ); 1338 1339 END_PROFILE(SMBcreate); 1340 return(outsize); 1341} 1342 1343/**************************************************************************** 1344 Reply to a create temporary file. 1345****************************************************************************/ 1346 1347int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) 1348{ 1349 pstring fname; 1350 int outsize = 0; 1351 int createattr; 1352 BOOL bad_path = False; 1353 files_struct *fsp; 1354 int oplock_request = CORE_OPLOCK_REQUEST(inbuf); 1355 int tmpfd; 1356 SMB_STRUCT_STAT sbuf; 1357 char *p, *s; 1358 NTSTATUS status; 1359 unsigned int namelen; 1360 1361 START_PROFILE(SMBctemp); 1362 1363 createattr = SVAL(inbuf,smb_vwv0); 1364 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status, False); 1365 if (!NT_STATUS_IS_OK(status)) { 1366 END_PROFILE(SMBctemp); 1367 return ERROR_NT(status); 1368 } 1369 if (*fname) { 1370 pstrcat(fname,"/TMXXXXXX"); 1371 } else { 1372 pstrcat(fname,"TMXXXXXX"); 1373 } 1374 1375 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); 1376 1377 unix_convert(fname,conn,0,&bad_path,&sbuf); 1378 if (bad_path) { 1379 END_PROFILE(SMBctemp); 1380 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); 1381 } 1382 1383 tmpfd = smb_mkstemp(fname); 1384 if (tmpfd == -1) { 1385 END_PROFILE(SMBctemp); 1386 return(UNIXERROR(ERRDOS,ERRnoaccess)); 1387 } 1388 1389 SMB_VFS_STAT(conn,fname,&sbuf); 1390 1391 /* Open file in dos compatibility share mode. */ 1392 /* We should fail if file does not exist. */ 1393 fsp = open_file_shared(conn,fname,&sbuf, 1394 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB), 1395 FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST, 1396 (uint32)createattr, oplock_request, NULL, NULL); 1397 1398 /* close fd from smb_mkstemp() */ 1399 close(tmpfd); 1400 1401 if (!fsp) { 1402 END_PROFILE(SMBctemp); 1403 if (open_was_deferred(SVAL(inbuf,smb_mid))) { 1404 /* We have re-scheduled this call. */ 1405 clear_cached_errors(); 1406 return -1; 1407 } 1408 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess); 1409 } 1410 1411 outsize = set_message(outbuf,1,0,True); 1412 SSVAL(outbuf,smb_vwv0,fsp->fnum); 1413 1414 /* the returned filename is relative to the directory */ 1415 s = strrchr_m(fname, '/'); 1416 if (!s) 1417 s = fname; 1418 else 1419 s++; 1420 1421 p = smb_buf(outbuf); 1422#if 0 1423 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only 1424 thing in the byte section. JRA */ 1425 SSVALS(p, 0, -1); /* what is this? not in spec */ 1426#endif 1427 namelen = srvstr_push(outbuf, p, s, -1, STR_ASCII|STR_TERMINATE); 1428 p += namelen; 1429 outsize = set_message_end(outbuf, p); 1430 1431 if (oplock_request && lp_fake_oplocks(SNUM(conn))) 1432 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED); 1433 1434 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) 1435 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED); 1436 1437 DEBUG( 2, ( "created temp file %s\n", fname ) ); 1438 DEBUG( 3, ( "ctemp %s fd=%d umode=%o\n", 1439 fname, fsp->fd, sbuf.st_mode ) ); 1440 1441 END_PROFILE(SMBctemp); 1442 return(outsize); 1443} 1444 1445/******************************************************************* 1446 Check if a user is allowed to rename a file. 1447********************************************************************/ 1448 1449static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, SMB_STRUCT_STAT *pst) 1450{ 1451 int smb_action; 1452 int access_mode; 1453 files_struct *fsp; 1454 uint16 fmode; 1455 1456 if (!CAN_WRITE(conn)) 1457 return NT_STATUS_MEDIA_WRITE_PROTECTED; 1458 1459 fmode = dos_mode(conn,fname,pst); 1460 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) 1461 return NT_STATUS_NO_SUCH_FILE; 1462 1463 if (S_ISDIR(pst->st_mode)) 1464 return NT_STATUS_OK; 1465 1466 /* We need a better way to return NT status codes from open... */ 1467 unix_ERR_class = 0; 1468 unix_ERR_code = 0; 1469 1470 fsp = open_file_shared1(conn, fname, pst, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL), 1471 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action); 1472 1473 if (!fsp) { 1474 NTSTATUS ret = NT_STATUS_ACCESS_DENIED; 1475 if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare) 1476 ret = NT_STATUS_SHARING_VIOLATION; 1477 unix_ERR_class = 0; 1478 unix_ERR_code = 0; 1479 unix_ERR_ntstatus = NT_STATUS_OK; 1480 return ret; 1481 } 1482 close_file(fsp,False); 1483 return NT_STATUS_OK; 1484} 1485 1486/******************************************************************* 1487 Check if a user is allowed to delete a file. 1488********************************************************************/ 1489 1490NTSTATUS can_delete(connection_struct *conn, char *fname, int dirtype, BOOL bad_path, BOOL check_is_at_open) 1491{ 1492 SMB_STRUCT_STAT sbuf; 1493 int fmode; 1494 int smb_action; 1495 int access_mode; 1496 files_struct *fsp; 1497 /* Foxconn, add by MJ., for block delete when bftpd is downloading file, 1498 * 2011.05.18 */ 1499 int fd = -1; 1500 struct flock my_lock; 1501 char file_path[256] = " "; 1502 char slash[5]="/"; 1503 1504 if(conn->origpath != NULL && fname != NULL) 1505 snprintf(file_path, 256, "%s/%s", conn->origpath, fname); 1506 fd = open(file_path, O_RDWR ); 1507 1508 my_lock.l_type = F_WRLCK; 1509 my_lock.l_whence = SEEK_SET; 1510 my_lock.l_start = 0; 1511 my_lock.l_len = 0; /* lock the whole file.*/ 1512 my_lock.l_pid = getpid(); 1513 1514 if(fd >=0) 1515 { 1516 if(!fcntl(fd, F_GETLK, &my_lock)){ 1517 if(my_lock.l_type != F_UNLCK){ 1518 close(fd); 1519 return NT_STATUS_CANNOT_DELETE; 1520 } 1521 } 1522 close(fd); 1523 } 1524 /* Foxconn, end by MJ., 2011.05.18 */ 1525 1526 DEBUG(10,("can_delete: %s, dirtype = %d\n", 1527 fname, dirtype )); 1528 1529 if (!CAN_WRITE(conn)) 1530 return NT_STATUS_MEDIA_WRITE_PROTECTED; 1531 1532 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) { 1533 if(errno == ENOENT) { 1534 if (bad_path) 1535 return NT_STATUS_OBJECT_PATH_NOT_FOUND; 1536 else 1537 return NT_STATUS_OBJECT_NAME_NOT_FOUND; 1538 } 1539 return map_nt_error_from_unix(errno); 1540 } 1541 1542 fmode = dos_mode(conn,fname,&sbuf); 1543 1544 /* Can't delete a directory. */ 1545 if (fmode & aDIR) 1546 return NT_STATUS_FILE_IS_A_DIRECTORY; 1547#if 0 /* JRATEST */ 1548 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */ 1549 return NT_STATUS_OBJECT_NAME_INVALID; 1550#endif /* JRATEST */ 1551 1552 if (!lp_delete_readonly(SNUM(conn))) { 1553 if (fmode & aRONLY) 1554 return NT_STATUS_CANNOT_DELETE; 1555 } 1556 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) 1557 return NT_STATUS_NO_SUCH_FILE; 1558 1559 if (check_is_at_open) { 1560 if (!can_delete_file_in_directory(conn, fname)) { 1561 return NT_STATUS_ACCESS_DENIED; 1562 } 1563 } else { 1564 /* On open checks the open itself will check the share mode, so 1565 don't do it here as we'll get it wrong. */ 1566 1567 /* We need a better way to return NT status codes from open... */ 1568 unix_ERR_class = 0; 1569 unix_ERR_code = 0; 1570 1571 fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL), 1572 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action); 1573 1574 if (!fsp) { 1575 NTSTATUS ret = NT_STATUS_ACCESS_DENIED; 1576 if (!NT_STATUS_IS_OK(unix_ERR_ntstatus)) 1577 ret = unix_ERR_ntstatus; 1578 else if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare) 1579 ret = NT_STATUS_SHARING_VIOLATION; 1580 unix_ERR_class = 0; 1581 unix_ERR_code = 0; 1582 unix_ERR_ntstatus = NT_STATUS_OK; 1583 return ret; 1584 } 1585 close_file(fsp,False); 1586 } 1587 return NT_STATUS_OK; 1588} 1589 1590/**************************************************************************** 1591 The guts of the unlink command, split out so it may be called by the NT SMB 1592 code. 1593****************************************************************************/ 1594 1595NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name) 1596{ 1597 pstring directory; 1598 pstring mask; 1599 char *p; 1600 int count=0; 1601 NTSTATUS error = NT_STATUS_OK; 1602 BOOL has_wild; 1603 BOOL bad_path = False; 1604 BOOL rc = True; 1605 SMB_STRUCT_STAT sbuf; 1606 1607 *directory = *mask = 0; 1608 1609 /* We must check for wildcards in the name given 1610 * directly by the client - before any unmangling. 1611 * This prevents an unmangling of a UNIX name containing 1612 * a DOS wildcard like '*' or '?' from unmangling into 1613 * a wildcard delete which was not intended. 1614 * FIX for #226. JRA. 1615 */ 1616 1617 has_wild = ms_has_wild(name); 1618 1619 rc = unix_convert(name,conn,0,&bad_path,&sbuf); 1620 1621 p = strrchr_m(name,'/'); 1622 if (!p) { 1623 pstrcpy(directory,"."); 1624 pstrcpy(mask,name); 1625 } else { 1626 *p = 0; 1627 pstrcpy(directory,name); 1628 pstrcpy(mask,p+1); 1629 } 1630 1631 /* 1632 * We should only check the mangled cache 1633 * here if unix_convert failed. This means 1634 * that the path in 'mask' doesn't exist 1635 * on the file system and so we need to look 1636 * for a possible mangle. This patch from 1637 * Tine Smukavec <valentin.smukavec@hermes.si>. 1638 */ 1639 1640 if (!rc && mangle_is_mangled(mask)) 1641 mangle_check_cache( mask, sizeof(pstring)-1 ); 1642 1643 if (!has_wild) { 1644 pstrcat(directory,"/"); 1645 pstrcat(directory,mask); 1646 error = can_delete(conn,directory,dirtype,bad_path,False); 1647 if (!NT_STATUS_IS_OK(error)) 1648 return error; 1649 1650 if (SMB_VFS_UNLINK(conn,directory) == 0) { 1651 count++; 1652 } 1653 } else { 1654 struct smb_Dir *dir_hnd = NULL; 1655 const char *dname; 1656 1657 if (check_name(directory,conn)) 1658 dir_hnd = OpenDir(conn, directory); 1659 1660 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then 1661 the pattern matches against the long name, otherwise the short name 1662 We don't implement this yet XXXX 1663 */ 1664 1665 if (dir_hnd) { 1666 long offset = 0; 1667 error = NT_STATUS_NO_SUCH_FILE; 1668 1669 if (strequal(mask,"????????.???")) 1670 pstrcpy(mask,"*"); 1671 1672 while ((dname = ReadDirName(dir_hnd, &offset))) { 1673 SMB_STRUCT_STAT st; 1674 pstring fname; 1675 BOOL sys_direntry = False; 1676 pstrcpy(fname,dname); 1677 1678 if (!is_visible_file(conn, directory, dname, &st, True)) { 1679 continue; 1680 } 1681 1682 /* Quick check for "." and ".." */ 1683 if (fname[0] == '.') { 1684 if (!fname[1] || (fname[1] == '.' && !fname[2])) { 1685 if ((dirtype & FILE_ATTRIBUTE_DIRECTORY) && (dirtype & FILE_ATTRIBUTE_SYSTEM)) { 1686 sys_direntry = True; 1687 } else { 1688 continue; 1689 } 1690 } 1691 } 1692 1693 if(!mask_match(fname, mask, conn->case_sensitive)) 1694 continue; 1695 1696 if (sys_direntry) { 1697 error = NT_STATUS_OBJECT_NAME_INVALID; 1698 DEBUG(3,("unlink_internals: system directory delete denied [%s] mask [%s]\n", 1699 fname, mask)); 1700 break; 1701 } 1702 1703 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname); 1704 error = can_delete(conn,fname,dirtype,bad_path,False); 1705 if (!NT_STATUS_IS_OK(error)) { 1706 continue; 1707 } 1708 if (SMB_VFS_UNLINK(conn,fname) == 0) 1709 count++; 1710 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname)); 1711 } 1712 CloseDir(dir_hnd); 1713 } 1714 } 1715 1716 if (count == 0 && NT_STATUS_IS_OK(error)) { 1717 error = map_nt_error_from_unix(errno); 1718 } 1719 1720 return error; 1721} 1722 1723/**************************************************************************** 1724 Reply to a unlink 1725****************************************************************************/ 1726 1727int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, 1728 int dum_buffsize) 1729{ 1730 int outsize = 0; 1731 pstring name; 1732 int dirtype; 1733 NTSTATUS status; 1734 START_PROFILE(SMBunlink); 1735 1736 dirtype = SVAL(inbuf,smb_vwv0); 1737 1738 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, True); 1739 if (!NT_STATUS_IS_OK(status)) { 1740 END_PROFILE(SMBunlink); 1741 return ERROR_NT(status); 1742 } 1743 1744 RESOLVE_DFSPATH(name, conn, inbuf, outbuf); 1745 1746 DEBUG(3,("reply_unlink : %s\n",name)); 1747 1748 status = unlink_internals(conn, dirtype, name); 1749 if (!NT_STATUS_IS_OK(status)) { 1750 if (open_was_deferred(SVAL(inbuf,smb_mid))) { 1751 /* We have re-scheduled this call. */ 1752 clear_cached_errors(); 1753 return -1; 1754 } 1755 return ERROR_NT(status); 1756 } 1757 1758 /* 1759 * Win2k needs a changenotify request response before it will 1760 * update after a rename.. 1761 */ 1762 process_pending_change_notify_queue((time_t)0); 1763 1764 outsize = set_message(outbuf,0,0,True); 1765 1766 END_PROFILE(SMBunlink); 1767 return outsize; 1768} 1769 1770/**************************************************************************** 1771 Fail for readbraw. 1772****************************************************************************/ 1773 1774static void fail_readraw(void) 1775{ 1776 pstring errstr; 1777 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)", 1778 strerror(errno) ); 1779 exit_server(errstr); 1780} 1781 1782#if defined(WITH_SENDFILE) 1783/**************************************************************************** 1784 Fake (read/write) sendfile. Returns -1 on read or write fail. 1785****************************************************************************/ 1786 1787static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread, char *buf, int bufsize) 1788{ 1789 ssize_t ret=0; 1790 1791 /* Paranioa check... */ 1792 if (nread > bufsize) { 1793 fail_readraw(); 1794 } 1795 1796 if (nread > 0) { 1797 ret = read_file(fsp,buf,startpos,nread); 1798 if (ret == -1) { 1799 return -1; 1800 } 1801 } 1802 1803 /* If we had a short read, fill with zeros. */ 1804 if (ret < nread) { 1805 memset(buf, '\0', nread - ret); 1806 } 1807 1808 if (write_data(smbd_server_fd(),buf,nread) != nread) { 1809 return -1; 1810 } 1811 1812 return (ssize_t)nread; 1813} 1814#endif 1815 1816/**************************************************************************** 1817 Use sendfile in readbraw. 1818****************************************************************************/ 1819 1820void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread, 1821 ssize_t mincount, char *outbuf, int out_buffsize) 1822{ 1823 ssize_t ret=0; 1824 1825#if defined(WITH_SENDFILE) 1826 /* 1827 * We can only use sendfile on a non-chained packet 1828 * but we can use on a non-oplocked file. tridge proved this 1829 * on a train in Germany :-). JRA. 1830 * reply_readbraw has already checked the length. 1831 */ 1832 1833 if (chain_size ==0 && (nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) && lp_use_sendfile(SNUM(conn)) ) { 1834 DATA_BLOB header; 1835 1836 _smb_setlen(outbuf,nread); 1837 header.data = outbuf; 1838 header.length = 4; 1839 header.free = NULL; 1840 1841 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) { 1842 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */ 1843 if (errno == ENOSYS) { 1844 goto normal_readbraw; 1845 } 1846 1847 /* 1848 * Special hack for broken Linux with no working sendfile. If we 1849 * return EINTR we sent the header but not the rest of the data. 1850 * Fake this up by doing read/write calls. 1851 */ 1852 if (errno == EINTR) { 1853 /* Ensure we don't do this again. */ 1854 set_use_sendfile(SNUM(conn), False); 1855 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n")); 1856 1857 if (fake_sendfile(fsp, startpos, nread, outbuf + 4, out_buffsize - 4) == -1) { 1858 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n", 1859 fsp->fsp_name, strerror(errno) )); 1860 exit_server("send_file_readbraw fake_sendfile failed"); 1861 } 1862 return; 1863 } 1864 1865 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n", 1866 fsp->fsp_name, strerror(errno) )); 1867 exit_server("send_file_readbraw sendfile failed"); 1868 } 1869 1870 } 1871 1872 normal_readbraw: 1873 1874#endif 1875 1876 if (nread > 0) { 1877 ret = read_file(fsp,outbuf+4,startpos,nread); 1878#if 0 /* mincount appears to be ignored in a W2K server. JRA. */ 1879 if (ret < mincount) 1880 ret = 0; 1881#else 1882 if (ret < nread) 1883 ret = 0; 1884#endif 1885 } 1886 1887 _smb_setlen(outbuf,ret); 1888 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret) 1889 fail_readraw(); 1890} 1891 1892/**************************************************************************** 1893 Reply to a readbraw (core+ protocol). 1894****************************************************************************/ 1895 1896int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int out_buffsize) 1897{ 1898 extern struct current_user current_user; 1899 ssize_t maxcount,mincount; 1900 size_t nread = 0; 1901 SMB_OFF_T startpos; 1902 char *header = outbuf; 1903 files_struct *fsp; 1904 START_PROFILE(SMBreadbraw); 1905 1906 if (srv_is_signing_active()) { 1907 exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed."); 1908 } 1909 1910 /* 1911 * Special check if an oplock break has been issued 1912 * and the readraw request croses on the wire, we must 1913 * return a zero length response here. 1914 */ 1915 1916 if(global_oplock_break) { 1917 _smb_setlen(header,0); 1918 if (write_data(smbd_server_fd(),header,4) != 4) 1919 fail_readraw(); 1920 DEBUG(5,("readbraw - oplock break finished\n")); 1921 END_PROFILE(SMBreadbraw); 1922 return -1; 1923 } 1924 1925 fsp = file_fsp(inbuf,smb_vwv0); 1926 1927 if (!FNUM_OK(fsp,conn) || !fsp->can_read) { 1928 /* 1929 * fsp could be NULL here so use the value from the packet. JRA. 1930 */ 1931 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0))); 1932 _smb_setlen(header,0); 1933 if (write_data(smbd_server_fd(),header,4) != 4) 1934 fail_readraw(); 1935 END_PROFILE(SMBreadbraw); 1936 return(-1); 1937 } 1938 1939 CHECK_FSP(fsp,conn); 1940 1941 flush_write_cache(fsp, READRAW_FLUSH); 1942 1943 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1); 1944 if(CVAL(inbuf,smb_wct) == 10) { 1945 /* 1946 * This is a large offset (64 bit) read. 1947 */ 1948#ifdef LARGE_SMB_OFF_T 1949 1950 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32); 1951 1952#else /* !LARGE_SMB_OFF_T */ 1953 1954 /* 1955 * Ensure we haven't been sent a >32 bit offset. 1956 */ 1957 1958 if(IVAL(inbuf,smb_vwv8) != 0) { 1959 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \ 196064 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) )); 1961 _smb_setlen(header,0); 1962 if (write_data(smbd_server_fd(),header,4) != 4) 1963 fail_readraw(); 1964 END_PROFILE(SMBreadbraw); 1965 return(-1); 1966 } 1967 1968#endif /* LARGE_SMB_OFF_T */ 1969 1970 if(startpos < 0) { 1971 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos )); 1972 _smb_setlen(header,0); 1973 if (write_data(smbd_server_fd(),header,4) != 4) 1974 fail_readraw(); 1975 END_PROFILE(SMBreadbraw); 1976 return(-1); 1977 } 1978 } 1979 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF); 1980 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF); 1981 1982 /* ensure we don't overrun the packet size */ 1983 maxcount = MIN(65535,maxcount); 1984 1985 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) { 1986 SMB_OFF_T size = fsp->size; 1987 SMB_OFF_T sizeneeded = startpos + maxcount; 1988 1989 if (size < sizeneeded) { 1990 SMB_STRUCT_STAT st; 1991 if (SMB_VFS_FSTAT(fsp,fsp->fd,&st) == 0) 1992 size = st.st_size; 1993 if (!fsp->can_write) 1994 fsp->size = size; 1995 } 1996 1997 if (startpos >= size) 1998 nread = 0; 1999 else 2000 nread = MIN(maxcount,(size - startpos)); 2001 } 2002 2003#if 0 /* mincount appears to be ignored in a W2K server. JRA. */ 2004 if (nread < mincount) 2005 nread = 0; 2006#endif 2007 2008 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos, 2009 (int)maxcount, (int)mincount, (int)nread ) ); 2010 2011 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf, out_buffsize); 2012 2013 DEBUG(5,("readbraw finished\n")); 2014 END_PROFILE(SMBreadbraw); 2015 return -1; 2016} 2017 2018/**************************************************************************** 2019 Reply to a lockread (core+ protocol). 2020****************************************************************************/ 2021 2022int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz) 2023{ 2024 ssize_t nread = -1; 2025 char *data; 2026 int outsize = 0; 2027 SMB_OFF_T startpos; 2028 size_t numtoread; 2029 NTSTATUS status; 2030 files_struct *fsp = file_fsp(inbuf,smb_vwv0); 2031 BOOL my_lock_ctx = False; 2032 START_PROFILE(SMBlockread); 2033 2034 CHECK_FSP(fsp,conn); 2035 CHECK_READ(fsp); 2036 2037 release_level_2_oplocks_on_change(fsp); 2038 2039 numtoread = SVAL(inbuf,smb_vwv1); 2040 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2); 2041 2042 outsize = set_message(outbuf,5,3,True); 2043 numtoread = MIN(BUFFER_SIZE-outsize,numtoread); 2044 data = smb_buf(outbuf) + 3; 2045 2046 /* 2047 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+ 2048 * protocol request that predates the read/write lock concept. 2049 * Thus instead of asking for a read lock here we need to ask 2050 * for a write lock. JRA. 2051 * Note that the requested lock size is unaffected by max_recv. 2052 */ 2053 2054 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), 2055 (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, &my_lock_ctx); 2056 2057 if (NT_STATUS_V(status)) { 2058#if 0 2059 /* 2060 * We used to make lockread a blocking lock. It turns out 2061 * that this isn't on W2k. Found by the Samba 4 RAW-READ torture 2062 * tester. JRA. 2063 */ 2064 2065 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) { 2066 /* 2067 * A blocking lock was requested. Package up 2068 * this smb into a queued request and push it 2069 * onto the blocking lock queue. 2070 */ 2071 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)startpos, 2072 (SMB_BIG_UINT)numtoread)) { 2073 END_PROFILE(SMBlockread); 2074 return -1; 2075 } 2076 } 2077#endif 2078 END_PROFILE(SMBlockread); 2079 return ERROR_NT(status); 2080 } 2081 2082 /* 2083 * However the requested READ size IS affected by max_recv. Insanity.... JRA. 2084 */ 2085 2086 if (numtoread > max_recv) { 2087 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \ 2088Returning short read of maximum allowed for compatibility with Windows 2000.\n", 2089 (unsigned int)numtoread, (unsigned int)max_recv )); 2090 numtoread = MIN(numtoread,max_recv); 2091 } 2092 nread = read_file(fsp,data,startpos,numtoread); 2093 2094 if (nread < 0) { 2095 END_PROFILE(SMBlockread); 2096 return(UNIXERROR(ERRDOS,ERRnoaccess)); 2097 } 2098 2099 outsize += nread; 2100 SSVAL(outbuf,smb_vwv0,nread); 2101 SSVAL(outbuf,smb_vwv5,nread+3); 2102 SSVAL(smb_buf(outbuf),1,nread); 2103 2104 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n", 2105 fsp->fnum, (int)numtoread, (int)nread)); 2106 2107 END_PROFILE(SMBlockread); 2108 return(outsize); 2109} 2110 2111/**************************************************************************** 2112 Reply to a read. 2113****************************************************************************/ 2114 2115int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize) 2116{ 2117 size_t numtoread; 2118 ssize_t nread = 0; 2119 char *data; 2120 SMB_OFF_T startpos; 2121 int outsize = 0; 2122 files_struct *fsp = file_fsp(inbuf,smb_vwv0); 2123 START_PROFILE(SMBread); 2124 2125 CHECK_FSP(fsp,conn); 2126 CHECK_READ(fsp); 2127 2128 numtoread = SVAL(inbuf,smb_vwv1); 2129 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2); 2130 2131 outsize = set_message(outbuf,5,3,True); 2132 numtoread = MIN(BUFFER_SIZE-outsize,numtoread); 2133 /* 2134 * The requested read size cannot be greater than max_recv. JRA. 2135 */ 2136 if (numtoread > max_recv) { 2137 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \ 2138Returning short read of maximum allowed for compatibility with Windows 2000.\n", 2139 (unsigned int)numtoread, (unsigned int)max_recv )); 2140 numtoread = MIN(numtoread,max_recv); 2141 } 2142 2143 data = smb_buf(outbuf) + 3; 2144 2145 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) { 2146 END_PROFILE(SMBread); 2147 return ERROR_DOS(ERRDOS,ERRlock); 2148 } 2149 2150 if (numtoread > 0) 2151 nread = read_file(fsp,data,startpos,numtoread); 2152 2153 if (nread < 0) { 2154 END_PROFILE(SMBread); 2155 return(UNIXERROR(ERRDOS,ERRnoaccess)); 2156 } 2157 2158 outsize += nread; 2159 SSVAL(outbuf,smb_vwv0,nread); 2160 SSVAL(outbuf,smb_vwv5,nread+3); 2161 SCVAL(smb_buf(outbuf),0,1); 2162 SSVAL(smb_buf(outbuf),1,nread); 2163 2164 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n", 2165 fsp->fnum, (int)numtoread, (int)nread ) ); 2166 2167 END_PROFILE(SMBread); 2168 return(outsize); 2169} 2170 2171/**************************************************************************** 2172 Reply to a read and X - possibly using sendfile. 2173****************************************************************************/ 2174 2175/* Foxconn modified start pling 11/24/2009 */ 2176//int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length, int len_outbuf, 2177// files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt) 2178int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length, int len_outbuf, 2179 files_struct *fsp, SMB_BIG_UINT startpos, size_t smb_maxcnt) 2180/* Foxconn modified end pling 11/24/2009 */ 2181{ 2182 int outsize = 0; 2183 ssize_t nread = -1; 2184 char *data = smb_buf(outbuf); 2185 2186#if defined(WITH_SENDFILE) 2187 /* 2188 * We can only use sendfile on a non-chained packet 2189 * but we can use on a non-oplocked file. tridge proved this 2190 * on a train in Germany :-). JRA. 2191 */ 2192 2193 if (chain_size ==0 && (CVAL(inbuf,smb_vwv0) == 0xFF) && lp_use_sendfile(SNUM(conn)) && 2194 (lp_write_cache_size(SNUM(conn)) == 0) ) { 2195 SMB_STRUCT_STAT sbuf; 2196 DATA_BLOB header; 2197 2198 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) 2199 return(UNIXERROR(ERRDOS,ERRnoaccess)); 2200 2201 if (startpos > sbuf.st_size) 2202 goto normal_read; 2203 2204 if (smb_maxcnt > (sbuf.st_size - startpos)) 2205 smb_maxcnt = (sbuf.st_size - startpos); 2206 2207 if (smb_maxcnt == 0) 2208 goto normal_read; 2209 2210 /* 2211 * Set up the packet header before send. We 2212 * assume here the sendfile will work (get the 2213 * correct amount of data). 2214 */ 2215 2216 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */ 2217 SSVAL(outbuf,smb_vwv5,smb_maxcnt); 2218 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf)); 2219 SSVAL(outbuf,smb_vwv7,((smb_maxcnt >> 16) & 1)); 2220 SSVAL(smb_buf(outbuf),-2,smb_maxcnt); 2221 SCVAL(outbuf,smb_vwv0,0xFF); 2222 set_message(outbuf,12,smb_maxcnt,False); 2223 header.data = outbuf; 2224 header.length = data - outbuf; 2225 header.free = NULL; 2226 2227 /* Foxconn modified start pling 11/25/2009 */ 2228 /* force 'startpos' to 32 bit since the 'sendfile' API can 2229 * only handle 32 bit offset. 2230 */ 2231 //if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt)) == -1) { 2232 if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, (unsigned long)startpos, smb_maxcnt)) == -1) { 2233 /* Foxconn modified end pling 11/25/2009 */ 2234 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */ 2235 if (errno == ENOSYS) { 2236 goto normal_read; 2237 } 2238 2239 /* 2240 * Special hack for broken Linux with no working sendfile. If we 2241 * return EINTR we sent the header but not the rest of the data. 2242 * Fake this up by doing read/write calls. 2243 */ 2244 2245 if (errno == EINTR) { 2246 /* Ensure we don't do this again. */ 2247 set_use_sendfile(SNUM(conn), False); 2248 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n")); 2249 2250 if ((nread = fake_sendfile(fsp, startpos, smb_maxcnt, data, 2251 len_outbuf - (data-outbuf))) == -1) { 2252 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n", 2253 fsp->fsp_name, strerror(errno) )); 2254 exit_server("send_file_readX: fake_sendfile failed"); 2255 } 2256 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n", 2257 fsp->fnum, (int)smb_maxcnt, (int)nread ) ); 2258 /* Returning -1 here means successful sendfile. */ 2259 return -1; 2260 } 2261 2262 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n", 2263 fsp->fsp_name, strerror(errno) )); 2264 exit_server("send_file_readX sendfile failed"); 2265 } 2266 2267 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n", 2268 fsp->fnum, (int)smb_maxcnt, (int)nread ) ); 2269 /* Returning -1 here means successful sendfile. */ 2270 return -1; 2271 } 2272 2273 normal_read: 2274 2275#endif 2276 2277 nread = read_file(fsp,data,startpos,smb_maxcnt); 2278 2279 if (nread < 0) { 2280 END_PROFILE(SMBreadX); 2281 return(UNIXERROR(ERRDOS,ERRnoaccess)); 2282 } 2283 2284 outsize = set_message(outbuf,12,nread,False); 2285 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */ 2286 SSVAL(outbuf,smb_vwv5,nread); 2287 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf)); 2288 SSVAL(outbuf,smb_vwv7,((nread >> 16) & 1)); 2289 SSVAL(smb_buf(outbuf),-2,nread); 2290 2291 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n", 2292 fsp->fnum, (int)smb_maxcnt, (int)nread ) ); 2293 2294 /* Returning the number of bytes we want to send back - including header. */ 2295 return outsize; 2296} 2297 2298/**************************************************************************** 2299 Reply to a read and X. 2300****************************************************************************/ 2301 2302int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) 2303{ 2304 files_struct *fsp = file_fsp(inbuf,smb_vwv2); 2305 /* Foxconn modified start pling 11/24/2009 */ 2306 //SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3); 2307 SMB_BIG_UINT startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3); 2308 /* Foxconn modified end pling 11/24/2009 */ 2309 ssize_t nread = -1; 2310 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5); 2311#if 0 2312 size_t smb_mincnt = SVAL(inbuf,smb_vwv6); 2313#endif 2314 2315 START_PROFILE(SMBreadX); 2316 2317 /* If it's an IPC, pass off the pipe handler. */ 2318 if (IS_IPC(conn)) { 2319 END_PROFILE(SMBreadX); 2320 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize); 2321 } 2322 2323 CHECK_FSP(fsp,conn); 2324 CHECK_READ(fsp); 2325 2326 set_message(outbuf,12,0,True); 2327 2328 if (global_client_caps & CAP_LARGE_READX) { 2329 if (SVAL(inbuf,smb_vwv7) == 1) { 2330 smb_maxcnt |= (1<<16); 2331 } 2332 if (smb_maxcnt > BUFFER_SIZE) { 2333 DEBUG(0,("reply_read_and_X - read too large (%u) for reply buffer %u\n", 2334 (unsigned int)smb_maxcnt, (unsigned int)BUFFER_SIZE)); 2335 END_PROFILE(SMBreadX); 2336 return ERROR_NT(NT_STATUS_INVALID_PARAMETER); 2337 } 2338 } 2339 2340 /* Foxconn added start pling 11/24/2009 */ 2341 startpos &= 0xFFFFFFFFUL; 2342 /* Foxconn added end pling 11/24/2009 */ 2343 2344 if(CVAL(inbuf,smb_wct) == 12) { 2345#ifdef LARGE_SMB_OFF_T 2346 /* 2347 * This is a large offset (64 bit) read. 2348 */ 2349 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32); 2350 2351#else /* !LARGE_SMB_OFF_T */ 2352 2353 /* Foxconn modified start pling 11/24/2009 */ 2354#if 0 2355 /* 2356 * Ensure we haven't been sent a >32 bit offset. 2357 */ 2358 2359 if(IVAL(inbuf,smb_vwv10) != 0) { 2360 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \ 236164 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) )); 2362 END_PROFILE(SMBreadX); 2363 return ERROR_DOS(ERRDOS,ERRbadaccess); 2364 } 2365#endif 2366 startpos |= (((SMB_BIG_UINT)IVAL(inbuf,smb_vwv10)) << 32); 2367 /* Foxconn modified end pling 11/24/2009 */ 2368 2369#endif /* LARGE_SMB_OFF_T */ 2370 2371 } 2372 2373 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) { 2374 END_PROFILE(SMBreadX); 2375 return ERROR_DOS(ERRDOS,ERRlock); 2376 } 2377 2378 nread = send_file_readX(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt); 2379 if (nread != -1) 2380 nread = chain_reply(inbuf,outbuf,length,bufsize); 2381 2382 END_PROFILE(SMBreadX); 2383 return nread; 2384} 2385 2386/**************************************************************************** 2387 Reply to a writebraw (core+ or LANMAN1.0 protocol). 2388****************************************************************************/ 2389 2390int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize) 2391{ 2392 ssize_t nwritten=0; 2393 ssize_t total_written=0; 2394 size_t numtowrite=0; 2395 size_t tcount; 2396 SMB_OFF_T startpos; 2397 char *data=NULL; 2398 BOOL write_through; 2399 files_struct *fsp = file_fsp(inbuf,smb_vwv0); 2400 int outsize = 0; 2401 START_PROFILE(SMBwritebraw); 2402 2403 if (srv_is_signing_active()) { 2404 exit_server("reply_writebraw: SMB signing is active - raw reads/writes are disallowed."); 2405 } 2406 2407 CHECK_FSP(fsp,conn); 2408 CHECK_WRITE(fsp); 2409 2410 tcount = IVAL(inbuf,smb_vwv1); 2411 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3); 2412 write_through = BITSETW(inbuf+smb_vwv7,0); 2413 2414 /* We have to deal with slightly different formats depending 2415 on whether we are using the core+ or lanman1.0 protocol */ 2416 2417 if(Protocol <= PROTOCOL_COREPLUS) { 2418 numtowrite = SVAL(smb_buf(inbuf),-2); 2419 data = smb_buf(inbuf); 2420 } else { 2421 numtowrite = SVAL(inbuf,smb_vwv10); 2422 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11); 2423 } 2424 2425 /* force the error type */ 2426 SCVAL(inbuf,smb_com,SMBwritec); 2427 SCVAL(outbuf,smb_com,SMBwritec); 2428 2429 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) { 2430 END_PROFILE(SMBwritebraw); 2431 return(ERROR_DOS(ERRDOS,ERRlock)); 2432 } 2433 2434 if (numtowrite>0) 2435 nwritten = write_file(fsp,data,startpos,numtowrite); 2436 2437 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n", 2438 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through)); 2439 2440 if (nwritten < (ssize_t)numtowrite) { 2441 END_PROFILE(SMBwritebraw); 2442 return(UNIXERROR(ERRHRD,ERRdiskfull)); 2443 } 2444 2445 total_written = nwritten; 2446 2447 /* Return a message to the redirector to tell it to send more bytes */ 2448 SCVAL(outbuf,smb_com,SMBwritebraw); 2449 SSVALS(outbuf,smb_vwv0,-1); 2450 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True); 2451 if (!send_smb(smbd_server_fd(),outbuf)) 2452 exit_server("reply_writebraw: send_smb failed."); 2453 2454 /* Now read the raw data into the buffer and write it */ 2455 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) { 2456 exit_server("secondary writebraw failed"); 2457 } 2458 2459 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */ 2460 numtowrite = smb_len(inbuf); 2461 2462 /* Set up outbuf to return the correct return */ 2463 outsize = set_message(outbuf,1,0,True); 2464 SCVAL(outbuf,smb_com,SMBwritec); 2465 SSVAL(outbuf,smb_vwv0,total_written); 2466 2467 if (numtowrite != 0) { 2468 2469 if (numtowrite > BUFFER_SIZE) { 2470 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n", 2471 (unsigned int)numtowrite )); 2472 exit_server("secondary writebraw failed"); 2473 } 2474 2475 if (tcount > nwritten+numtowrite) { 2476 DEBUG(3,("Client overestimated the write %d %d %d\n", 2477 (int)tcount,(int)nwritten,(int)numtowrite)); 2478 } 2479 2480 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) { 2481 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n", 2482 strerror(errno) )); 2483 exit_server("secondary writebraw failed"); 2484 } 2485 2486 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite); 2487 2488 if (nwritten < (ssize_t)numtowrite) { 2489 SCVAL(outbuf,smb_rcls,ERRHRD); 2490 SSVAL(outbuf,smb_err,ERRdiskfull); 2491 } 2492 2493 if (nwritten > 0) 2494 total_written += nwritten; 2495 } 2496 2497 if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn))) 2498 sync_file(conn,fsp); 2499 2500 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n", 2501 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written)); 2502 2503 /* we won't return a status if write through is not selected - this follows what WfWg does */ 2504 END_PROFILE(SMBwritebraw); 2505 if (!write_through && total_written==tcount) { 2506 2507#if RABBIT_PELLET_FIX 2508 /* 2509 * Fix for "rabbit pellet" mode, trigger an early TCP ack by 2510 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA. 2511 */ 2512 if (!send_keepalive(smbd_server_fd())) 2513 exit_server("reply_writebraw: send of keepalive failed"); 2514#endif 2515 return(-1); 2516 } 2517 2518 return(outsize); 2519} 2520 2521/**************************************************************************** 2522 Reply to a writeunlock (core+). 2523****************************************************************************/ 2524 2525int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, 2526 int size, int dum_buffsize) 2527{ 2528 ssize_t nwritten = -1; 2529 size_t numtowrite; 2530 SMB_OFF_T startpos; 2531 char *data; 2532 NTSTATUS status = NT_STATUS_OK; 2533 files_struct *fsp = file_fsp(inbuf,smb_vwv0); 2534 int outsize = 0; 2535 START_PROFILE(SMBwriteunlock); 2536 2537 CHECK_FSP(fsp,conn); 2538 CHECK_WRITE(fsp); 2539 2540 numtowrite = SVAL(inbuf,smb_vwv1); 2541 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2); 2542 data = smb_buf(inbuf) + 3; 2543 2544 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) { 2545 END_PROFILE(SMBwriteunlock); 2546 return ERROR_DOS(ERRDOS,ERRlock); 2547 } 2548 2549 /* The special X/Open SMB protocol handling of 2550 zero length writes is *NOT* done for 2551 this call */ 2552 if(numtowrite == 0) 2553 nwritten = 0; 2554 else 2555 nwritten = write_file(fsp,data,startpos,numtowrite); 2556 2557 if (lp_syncalways(SNUM(conn))) 2558 sync_file(conn,fsp); 2559 2560 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) { 2561 END_PROFILE(SMBwriteunlock); 2562 return(UNIXERROR(ERRHRD,ERRdiskfull)); 2563 } 2564 2565 if (numtowrite) { 2566 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite, 2567 (SMB_BIG_UINT)startpos); 2568 if (NT_STATUS_V(status)) { 2569 END_PROFILE(SMBwriteunlock); 2570 return ERROR_NT(status); 2571 } 2572 } 2573 2574 outsize = set_message(outbuf,1,0,True); 2575 2576 SSVAL(outbuf,smb_vwv0,nwritten); 2577 2578 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n", 2579 fsp->fnum, (int)numtowrite, (int)nwritten)); 2580 2581 END_PROFILE(SMBwriteunlock); 2582 return outsize; 2583} 2584 2585/**************************************************************************** 2586 Reply to a write. 2587****************************************************************************/ 2588 2589int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize) 2590{ 2591 size_t numtowrite; 2592 ssize_t nwritten = -1; 2593 SMB_OFF_T startpos; 2594 char *data; 2595 files_struct *fsp = file_fsp(inbuf,smb_vwv0); 2596 int outsize = 0; 2597 START_PROFILE(SMBwrite); 2598 2599 /* If it's an IPC, pass off the pipe handler. */ 2600 if (IS_IPC(conn)) { 2601 END_PROFILE(SMBwrite); 2602 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize); 2603 } 2604 2605 CHECK_FSP(fsp,conn); 2606 CHECK_WRITE(fsp); 2607 2608 numtowrite = SVAL(inbuf,smb_vwv1); 2609 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2); 2610 data = smb_buf(inbuf) + 3; 2611 2612 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) { 2613 END_PROFILE(SMBwrite); 2614 return ERROR_DOS(ERRDOS,ERRlock); 2615 } 2616 2617 /* 2618 * X/Open SMB protocol says that if smb_vwv1 is 2619 * zero then the file size should be extended or 2620 * truncated to the size given in smb_vwv[2-3]. 2621 */ 2622 2623 if(numtowrite == 0) { 2624 /* 2625 * This is actually an allocate call, and set EOF. JRA. 2626 */ 2627 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos); 2628 if (nwritten < 0) { 2629 END_PROFILE(SMBwrite); 2630 return ERROR_NT(NT_STATUS_DISK_FULL); 2631 } 2632 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos); 2633 if (nwritten < 0) { 2634 END_PROFILE(SMBwrite); 2635 return ERROR_NT(NT_STATUS_DISK_FULL); 2636 } 2637 } else 2638 nwritten = write_file(fsp,data,startpos,numtowrite); 2639 2640 if (lp_syncalways(SNUM(conn))) 2641 sync_file(conn,fsp); 2642 2643 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) { 2644 END_PROFILE(SMBwrite); 2645 return(UNIXERROR(ERRHRD,ERRdiskfull)); 2646 } 2647 2648 outsize = set_message(outbuf,1,0,True); 2649 2650 SSVAL(outbuf,smb_vwv0,nwritten); 2651 2652 if (nwritten < (ssize_t)numtowrite) { 2653 SCVAL(outbuf,smb_rcls,ERRHRD); 2654 SSVAL(outbuf,smb_err,ERRdiskfull); 2655 } 2656 2657 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten)); 2658 2659 END_PROFILE(SMBwrite); 2660 return(outsize); 2661} 2662 2663/**************************************************************************** 2664 Reply to a write and X. 2665****************************************************************************/ 2666 2667int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) 2668{ 2669 files_struct *fsp = file_fsp(inbuf,smb_vwv2); 2670 /* Foxconn modified start pling 11/24/2009 */ 2671 //SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3); 2672 SMB_BIG_UINT startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3); 2673 /* Foxconn modified end pling 11/24/2009 */ 2674 size_t numtowrite = SVAL(inbuf,smb_vwv10); 2675 BOOL write_through = BITSETW(inbuf+smb_vwv7,0); 2676 ssize_t nwritten = -1; 2677 unsigned int smb_doff = SVAL(inbuf,smb_vwv11); 2678 unsigned int smblen = smb_len(inbuf); 2679 char *data; 2680 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF)); 2681 START_PROFILE(SMBwriteX); 2682 2683 /* If it's an IPC, pass off the pipe handler. */ 2684 if (IS_IPC(conn)) { 2685 END_PROFILE(SMBwriteX); 2686 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize); 2687 } 2688 2689 CHECK_FSP(fsp,conn); 2690 CHECK_WRITE(fsp); 2691 2692 /* Deal with possible LARGE_WRITEX */ 2693 if (large_writeX) 2694 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16); 2695 2696 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) { 2697 END_PROFILE(SMBwriteX); 2698 return ERROR_DOS(ERRDOS,ERRbadmem); 2699 } 2700 2701 data = smb_base(inbuf) + smb_doff; 2702 2703 /* Foxconn added start pling 11/24/2009 */ 2704 /* Force startpos to 32 bit (unsigned), since 2705 * the 'offset' field is 32 bit only. 2706 */ 2707 startpos &= 0xFFFFFFFFUL; 2708 /* Foxconn added end pling 11/24/2009 */ 2709 2710 if(CVAL(inbuf,smb_wct) == 14) { 2711#ifdef LARGE_SMB_OFF_T 2712 /* 2713 * This is a large offset (64 bit) write. 2714 */ 2715 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32); 2716 2717#else /* !LARGE_SMB_OFF_T */ 2718 2719 /* Foxconn modified start pling 11/14/2009 */ 2720 /* Bypass the file size limitation */ 2721#if 0 2722 /* 2723 * Ensure we haven't been sent a >32 bit offset. 2724 */ 2725 2726 if(IVAL(inbuf,smb_vwv12) != 0) { 2727 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \ 272864 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) )); 2729 END_PROFILE(SMBwriteX); 2730 return ERROR_DOS(ERRDOS,ERRbadaccess); 2731 } 2732#endif 2733 startpos |= (((SMB_BIG_UINT)IVAL(inbuf,smb_vwv12)) << 32); 2734 /* Foxconn modified end pling 11/14/2009 */ 2735 2736#endif /* LARGE_SMB_OFF_T */ 2737 } 2738 2739 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) { 2740 END_PROFILE(SMBwriteX); 2741 return ERROR_DOS(ERRDOS,ERRlock); 2742 } 2743 2744 /* X/Open SMB protocol says that, unlike SMBwrite 2745 if the length is zero then NO truncation is 2746 done, just a write of zero. To truncate a file, 2747 use SMBwrite. */ 2748 2749 if(numtowrite == 0) 2750 nwritten = 0; 2751 else 2752 nwritten = write_file(fsp,data,startpos,numtowrite); 2753 2754 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) { 2755 END_PROFILE(SMBwriteX); 2756 return(UNIXERROR(ERRHRD,ERRdiskfull)); 2757 } 2758 2759 set_message(outbuf,6,0,True); 2760 2761 SSVAL(outbuf,smb_vwv2,nwritten); 2762 if (large_writeX) 2763 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1); 2764 2765 if (nwritten < (ssize_t)numtowrite) { 2766 SCVAL(outbuf,smb_rcls,ERRHRD); 2767 SSVAL(outbuf,smb_err,ERRdiskfull); 2768 } 2769 2770 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n", 2771 fsp->fnum, (int)numtowrite, (int)nwritten)); 2772 2773 if (lp_syncalways(SNUM(conn)) || write_through) 2774 sync_file(conn,fsp); 2775 2776 END_PROFILE(SMBwriteX); 2777 return chain_reply(inbuf,outbuf,length,bufsize); 2778} 2779 2780/**************************************************************************** 2781 Reply to a lseek. 2782****************************************************************************/ 2783 2784int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize) 2785{ 2786 SMB_OFF_T startpos; 2787 SMB_OFF_T res= -1; 2788 int mode,umode; 2789 int outsize = 0; 2790 files_struct *fsp = file_fsp(inbuf,smb_vwv0); 2791 START_PROFILE(SMBlseek); 2792 2793 CHECK_FSP(fsp,conn); 2794 2795 flush_write_cache(fsp, SEEK_FLUSH); 2796 2797 mode = SVAL(inbuf,smb_vwv1) & 3; 2798 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */ 2799 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2); 2800 2801 switch (mode) { 2802 case 0: 2803 umode = SEEK_SET; 2804 res = startpos; 2805 break; 2806 case 1: 2807 umode = SEEK_CUR; 2808 res = fsp->pos + startpos; 2809 break; 2810 case 2: 2811 umode = SEEK_END; 2812 break; 2813 default: 2814 umode = SEEK_SET; 2815 res = startpos; 2816 break; 2817 } 2818 2819 if (umode == SEEK_END) { 2820 if((res = SMB_VFS_LSEEK(fsp,fsp->fd,startpos,umode)) == -1) { 2821 if(errno == EINVAL) { 2822 SMB_OFF_T current_pos = startpos; 2823 SMB_STRUCT_STAT sbuf; 2824 2825 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) { 2826 END_PROFILE(SMBlseek); 2827 return(UNIXERROR(ERRDOS,ERRnoaccess)); 2828 } 2829 2830 current_pos += sbuf.st_size; 2831 if(current_pos < 0) 2832 res = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_SET); 2833 } 2834 } 2835 2836 if(res == -1) { 2837 END_PROFILE(SMBlseek); 2838 return(UNIXERROR(ERRDOS,ERRnoaccess)); 2839 } 2840 } 2841 2842 fsp->pos = res; 2843 2844 outsize = set_message(outbuf,2,0,True); 2845 SIVAL(outbuf,smb_vwv0,res); 2846 2847 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n", 2848 fsp->fnum, (double)startpos, (double)res, mode)); 2849 2850 END_PROFILE(SMBlseek); 2851 return(outsize); 2852} 2853 2854/**************************************************************************** 2855 Reply to a flush. 2856****************************************************************************/ 2857 2858int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize) 2859{ 2860 int outsize = set_message(outbuf,0,0,True); 2861 uint16 fnum = SVAL(inbuf,smb_vwv0); 2862 files_struct *fsp = file_fsp(inbuf,smb_vwv0); 2863 START_PROFILE(SMBflush); 2864 2865 if (fnum != 0xFFFF) 2866 CHECK_FSP(fsp,conn); 2867 2868 if (!fsp) { 2869 file_sync_all(conn); 2870 } else { 2871 sync_file(conn,fsp); 2872 } 2873 2874 DEBUG(3,("flush\n")); 2875 END_PROFILE(SMBflush); 2876 return(outsize); 2877} 2878 2879/**************************************************************************** 2880 Reply to a exit. 2881****************************************************************************/ 2882 2883int reply_exit(connection_struct *conn, 2884 char *inbuf,char *outbuf, int dum_size, int dum_buffsize) 2885{ 2886 int outsize; 2887 START_PROFILE(SMBexit); 2888 2889 file_close_pid(SVAL(inbuf,smb_pid)); 2890 2891 outsize = set_message(outbuf,0,0,True); 2892 2893 DEBUG(3,("exit\n")); 2894 2895 END_PROFILE(SMBexit); 2896 return(outsize); 2897} 2898 2899/**************************************************************************** 2900 Reply to a close - has to deal with closing a directory opened by NT SMB's. 2901****************************************************************************/ 2902 2903int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size, 2904 int dum_buffsize) 2905{ 2906 extern struct current_user current_user; 2907 int outsize = 0; 2908 time_t mtime; 2909 int32 eclass = 0, err = 0; 2910 files_struct *fsp = NULL; 2911 START_PROFILE(SMBclose); 2912 2913 outsize = set_message(outbuf,0,0,True); 2914 2915 /* If it's an IPC, pass off to the pipe handler. */ 2916 if (IS_IPC(conn)) { 2917 END_PROFILE(SMBclose); 2918 return reply_pipe_close(conn, inbuf,outbuf); 2919 } 2920 2921 fsp = file_fsp(inbuf,smb_vwv0); 2922 2923 /* 2924 * We can only use CHECK_FSP if we know it's not a directory. 2925 */ 2926 2927 if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) { 2928 END_PROFILE(SMBclose); 2929 return ERROR_DOS(ERRDOS,ERRbadfid); 2930 } 2931 2932 if(fsp->is_directory) { 2933 /* 2934 * Special case - close NT SMB directory handle. 2935 */ 2936 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum)); 2937 close_file(fsp,True); 2938 } else { 2939 /* 2940 * Close ordinary file. 2941 */ 2942 int close_err; 2943 pstring file_name; 2944 2945 /* Save the name for time set in close. */ 2946 pstrcpy( file_name, fsp->fsp_name); 2947 2948 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n", 2949 fsp->fd, fsp->fnum, 2950 conn->num_files_open)); 2951 2952 /* 2953 * Take care of any time sent in the close. 2954 */ 2955 2956 mtime = make_unix_date3(inbuf+smb_vwv1); 2957 fsp_set_pending_modtime(fsp, mtime); 2958 2959 /* 2960 * close_file() returns the unix errno if an error 2961 * was detected on close - normally this is due to 2962 * a disk full error. If not then it was probably an I/O error. 2963 */ 2964 2965 if((close_err = close_file(fsp,True)) != 0) { 2966 errno = close_err; 2967 END_PROFILE(SMBclose); 2968 return (UNIXERROR(ERRHRD,ERRgeneral)); 2969 } 2970 } 2971 2972 /* We have a cached error */ 2973 if(eclass || err) { 2974 END_PROFILE(SMBclose); 2975 return ERROR_DOS(eclass,err); 2976 } 2977 2978 END_PROFILE(SMBclose); 2979 return(outsize); 2980} 2981 2982/**************************************************************************** 2983 Reply to a writeclose (Core+ protocol). 2984****************************************************************************/ 2985 2986int reply_writeclose(connection_struct *conn, 2987 char *inbuf,char *outbuf, int size, int dum_buffsize) 2988{ 2989 size_t numtowrite; 2990 ssize_t nwritten = -1; 2991 int outsize = 0; 2992 int close_err = 0; 2993 SMB_OFF_T startpos; 2994 char *data; 2995 time_t mtime; 2996 files_struct *fsp = file_fsp(inbuf,smb_vwv0); 2997 START_PROFILE(SMBwriteclose); 2998 2999 CHECK_FSP(fsp,conn); 3000 CHECK_WRITE(fsp); 3001 3002 numtowrite = SVAL(inbuf,smb_vwv1); 3003 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2); 3004 mtime = make_unix_date3(inbuf+smb_vwv4); 3005 data = smb_buf(inbuf) + 1; 3006 3007 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) { 3008 END_PROFILE(SMBwriteclose); 3009 return ERROR_DOS(ERRDOS,ERRlock); 3010 } 3011 3012 nwritten = write_file(fsp,data,startpos,numtowrite); 3013 3014 set_filetime(conn, fsp->fsp_name,mtime); 3015 3016 /* 3017 * More insanity. W2K only closes the file if writelen > 0. 3018 * JRA. 3019 */ 3020 3021 if (numtowrite) { 3022 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n", 3023 fsp->fsp_name )); 3024 close_err = close_file(fsp,True); 3025 } 3026 3027 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n", 3028 fsp->fnum, (int)numtowrite, (int)nwritten, 3029 conn->num_files_open)); 3030 3031 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) { 3032 END_PROFILE(SMBwriteclose); 3033 return(UNIXERROR(ERRHRD,ERRdiskfull)); 3034 } 3035 3036 if(close_err != 0) { 3037 errno = close_err; 3038 END_PROFILE(SMBwriteclose); 3039 return(UNIXERROR(ERRHRD,ERRgeneral)); 3040 } 3041 3042 outsize = set_message(outbuf,1,0,True); 3043 3044 SSVAL(outbuf,smb_vwv0,nwritten); 3045 END_PROFILE(SMBwriteclose); 3046 return(outsize); 3047} 3048 3049/**************************************************************************** 3050 Reply to a lock. 3051****************************************************************************/ 3052 3053int reply_lock(connection_struct *conn, 3054 char *inbuf,char *outbuf, int length, int dum_buffsize) 3055{ 3056 int outsize = set_message(outbuf,0,0,True); 3057 SMB_BIG_UINT count,offset; 3058 NTSTATUS status; 3059 files_struct *fsp = file_fsp(inbuf,smb_vwv0); 3060 BOOL my_lock_ctx = False; 3061 3062 START_PROFILE(SMBlock); 3063 3064 CHECK_FSP(fsp,conn); 3065 3066 release_level_2_oplocks_on_change(fsp); 3067 3068 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1); 3069 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3); 3070 3071 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n", 3072 fsp->fd, fsp->fnum, (double)offset, (double)count)); 3073 3074 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &my_lock_ctx); 3075 if (NT_STATUS_V(status)) { 3076#if 0 3077 /* Tests using Samba4 against W2K show this call never creates a blocking lock. */ 3078 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) { 3079 /* 3080 * A blocking lock was requested. Package up 3081 * this smb into a queued request and push it 3082 * onto the blocking lock queue. 3083 */ 3084 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), offset, count)) { 3085 END_PROFILE(SMBlock); 3086 return -1; 3087 } 3088 } 3089#endif 3090 END_PROFILE(SMBlock); 3091 return ERROR_NT(status); 3092 } 3093 3094 END_PROFILE(SMBlock); 3095 return(outsize); 3096} 3097 3098/**************************************************************************** 3099 Reply to a unlock. 3100****************************************************************************/ 3101 3102int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, 3103 int dum_buffsize) 3104{ 3105 int outsize = set_message(outbuf,0,0,True); 3106 SMB_BIG_UINT count,offset; 3107 NTSTATUS status; 3108 files_struct *fsp = file_fsp(inbuf,smb_vwv0); 3109 START_PROFILE(SMBunlock); 3110 3111 CHECK_FSP(fsp,conn); 3112 3113 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1); 3114 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3); 3115 3116 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset); 3117 if (NT_STATUS_V(status)) { 3118 END_PROFILE(SMBunlock); 3119 return ERROR_NT(status); 3120 } 3121 3122 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n", 3123 fsp->fd, fsp->fnum, (double)offset, (double)count ) ); 3124 3125 END_PROFILE(SMBunlock); 3126 return(outsize); 3127} 3128 3129/**************************************************************************** 3130 Reply to a tdis. 3131****************************************************************************/ 3132 3133int reply_tdis(connection_struct *conn, 3134 char *inbuf,char *outbuf, int dum_size, int dum_buffsize) 3135{ 3136 int outsize = set_message(outbuf,0,0,True); 3137 uint16 vuid; 3138 START_PROFILE(SMBtdis); 3139 3140 vuid = SVAL(inbuf,smb_uid); 3141 3142 if (!conn) { 3143 DEBUG(4,("Invalid connection in tdis\n")); 3144 END_PROFILE(SMBtdis); 3145 return ERROR_DOS(ERRSRV,ERRinvnid); 3146 } 3147 3148 conn->used = False; 3149 3150 close_cnum(conn,vuid); 3151 3152 END_PROFILE(SMBtdis); 3153 return outsize; 3154} 3155 3156/**************************************************************************** 3157 Reply to a echo. 3158****************************************************************************/ 3159 3160int reply_echo(connection_struct *conn, 3161 char *inbuf,char *outbuf, int dum_size, int dum_buffsize) 3162{ 3163 int smb_reverb = SVAL(inbuf,smb_vwv0); 3164 int seq_num; 3165 unsigned int data_len = smb_buflen(inbuf); 3166 int outsize = set_message(outbuf,1,data_len,True); 3167 START_PROFILE(SMBecho); 3168 3169 if (data_len > BUFFER_SIZE) { 3170 DEBUG(0,("reply_echo: data_len too large.\n")); 3171 END_PROFILE(SMBecho); 3172 return -1; 3173 } 3174 3175 /* copy any incoming data back out */ 3176 if (data_len > 0) 3177 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len); 3178 3179 if (smb_reverb > 100) { 3180 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb)); 3181 smb_reverb = 100; 3182 } 3183 3184 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) { 3185 SSVAL(outbuf,smb_vwv0,seq_num); 3186 3187 smb_setlen(outbuf,outsize - 4); 3188 3189 if (!send_smb(smbd_server_fd(),outbuf)) 3190 exit_server("reply_echo: send_smb failed."); 3191 } 3192 3193 DEBUG(3,("echo %d times\n", smb_reverb)); 3194 3195 smb_echo_count++; 3196 3197 END_PROFILE(SMBecho); 3198 return -1; 3199} 3200 3201/**************************************************************************** 3202 Reply to a printopen. 3203****************************************************************************/ 3204 3205int reply_printopen(connection_struct *conn, 3206 char *inbuf,char *outbuf, int dum_size, int dum_buffsize) 3207{ 3208 int outsize = 0; 3209 files_struct *fsp; 3210 START_PROFILE(SMBsplopen); 3211 3212 if (!CAN_PRINT(conn)) { 3213 END_PROFILE(SMBsplopen); 3214 return ERROR_DOS(ERRDOS,ERRnoaccess); 3215 } 3216 3217 /* Open for exclusive use, write only. */ 3218 fsp = print_fsp_open(conn, NULL); 3219 3220 if (!fsp) { 3221 END_PROFILE(SMBsplopen); 3222 return(UNIXERROR(ERRDOS,ERRnoaccess)); 3223 } 3224 3225 outsize = set_message(outbuf,1,0,True); 3226 SSVAL(outbuf,smb_vwv0,fsp->fnum); 3227 3228 DEBUG(3,("openprint fd=%d fnum=%d\n", 3229 fsp->fd, fsp->fnum)); 3230 3231 END_PROFILE(SMBsplopen); 3232 return(outsize); 3233} 3234 3235/**************************************************************************** 3236 Reply to a printclose. 3237****************************************************************************/ 3238 3239int reply_printclose(connection_struct *conn, 3240 char *inbuf,char *outbuf, int dum_size, int dum_buffsize) 3241{ 3242 int outsize = set_message(outbuf,0,0,True); 3243 files_struct *fsp = file_fsp(inbuf,smb_vwv0); 3244 int close_err = 0; 3245 START_PROFILE(SMBsplclose); 3246 3247 CHECK_FSP(fsp,conn); 3248 3249 if (!CAN_PRINT(conn)) { 3250 END_PROFILE(SMBsplclose); 3251 return ERROR_NT(NT_STATUS_UNSUCCESSFUL); 3252 } 3253 3254 DEBUG(3,("printclose fd=%d fnum=%d\n", 3255 fsp->fd,fsp->fnum)); 3256 3257 close_err = close_file(fsp,True); 3258 3259 if(close_err != 0) { 3260 errno = close_err; 3261 END_PROFILE(SMBsplclose); 3262 return(UNIXERROR(ERRHRD,ERRgeneral)); 3263 } 3264 3265 END_PROFILE(SMBsplclose); 3266 return(outsize); 3267} 3268 3269/**************************************************************************** 3270 Reply to a printqueue. 3271****************************************************************************/ 3272 3273int reply_printqueue(connection_struct *conn, 3274 char *inbuf,char *outbuf, int dum_size, int dum_buffsize) 3275{ 3276 int outsize = set_message(outbuf,2,3,True); 3277 int max_count = SVAL(inbuf,smb_vwv0); 3278 int start_index = SVAL(inbuf,smb_vwv1); 3279 START_PROFILE(SMBsplretq); 3280 3281 /* we used to allow the client to get the cnum wrong, but that 3282 is really quite gross and only worked when there was only 3283 one printer - I think we should now only accept it if they 3284 get it right (tridge) */ 3285 if (!CAN_PRINT(conn)) { 3286 END_PROFILE(SMBsplretq); 3287 return ERROR_DOS(ERRDOS,ERRnoaccess); 3288 } 3289 3290 SSVAL(outbuf,smb_vwv0,0); 3291 SSVAL(outbuf,smb_vwv1,0); 3292 SCVAL(smb_buf(outbuf),0,1); 3293 SSVAL(smb_buf(outbuf),1,0); 3294 3295 DEBUG(3,("printqueue start_index=%d max_count=%d\n", 3296 start_index, max_count)); 3297 3298 { 3299 print_queue_struct *queue = NULL; 3300 print_status_struct status; 3301 char *p = smb_buf(outbuf) + 3; 3302 int count = print_queue_status(SNUM(conn), &queue, &status); 3303 int num_to_get = ABS(max_count); 3304 int first = (max_count>0?start_index:start_index+max_count+1); 3305 int i; 3306 3307 if (first >= count) 3308 num_to_get = 0; 3309 else 3310 num_to_get = MIN(num_to_get,count-first); 3311 3312 3313 for (i=first;i<first+num_to_get;i++) { 3314 put_dos_date2(p,0,queue[i].time); 3315 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3)); 3316 SSVAL(p,5, queue[i].job); 3317 SIVAL(p,7,queue[i].size); 3318 SCVAL(p,11,0); 3319 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII); 3320 p += 28; 3321 } 3322 3323 if (count > 0) { 3324 outsize = set_message(outbuf,2,28*count+3,False); 3325 SSVAL(outbuf,smb_vwv0,count); 3326 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1)); 3327 SCVAL(smb_buf(outbuf),0,1); 3328 SSVAL(smb_buf(outbuf),1,28*count); 3329 } 3330 3331 SAFE_FREE(queue); 3332 3333 DEBUG(3,("%d entries returned in queue\n",count)); 3334 } 3335 3336 END_PROFILE(SMBsplretq); 3337 return(outsize); 3338} 3339 3340/**************************************************************************** 3341 Reply to a printwrite. 3342****************************************************************************/ 3343 3344int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) 3345{ 3346 int numtowrite; 3347 int outsize = set_message(outbuf,0,0,True); 3348 char *data; 3349 files_struct *fsp = file_fsp(inbuf,smb_vwv0); 3350 3351 START_PROFILE(SMBsplwr); 3352 3353 if (!CAN_PRINT(conn)) { 3354 END_PROFILE(SMBsplwr); 3355 return ERROR_DOS(ERRDOS,ERRnoaccess); 3356 } 3357 3358 CHECK_FSP(fsp,conn); 3359 CHECK_WRITE(fsp); 3360 3361 numtowrite = SVAL(smb_buf(inbuf),1); 3362 data = smb_buf(inbuf) + 3; 3363 3364 if (write_file(fsp,data,-1,numtowrite) != numtowrite) { 3365 END_PROFILE(SMBsplwr); 3366 return(UNIXERROR(ERRHRD,ERRdiskfull)); 3367 } 3368 3369 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) ); 3370 3371 END_PROFILE(SMBsplwr); 3372 return(outsize); 3373} 3374 3375/**************************************************************************** 3376 The guts of the mkdir command, split out so it may be called by the NT SMB 3377 code. 3378****************************************************************************/ 3379 3380NTSTATUS mkdir_internal(connection_struct *conn, pstring directory) 3381{ 3382 BOOL bad_path = False; 3383 SMB_STRUCT_STAT sbuf; 3384 int ret= -1; 3385 3386 unix_convert(directory,conn,0,&bad_path,&sbuf); 3387 3388 if( strchr_m(directory, ':')) { 3389 return NT_STATUS_NOT_A_DIRECTORY; 3390 } 3391 3392 if (ms_has_wild(directory)) { 3393 return NT_STATUS_OBJECT_NAME_INVALID; 3394 } 3395 3396 if (bad_path) { 3397 return NT_STATUS_OBJECT_PATH_NOT_FOUND; 3398 } 3399 3400 if (check_name(directory, conn)) 3401 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True)); 3402 3403 if (ret == -1) { 3404 if(errno == ENOENT) { 3405 return NT_STATUS_OBJECT_NAME_NOT_FOUND; 3406 } 3407 return map_nt_error_from_unix(errno); 3408 } 3409 3410 return NT_STATUS_OK; 3411} 3412 3413/**************************************************************************** 3414 Reply to a mkdir. 3415****************************************************************************/ 3416 3417int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) 3418{ 3419 pstring directory; 3420 int outsize; 3421 NTSTATUS status; 3422 START_PROFILE(SMBmkdir); 3423 3424 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False); 3425 if (!NT_STATUS_IS_OK(status)) { 3426 END_PROFILE(SMBmkdir); 3427 return ERROR_NT(status); 3428 } 3429 3430 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf); 3431 3432 status = mkdir_internal(conn, directory); 3433 if (!NT_STATUS_IS_OK(status)) { 3434 END_PROFILE(SMBmkdir); 3435 return ERROR_NT(status); 3436 } 3437 3438 outsize = set_message(outbuf,0,0,True); 3439 3440 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) ); 3441 3442 END_PROFILE(SMBmkdir); 3443 return(outsize); 3444} 3445 3446/**************************************************************************** 3447 Static function used by reply_rmdir to delete an entire directory 3448 tree recursively. Return False on ok, True on fail. 3449****************************************************************************/ 3450 3451static BOOL recursive_rmdir(connection_struct *conn, char *directory) 3452{ 3453 const char *dname = NULL; 3454 BOOL ret = False; 3455 long offset = 0; 3456 struct smb_Dir *dir_hnd = OpenDir(conn, directory); 3457 3458 if(dir_hnd == NULL) 3459 return True; 3460 3461 while((dname = ReadDirName(dir_hnd, &offset))) { 3462 pstring fullname; 3463 SMB_STRUCT_STAT st; 3464 3465 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) 3466 continue; 3467 3468 if (!is_visible_file(conn, directory, dname, &st, False)) 3469 continue; 3470 3471 /* Construct the full name. */ 3472 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) { 3473 errno = ENOMEM; 3474 ret = True; 3475 break; 3476 } 3477 3478 pstrcpy(fullname, directory); 3479 pstrcat(fullname, "/"); 3480 pstrcat(fullname, dname); 3481 3482 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) { 3483 ret = True; 3484 break; 3485 } 3486 3487 if(st.st_mode & S_IFDIR) { 3488 if(recursive_rmdir(conn, fullname)!=0) { 3489 ret = True; 3490 break; 3491 } 3492 if(SMB_VFS_RMDIR(conn,fullname) != 0) { 3493 ret = True; 3494 break; 3495 } 3496 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) { 3497 ret = True; 3498 break; 3499 } 3500 } 3501 CloseDir(dir_hnd); 3502 return ret; 3503} 3504 3505/**************************************************************************** 3506 The internals of the rmdir code - called elsewhere. 3507****************************************************************************/ 3508 3509BOOL rmdir_internals(connection_struct *conn, char *directory) 3510{ 3511 BOOL ok; 3512 SMB_STRUCT_STAT st; 3513 3514 ok = (SMB_VFS_RMDIR(conn,directory) == 0); 3515 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) { 3516 /* 3517 * Check to see if the only thing in this directory are 3518 * vetoed files/directories. If so then delete them and 3519 * retry. If we fail to delete any of them (and we *don't* 3520 * do a recursive delete) then fail the rmdir. 3521 */ 3522 BOOL all_veto_files = True; 3523 const char *dname; 3524 struct smb_Dir *dir_hnd = OpenDir(conn, directory); 3525 3526 if(dir_hnd != NULL) { 3527 long dirpos = TellDir(dir_hnd); 3528 while ((dname = ReadDirName(dir_hnd,&dirpos))) { 3529 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) 3530 continue; 3531 if (!is_visible_file(conn, directory, dname, &st, False)) 3532 continue; 3533 if(!IS_VETO_PATH(conn, dname)) { 3534 all_veto_files = False; 3535 break; 3536 } 3537 } 3538 3539 if(all_veto_files) { 3540 SeekDir(dir_hnd,dirpos); 3541 while ((dname = ReadDirName(dir_hnd,&dirpos))) { 3542 pstring fullname; 3543 3544 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) 3545 continue; 3546 if (!is_visible_file(conn, directory, dname, &st, False)) 3547 continue; 3548 3549 /* Construct the full name. */ 3550 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) { 3551 errno = ENOMEM; 3552 break; 3553 } 3554 3555 pstrcpy(fullname, directory); 3556 pstrcat(fullname, "/"); 3557 pstrcat(fullname, dname); 3558 3559 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) 3560 break; 3561 if(st.st_mode & S_IFDIR) { 3562 if(lp_recursive_veto_delete(SNUM(conn))) { 3563 if(recursive_rmdir(conn, fullname) != 0) 3564 break; 3565 } 3566 if(SMB_VFS_RMDIR(conn,fullname) != 0) 3567 break; 3568 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) 3569 break; 3570 } 3571 CloseDir(dir_hnd); 3572 /* Retry the rmdir */ 3573 ok = (SMB_VFS_RMDIR(conn,directory) == 0); 3574 } else { 3575 CloseDir(dir_hnd); 3576 } 3577 } else { 3578 errno = ENOTEMPTY; 3579 } 3580 } 3581 3582 if (!ok) 3583 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno))); 3584 3585 return ok; 3586} 3587 3588/**************************************************************************** 3589 Reply to a rmdir. 3590****************************************************************************/ 3591 3592int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) 3593{ 3594 pstring directory; 3595 int outsize = 0; 3596 BOOL ok = False; 3597 BOOL bad_path = False; 3598 SMB_STRUCT_STAT sbuf; 3599 NTSTATUS status; 3600 START_PROFILE(SMBrmdir); 3601 3602 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False); 3603 if (!NT_STATUS_IS_OK(status)) { 3604 END_PROFILE(SMBrmdir); 3605 return ERROR_NT(status); 3606 } 3607 3608 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf) 3609 3610 unix_convert(directory,conn, NULL,&bad_path,&sbuf); 3611 if (bad_path) { 3612 END_PROFILE(SMBrmdir); 3613 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); 3614 } 3615 3616 if (check_name(directory,conn)) { 3617 dptr_closepath(directory,SVAL(inbuf,smb_pid)); 3618 ok = rmdir_internals(conn, directory); 3619 } 3620 3621 if (!ok) { 3622 END_PROFILE(SMBrmdir); 3623 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRbadpath); 3624 } 3625 3626 outsize = set_message(outbuf,0,0,True); 3627 3628 DEBUG( 3, ( "rmdir %s\n", directory ) ); 3629 3630 END_PROFILE(SMBrmdir); 3631 return(outsize); 3632} 3633 3634/******************************************************************* 3635 Resolve wildcards in a filename rename. 3636 Note that name is in UNIX charset and thus potentially can be more 3637 than fstring buffer (255 bytes) especially in default UTF-8 case. 3638 Therefore, we use pstring inside and all calls should ensure that 3639 name2 is at least pstring-long (they do already) 3640********************************************************************/ 3641 3642static BOOL resolve_wildcards(const char *name1, char *name2) 3643{ 3644 pstring root1,root2; 3645 pstring ext1,ext2; 3646 char *p,*p2, *pname1, *pname2; 3647 int available_space, actual_space; 3648 3649 3650 pname1 = strrchr_m(name1,'/'); 3651 pname2 = strrchr_m(name2,'/'); 3652 3653 if (!pname1 || !pname2) 3654 return(False); 3655 3656 pstrcpy(root1,pname1); 3657 pstrcpy(root2,pname2); 3658 p = strrchr_m(root1,'.'); 3659 if (p) { 3660 *p = 0; 3661 pstrcpy(ext1,p+1); 3662 } else { 3663 pstrcpy(ext1,""); 3664 } 3665 p = strrchr_m(root2,'.'); 3666 if (p) { 3667 *p = 0; 3668 pstrcpy(ext2,p+1); 3669 } else { 3670 pstrcpy(ext2,""); 3671 } 3672 3673 p = root1; 3674 p2 = root2; 3675 while (*p2) { 3676 if (*p2 == '?') { 3677 *p2 = *p; 3678 p2++; 3679 } else if (*p2 == '*') { 3680 pstrcpy(p2, p); 3681 break; 3682 } else { 3683 p2++; 3684 } 3685 if (*p) 3686 p++; 3687 } 3688 3689 p = ext1; 3690 p2 = ext2; 3691 while (*p2) { 3692 if (*p2 == '?') { 3693 *p2 = *p; 3694 p2++; 3695 } else if (*p2 == '*') { 3696 pstrcpy(p2, p); 3697 break; 3698 } else { 3699 p2++; 3700 } 3701 if (*p) 3702 p++; 3703 } 3704 3705 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2); 3706 3707 if (ext2[0]) { 3708 actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2); 3709 if (actual_space >= available_space - 1) { 3710 DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n", 3711 actual_space - available_space)); 3712 } 3713 } else { 3714 pstrcpy_base(pname2, root2, name2); 3715 } 3716 3717 return(True); 3718} 3719 3720/**************************************************************************** 3721 Ensure open files have their names updates. 3722****************************************************************************/ 3723 3724static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode, char *newname) 3725{ 3726 files_struct *fsp; 3727 BOOL did_rename = False; 3728 3729 for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) { 3730 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n", 3731 fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode, 3732 fsp->fsp_name, newname )); 3733 string_set(&fsp->fsp_name, newname); 3734 did_rename = True; 3735 } 3736 3737 if (!did_rename) 3738 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n", 3739 (unsigned int)dev, (double)inode, newname )); 3740} 3741 3742/**************************************************************************** 3743 Rename an open file - given an fsp. 3744****************************************************************************/ 3745 3746NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, uint16 attrs, BOOL replace_if_exists) 3747{ 3748 SMB_STRUCT_STAT sbuf; 3749 BOOL bad_path = False; 3750 pstring newname_last_component; 3751 NTSTATUS error = NT_STATUS_OK; 3752 BOOL dest_exists; 3753 BOOL rcdest = True; 3754 3755 ZERO_STRUCT(sbuf); 3756 rcdest = unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf); 3757 3758 /* Quick check for "." and ".." */ 3759 if (!bad_path && newname_last_component[0] == '.') { 3760 if (!newname_last_component[1] || (newname_last_component[1] == '.' && !newname_last_component[2])) { 3761 return NT_STATUS_ACCESS_DENIED; 3762 } 3763 } 3764 if (!rcdest && bad_path) { 3765 return NT_STATUS_OBJECT_PATH_NOT_FOUND; 3766 } 3767 3768 /* Ensure newname contains a '/' */ 3769 if(strrchr_m(newname,'/') == 0) { 3770 pstring tmpstr; 3771 3772 pstrcpy(tmpstr, "./"); 3773 pstrcat(tmpstr, newname); 3774 pstrcpy(newname, tmpstr); 3775 } 3776 3777 /* 3778 * Check for special case with case preserving and not 3779 * case sensitive. If the old last component differs from the original 3780 * last component only by case, then we should allow 3781 * the rename (user is trying to change the case of the 3782 * filename). 3783 */ 3784 3785 if((conn->case_sensitive == False) && (conn->case_preserve == True) && 3786 strequal(newname, fsp->fsp_name)) { 3787 char *p; 3788 pstring newname_modified_last_component; 3789 3790 /* 3791 * Get the last component of the modified name. 3792 * Note that we guarantee that newname contains a '/' 3793 * character above. 3794 */ 3795 p = strrchr_m(newname,'/'); 3796 pstrcpy(newname_modified_last_component,p+1); 3797 3798 if(strcsequal(newname_modified_last_component, 3799 newname_last_component) == False) { 3800 /* 3801 * Replace the modified last component with 3802 * the original. 3803 */ 3804 pstrcpy(p+1, newname_last_component); 3805 } 3806 } 3807 3808 /* 3809 * If the src and dest names are identical - including case, 3810 * don't do the rename, just return success. 3811 */ 3812 3813 if (strcsequal(fsp->fsp_name, newname)) { 3814 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n", 3815 newname)); 3816 return NT_STATUS_OK; 3817 } 3818 3819 dest_exists = vfs_object_exist(conn,newname,NULL); 3820 3821 if(!replace_if_exists && dest_exists) { 3822 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n", 3823 fsp->fsp_name,newname)); 3824 return NT_STATUS_OBJECT_NAME_COLLISION; 3825 } 3826 3827 error = can_rename(conn,newname,attrs,&sbuf); 3828 3829 if (dest_exists && !NT_STATUS_IS_OK(error)) { 3830 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n", 3831 nt_errstr(error), fsp->fsp_name,newname)); 3832 if (NT_STATUS_EQUAL(error,NT_STATUS_SHARING_VIOLATION)) 3833 error = NT_STATUS_ACCESS_DENIED; 3834 return error; 3835 } 3836 3837 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) { 3838 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n", 3839 fsp->fsp_name,newname)); 3840 rename_open_files(conn, fsp->dev, fsp->inode, newname); 3841 return NT_STATUS_OK; 3842 } 3843 3844 if (errno == ENOTDIR || errno == EISDIR) 3845 error = NT_STATUS_OBJECT_NAME_COLLISION; 3846 else 3847 error = map_nt_error_from_unix(errno); 3848 3849 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n", 3850 nt_errstr(error), fsp->fsp_name,newname)); 3851 3852 return error; 3853} 3854 3855/**************************************************************************** 3856 The guts of the rename command, split out so it may be called by the NT SMB 3857 code. 3858****************************************************************************/ 3859 3860NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, uint16 attrs, BOOL replace_if_exists) 3861{ 3862 pstring directory; 3863 pstring mask; 3864 pstring last_component_src; 3865 pstring last_component_dest; 3866 char *p; 3867 BOOL has_wild; 3868 BOOL bad_path_src = False; 3869 BOOL bad_path_dest = False; 3870 int count=0; 3871 NTSTATUS error = NT_STATUS_OK; 3872 BOOL rc = True; 3873 BOOL rcdest = True; 3874 SMB_STRUCT_STAT sbuf1, sbuf2; 3875 3876 *directory = *mask = 0; 3877 3878 ZERO_STRUCT(sbuf1); 3879 ZERO_STRUCT(sbuf2); 3880 3881 rc = unix_convert(name,conn,last_component_src,&bad_path_src,&sbuf1); 3882 if (!rc && bad_path_src) { 3883 if (ms_has_wild(last_component_src)) 3884 return NT_STATUS_OBJECT_NAME_NOT_FOUND; 3885 return NT_STATUS_OBJECT_PATH_NOT_FOUND; 3886 } 3887 3888 /* Quick check for "." and ".." */ 3889 if (last_component_src[0] == '.') { 3890 if (!last_component_src[1] || (last_component_src[1] == '.' && !last_component_src[2])) { 3891 return NT_STATUS_OBJECT_NAME_INVALID; 3892 } 3893 } 3894 3895 rcdest = unix_convert(newname,conn,last_component_dest,&bad_path_dest,&sbuf2); 3896 3897 /* Quick check for "." and ".." */ 3898 if (last_component_dest[0] == '.') { 3899 if (!last_component_dest[1] || (last_component_dest[1] == '.' && !last_component_dest[2])) { 3900 return NT_STATUS_OBJECT_NAME_INVALID; 3901 } 3902 } 3903 3904 /* 3905 * Split the old name into directory and last component 3906 * strings. Note that unix_convert may have stripped off a 3907 * leading ./ from both name and newname if the rename is 3908 * at the root of the share. We need to make sure either both 3909 * name and newname contain a / character or neither of them do 3910 * as this is checked in resolve_wildcards(). 3911 */ 3912 3913 p = strrchr_m(name,'/'); 3914 if (!p) { 3915 pstrcpy(directory,"."); 3916 pstrcpy(mask,name); 3917 } else { 3918 *p = 0; 3919 pstrcpy(directory,name); 3920 pstrcpy(mask,p+1); 3921 *p = '/'; /* Replace needed for exceptional test below. */ 3922 } 3923 3924 /* 3925 * We should only check the mangled cache 3926 * here if unix_convert failed. This means 3927 * that the path in 'mask' doesn't exist 3928 * on the file system and so we need to look 3929 * for a possible mangle. This patch from 3930 * Tine Smukavec <valentin.smukavec@hermes.si>. 3931 */ 3932 3933 if (!rc && mangle_is_mangled(mask)) 3934 mangle_check_cache( mask, sizeof(pstring)-1 ); 3935 3936 has_wild = ms_has_wild(mask); 3937 3938 if (!has_wild) { 3939 /* 3940 * No wildcards - just process the one file. 3941 */ 3942 BOOL is_short_name = mangle_is_8_3(name, True); 3943 3944 /* Add a terminating '/' to the directory name. */ 3945 pstrcat(directory,"/"); 3946 pstrcat(directory,mask); 3947 3948 /* Ensure newname contains a '/' also */ 3949 if(strrchr_m(newname,'/') == 0) { 3950 pstring tmpstr; 3951 3952 pstrcpy(tmpstr, "./"); 3953 pstrcat(tmpstr, newname); 3954 pstrcpy(newname, tmpstr); 3955 } 3956 3957 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \ 3958directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n", 3959 conn->case_sensitive, conn->case_preserve, conn->short_case_preserve, directory, 3960 newname, last_component_dest, is_short_name)); 3961 3962 /* 3963 * Check for special case with case preserving and not 3964 * case sensitive, if directory and newname are identical, 3965 * and the old last component differs from the original 3966 * last component only by case, then we should allow 3967 * the rename (user is trying to change the case of the 3968 * filename). 3969 */ 3970 if((conn->case_sensitive == False) && 3971 (((conn->case_preserve == True) && 3972 (is_short_name == False)) || 3973 ((conn->short_case_preserve == True) && 3974 (is_short_name == True))) && 3975 strcsequal(directory, newname)) { 3976 pstring modified_last_component; 3977 3978 /* 3979 * Get the last component of the modified name. 3980 * Note that we guarantee that newname contains a '/' 3981 * character above. 3982 */ 3983 p = strrchr_m(newname,'/'); 3984 pstrcpy(modified_last_component,p+1); 3985 3986 if(strcsequal(modified_last_component, 3987 last_component_dest) == False) { 3988 /* 3989 * Replace the modified last component with 3990 * the original. 3991 */ 3992 pstrcpy(p+1, last_component_dest); 3993 } 3994 } 3995 3996 resolve_wildcards(directory,newname); 3997 3998 /* 3999 * The source object must exist. 4000 */ 4001 4002 if (!vfs_object_exist(conn, directory, &sbuf1)) { 4003 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n", 4004 directory,newname)); 4005 4006 if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) { 4007 /* 4008 * Must return different errors depending on whether the parent 4009 * directory existed or not. 4010 */ 4011 4012 p = strrchr_m(directory, '/'); 4013 if (!p) 4014 return NT_STATUS_OBJECT_NAME_NOT_FOUND; 4015 *p = '\0'; 4016 if (vfs_object_exist(conn, directory, NULL)) 4017 return NT_STATUS_OBJECT_NAME_NOT_FOUND; 4018 return NT_STATUS_OBJECT_PATH_NOT_FOUND; 4019 } 4020 error = map_nt_error_from_unix(errno); 4021 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n", 4022 nt_errstr(error), directory,newname)); 4023 4024 return error; 4025 } 4026 4027 if (!rcdest && bad_path_dest) { 4028 if (ms_has_wild(last_component_dest)) 4029 return NT_STATUS_OBJECT_NAME_INVALID; 4030 return NT_STATUS_OBJECT_PATH_NOT_FOUND; 4031 } 4032 4033 error = can_rename(conn,directory,attrs,&sbuf1); 4034 4035 if (!NT_STATUS_IS_OK(error)) { 4036 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n", 4037 nt_errstr(error), directory,newname)); 4038 return error; 4039 } 4040 4041 /* 4042 * If the src and dest names are identical - including case, 4043 * don't do the rename, just return success. 4044 */ 4045 4046 if (strcsequal(directory, newname)) { 4047 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname); 4048 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory)); 4049 return NT_STATUS_OK; 4050 } 4051 4052 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) { 4053 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n", 4054 directory,newname)); 4055 return NT_STATUS_OBJECT_NAME_COLLISION; 4056 } 4057 4058 if(SMB_VFS_RENAME(conn,directory, newname) == 0) { 4059 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n", 4060 directory,newname)); 4061 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname); 4062 return NT_STATUS_OK; 4063 } 4064 4065 if (errno == ENOTDIR || errno == EISDIR) 4066 error = NT_STATUS_OBJECT_NAME_COLLISION; 4067 else 4068 error = map_nt_error_from_unix(errno); 4069 4070 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n", 4071 nt_errstr(error), directory,newname)); 4072 4073 return error; 4074 } else { 4075 /* 4076 * Wildcards - process each file that matches. 4077 */ 4078 struct smb_Dir *dir_hnd = NULL; 4079 const char *dname; 4080 pstring destname; 4081 4082 if (check_name(directory,conn)) 4083 dir_hnd = OpenDir(conn, directory); 4084 4085 if (dir_hnd) { 4086 long offset = 0; 4087 error = NT_STATUS_NO_SUCH_FILE; 4088/* Was error = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */ 4089 4090 if (strequal(mask,"????????.???")) 4091 pstrcpy(mask,"*"); 4092 4093 while ((dname = ReadDirName(dir_hnd, &offset))) { 4094 pstring fname; 4095 BOOL sysdir_entry = False; 4096 4097 pstrcpy(fname,dname); 4098 4099 /* Quick check for "." and ".." */ 4100 if (fname[0] == '.') { 4101 if (!fname[1] || (fname[1] == '.' && !fname[2])) { 4102 if (attrs & aDIR) { 4103 sysdir_entry = True; 4104 } else { 4105 continue; 4106 } 4107 } 4108 } 4109 4110 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) 4111 continue; 4112 4113 if(!mask_match(fname, mask, conn->case_sensitive)) 4114 continue; 4115 4116 if (sysdir_entry) { 4117 error = NT_STATUS_OBJECT_NAME_INVALID; 4118 break; 4119 } 4120 4121 error = NT_STATUS_ACCESS_DENIED; 4122 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname); 4123 if (!vfs_object_exist(conn, fname, &sbuf1)) { 4124 error = NT_STATUS_OBJECT_NAME_NOT_FOUND; 4125 DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error))); 4126 continue; 4127 } 4128 error = can_rename(conn,fname,attrs,&sbuf1); 4129 if (!NT_STATUS_IS_OK(error)) { 4130 DEBUG(6,("rename %s refused\n", fname)); 4131 continue; 4132 } 4133 pstrcpy(destname,newname); 4134 4135 if (!resolve_wildcards(fname,destname)) { 4136 DEBUG(6,("resolve_wildcards %s %s failed\n", 4137 fname, destname)); 4138 continue; 4139 } 4140 4141 if (strcsequal(fname,destname)) { 4142 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname); 4143 DEBUG(3,("rename_internals: identical names in wildcard rename %s - success\n", fname)); 4144 count++; 4145 error = NT_STATUS_OK; 4146 continue; 4147 } 4148 4149 if (!replace_if_exists && 4150 vfs_file_exist(conn,destname, NULL)) { 4151 DEBUG(6,("file_exist %s\n", destname)); 4152 error = NT_STATUS_OBJECT_NAME_COLLISION; 4153 continue; 4154 } 4155 4156 if (!SMB_VFS_RENAME(conn,fname,destname)) { 4157 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname); 4158 count++; 4159 error = NT_STATUS_OK; 4160 } 4161 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname)); 4162 } 4163 CloseDir(dir_hnd); 4164 } 4165 4166 if (!NT_STATUS_EQUAL(error,NT_STATUS_NO_SUCH_FILE)) { 4167 if (!rcdest && bad_path_dest) { 4168 if (ms_has_wild(last_component_dest)) 4169 return NT_STATUS_OBJECT_NAME_INVALID; 4170 return NT_STATUS_OBJECT_PATH_NOT_FOUND; 4171 } 4172 } 4173 } 4174 4175 if (count == 0 && NT_STATUS_IS_OK(error)) { 4176 error = map_nt_error_from_unix(errno); 4177 } 4178 4179 return error; 4180} 4181 4182/**************************************************************************** 4183 Reply to a mv. 4184****************************************************************************/ 4185 4186int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, 4187 int dum_buffsize) 4188{ 4189 int outsize = 0; 4190 pstring name; 4191 pstring newname; 4192 char *p; 4193 uint16 attrs = SVAL(inbuf,smb_vwv0); 4194 NTSTATUS status; 4195 4196 START_PROFILE(SMBmv); 4197 4198 p = smb_buf(inbuf) + 1; 4199 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True); 4200 if (!NT_STATUS_IS_OK(status)) { 4201 END_PROFILE(SMBmv); 4202 return ERROR_NT(status); 4203 } 4204 p++; 4205 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True); 4206 if (!NT_STATUS_IS_OK(status)) { 4207 END_PROFILE(SMBmv); 4208 return ERROR_NT(status); 4209 } 4210 4211 RESOLVE_DFSPATH(name, conn, inbuf, outbuf); 4212 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf); 4213 4214 DEBUG(3,("reply_mv : %s -> %s\n",name,newname)); 4215 4216 status = rename_internals(conn, name, newname, attrs, False); 4217 if (!NT_STATUS_IS_OK(status)) { 4218 END_PROFILE(SMBmv); 4219 if (open_was_deferred(SVAL(inbuf,smb_mid))) { 4220 /* We have re-scheduled this call. */ 4221 clear_cached_errors(); 4222 return -1; 4223 } 4224 return ERROR_NT(status); 4225 } 4226 4227 /* 4228 * Win2k needs a changenotify request response before it will 4229 * update after a rename.. 4230 */ 4231 process_pending_change_notify_queue((time_t)0); 4232 outsize = set_message(outbuf,0,0,True); 4233 4234 END_PROFILE(SMBmv); 4235 return(outsize); 4236} 4237 4238/******************************************************************* 4239 Copy a file as part of a reply_copy. 4240******************************************************************/ 4241 4242static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, 4243 int count,BOOL target_is_directory, int *err_ret) 4244{ 4245 int Access,action; 4246 SMB_STRUCT_STAT src_sbuf, sbuf2; 4247 SMB_OFF_T ret=-1; 4248 files_struct *fsp1,*fsp2; 4249 pstring dest; 4250 uint32 dosattrs; 4251 4252 *err_ret = 0; 4253 4254 pstrcpy(dest,dest1); 4255 if (target_is_directory) { 4256 char *p = strrchr_m(src,'/'); 4257 if (p) 4258 p++; 4259 else 4260 p = src; 4261 pstrcat(dest,"/"); 4262 pstrcat(dest,p); 4263 } 4264 4265 if (!vfs_file_exist(conn,src,&src_sbuf)) 4266 return(False); 4267 4268 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY), 4269 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),FILE_ATTRIBUTE_NORMAL,INTERNAL_OPEN_ONLY, 4270 &Access,&action); 4271 4272 if (!fsp1) 4273 return(False); 4274 4275 if (!target_is_directory && count) 4276 ofun = FILE_EXISTS_OPEN; 4277 4278 dosattrs = dos_mode(conn, src, &src_sbuf); 4279 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) 4280 ZERO_STRUCTP(&sbuf2); 4281 4282 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY), 4283 ofun,dosattrs,INTERNAL_OPEN_ONLY,&Access,&action); 4284 4285 if (!fsp2) { 4286 close_file(fsp1,False); 4287 return(False); 4288 } 4289 4290 if ((ofun&3) == 1) { 4291 if(SMB_VFS_LSEEK(fsp2,fsp2->fd,0,SEEK_END) == -1) { 4292 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) )); 4293 /* 4294 * Stop the copy from occurring. 4295 */ 4296 ret = -1; 4297 src_sbuf.st_size = 0; 4298 } 4299 } 4300 4301 if (src_sbuf.st_size) 4302 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size); 4303 4304 close_file(fsp1,False); 4305 4306 /* Ensure the modtime is set correctly on the destination file. */ 4307 fsp_set_pending_modtime( fsp2, src_sbuf.st_mtime); 4308 4309 /* 4310 * As we are opening fsp1 read-only we only expect 4311 * an error on close on fsp2 if we are out of space. 4312 * Thus we don't look at the error return from the 4313 * close of fsp1. 4314 */ 4315 *err_ret = close_file(fsp2,False); 4316 4317 return(ret == (SMB_OFF_T)src_sbuf.st_size); 4318} 4319 4320/**************************************************************************** 4321 Reply to a file copy. 4322****************************************************************************/ 4323 4324int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) 4325{ 4326 int outsize = 0; 4327 pstring name; 4328 pstring directory; 4329 pstring mask,newname; 4330 char *p; 4331 int count=0; 4332 int error = ERRnoaccess; 4333 int err = 0; 4334 BOOL has_wild; 4335 BOOL exists=False; 4336 int tid2 = SVAL(inbuf,smb_vwv0); 4337 int ofun = SVAL(inbuf,smb_vwv1); 4338 int flags = SVAL(inbuf,smb_vwv2); 4339 BOOL target_is_directory=False; 4340 BOOL bad_path1 = False; 4341 BOOL bad_path2 = False; 4342 BOOL rc = True; 4343 SMB_STRUCT_STAT sbuf1, sbuf2; 4344 NTSTATUS status; 4345 4346 START_PROFILE(SMBcopy); 4347 4348 *directory = *mask = 0; 4349 4350 p = smb_buf(inbuf); 4351 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True); 4352 if (!NT_STATUS_IS_OK(status)) { 4353 END_PROFILE(SMBcopy); 4354 return ERROR_NT(status); 4355 } 4356 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True); 4357 if (!NT_STATUS_IS_OK(status)) { 4358 END_PROFILE(SMBcopy); 4359 return ERROR_NT(status); 4360 } 4361 4362 DEBUG(3,("reply_copy : %s -> %s\n",name,newname)); 4363 4364 if (tid2 != conn->cnum) { 4365 /* can't currently handle inter share copies XXXX */ 4366 DEBUG(3,("Rejecting inter-share copy\n")); 4367 END_PROFILE(SMBcopy); 4368 return ERROR_DOS(ERRSRV,ERRinvdevice); 4369 } 4370 4371 RESOLVE_DFSPATH(name, conn, inbuf, outbuf); 4372 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf); 4373 4374 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1); 4375 unix_convert(newname,conn,0,&bad_path2,&sbuf2); 4376 4377 target_is_directory = VALID_STAT_OF_DIR(sbuf2); 4378 4379 if ((flags&1) && target_is_directory) { 4380 END_PROFILE(SMBcopy); 4381 return ERROR_DOS(ERRDOS,ERRbadfile); 4382 } 4383 4384 if ((flags&2) && !target_is_directory) { 4385 END_PROFILE(SMBcopy); 4386 return ERROR_DOS(ERRDOS,ERRbadpath); 4387 } 4388 4389 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) { 4390 /* wants a tree copy! XXXX */ 4391 DEBUG(3,("Rejecting tree copy\n")); 4392 END_PROFILE(SMBcopy); 4393 return ERROR_DOS(ERRSRV,ERRerror); 4394 } 4395 4396 p = strrchr_m(name,'/'); 4397 if (!p) { 4398 pstrcpy(directory,"./"); 4399 pstrcpy(mask,name); 4400 } else { 4401 *p = 0; 4402 pstrcpy(directory,name); 4403 pstrcpy(mask,p+1); 4404 } 4405 4406 /* 4407 * We should only check the mangled cache 4408 * here if unix_convert failed. This means 4409 * that the path in 'mask' doesn't exist 4410 * on the file system and so we need to look 4411 * for a possible mangle. This patch from 4412 * Tine Smukavec <valentin.smukavec@hermes.si>. 4413 */ 4414 4415 if (!rc && mangle_is_mangled(mask)) 4416 mangle_check_cache( mask, sizeof(pstring)-1 ); 4417 4418 has_wild = ms_has_wild(mask); 4419 4420 if (!has_wild) { 4421 pstrcat(directory,"/"); 4422 pstrcat(directory,mask); 4423 if (resolve_wildcards(directory,newname) && 4424 copy_file(directory,newname,conn,ofun, count,target_is_directory,&err)) 4425 count++; 4426 if(!count && err) { 4427 errno = err; 4428 END_PROFILE(SMBcopy); 4429 return(UNIXERROR(ERRHRD,ERRgeneral)); 4430 } 4431 if (!count) { 4432 exists = vfs_file_exist(conn,directory,NULL); 4433 } 4434 } else { 4435 struct smb_Dir *dir_hnd = NULL; 4436 const char *dname; 4437 pstring destname; 4438 4439 if (check_name(directory,conn)) 4440 dir_hnd = OpenDir(conn, directory); 4441 4442 if (dir_hnd) { 4443 long offset = 0; 4444 error = ERRbadfile; 4445 4446 if (strequal(mask,"????????.???")) 4447 pstrcpy(mask,"*"); 4448 4449 while ((dname = ReadDirName(dir_hnd, &offset))) { 4450 pstring fname; 4451 pstrcpy(fname,dname); 4452 4453 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) 4454 continue; 4455 4456 if(!mask_match(fname, mask, conn->case_sensitive)) 4457 continue; 4458 4459 error = ERRnoaccess; 4460 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname); 4461 pstrcpy(destname,newname); 4462 if (resolve_wildcards(fname,destname) && 4463 copy_file(fname,destname,conn,ofun, 4464 count,target_is_directory,&err)) 4465 count++; 4466 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname)); 4467 } 4468 CloseDir(dir_hnd); 4469 } 4470 } 4471 4472 if (count == 0) { 4473 if(err) { 4474 /* Error on close... */ 4475 errno = err; 4476 END_PROFILE(SMBcopy); 4477 return(UNIXERROR(ERRHRD,ERRgeneral)); 4478 } 4479 4480 if (exists) { 4481 END_PROFILE(SMBcopy); 4482 return ERROR_DOS(ERRDOS,error); 4483 } else { 4484 if((errno == ENOENT) && (bad_path1 || bad_path2)) { 4485 unix_ERR_class = ERRDOS; 4486 unix_ERR_code = ERRbadpath; 4487 } 4488 END_PROFILE(SMBcopy); 4489 return(UNIXERROR(ERRDOS,error)); 4490 } 4491 } 4492 4493 outsize = set_message(outbuf,1,0,True); 4494 SSVAL(outbuf,smb_vwv0,count); 4495 4496 END_PROFILE(SMBcopy); 4497 return(outsize); 4498} 4499 4500/**************************************************************************** 4501 Reply to a setdir. 4502****************************************************************************/ 4503 4504int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) 4505{ 4506 int snum; 4507 int outsize = 0; 4508 BOOL ok = False; 4509 pstring newdir; 4510 NTSTATUS status; 4511 4512 START_PROFILE(pathworks_setdir); 4513 4514 snum = SNUM(conn); 4515 if (!CAN_SETDIR(snum)) { 4516 END_PROFILE(pathworks_setdir); 4517 return ERROR_DOS(ERRDOS,ERRnoaccess); 4518 } 4519 4520 srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status, False); 4521 if (!NT_STATUS_IS_OK(status)) { 4522 END_PROFILE(pathworks_setdir); 4523 return ERROR_NT(status); 4524 } 4525 4526 RESOLVE_DFSPATH(newdir, conn, inbuf, outbuf); 4527 4528 if (strlen(newdir) == 0) { 4529 ok = True; 4530 } else { 4531 ok = vfs_directory_exist(conn,newdir,NULL); 4532 if (ok) 4533 string_set(&conn->connectpath,newdir); 4534 } 4535 4536 if (!ok) { 4537 END_PROFILE(pathworks_setdir); 4538 return ERROR_DOS(ERRDOS,ERRbadpath); 4539 } 4540 4541 outsize = set_message(outbuf,0,0,True); 4542 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh)); 4543 4544 DEBUG(3,("setdir %s\n", newdir)); 4545 4546 END_PROFILE(pathworks_setdir); 4547 return(outsize); 4548} 4549 4550/**************************************************************************** 4551 Get a lock pid, dealing with large count requests. 4552****************************************************************************/ 4553 4554uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format) 4555{ 4556 if(!large_file_format) 4557 return SVAL(data,SMB_LPID_OFFSET(data_offset)); 4558 else 4559 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset)); 4560} 4561 4562/**************************************************************************** 4563 Get a lock count, dealing with large count requests. 4564****************************************************************************/ 4565 4566SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format) 4567{ 4568 SMB_BIG_UINT count = 0; 4569 4570 if(!large_file_format) { 4571 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset)); 4572 } else { 4573 4574#if defined(HAVE_LONGLONG) 4575 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) | 4576 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset))); 4577#else /* HAVE_LONGLONG */ 4578 4579 /* 4580 * NT4.x seems to be broken in that it sends large file (64 bit) 4581 * lockingX calls even if the CAP_LARGE_FILES was *not* 4582 * negotiated. For boxes without large unsigned ints truncate the 4583 * lock count by dropping the top 32 bits. 4584 */ 4585 4586 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) { 4587 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n", 4588 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)), 4589 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) )); 4590 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0); 4591 } 4592 4593 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)); 4594#endif /* HAVE_LONGLONG */ 4595 } 4596 4597 return count; 4598} 4599 4600#if !defined(HAVE_LONGLONG) 4601/**************************************************************************** 4602 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-). 4603****************************************************************************/ 4604 4605static uint32 map_lock_offset(uint32 high, uint32 low) 4606{ 4607 unsigned int i; 4608 uint32 mask = 0; 4609 uint32 highcopy = high; 4610 4611 /* 4612 * Try and find out how many significant bits there are in high. 4613 */ 4614 4615 for(i = 0; highcopy; i++) 4616 highcopy >>= 1; 4617 4618 /* 4619 * We use 31 bits not 32 here as POSIX 4620 * lock offsets may not be negative. 4621 */ 4622 4623 mask = (~0) << (31 - i); 4624 4625 if(low & mask) 4626 return 0; /* Fail. */ 4627 4628 high <<= (31 - i); 4629 4630 return (high|low); 4631} 4632#endif /* !defined(HAVE_LONGLONG) */ 4633 4634/**************************************************************************** 4635 Get a lock offset, dealing with large offset requests. 4636****************************************************************************/ 4637 4638SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err) 4639{ 4640 SMB_BIG_UINT offset = 0; 4641 4642 *err = False; 4643 4644 if(!large_file_format) { 4645 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset)); 4646 } else { 4647 4648#if defined(HAVE_LONGLONG) 4649 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) | 4650 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset))); 4651#else /* HAVE_LONGLONG */ 4652 4653 /* 4654 * NT4.x seems to be broken in that it sends large file (64 bit) 4655 * lockingX calls even if the CAP_LARGE_FILES was *not* 4656 * negotiated. For boxes without large unsigned ints mangle the 4657 * lock offset by mapping the top 32 bits onto the lower 32. 4658 */ 4659 4660 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) { 4661 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)); 4662 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)); 4663 uint32 new_low = 0; 4664 4665 if((new_low = map_lock_offset(high, low)) == 0) { 4666 *err = True; 4667 return (SMB_BIG_UINT)-1; 4668 } 4669 4670 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n", 4671 (unsigned int)high, (unsigned int)low, (unsigned int)new_low )); 4672 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0); 4673 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low); 4674 } 4675 4676 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)); 4677#endif /* HAVE_LONGLONG */ 4678 } 4679 4680 return offset; 4681} 4682 4683/**************************************************************************** 4684 Reply to a lockingX request. 4685****************************************************************************/ 4686 4687int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) 4688{ 4689 files_struct *fsp = file_fsp(inbuf,smb_vwv2); 4690 unsigned char locktype = CVAL(inbuf,smb_vwv3); 4691 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1); 4692 uint16 num_ulocks = SVAL(inbuf,smb_vwv6); 4693 uint16 num_locks = SVAL(inbuf,smb_vwv7); 4694 SMB_BIG_UINT count = 0, offset = 0; 4695 uint16 lock_pid; 4696 int32 lock_timeout = IVAL(inbuf,smb_vwv4); 4697 int i; 4698 char *data; 4699 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False; 4700 BOOL err; 4701 BOOL my_lock_ctx = False; 4702 NTSTATUS status; 4703 4704 START_PROFILE(SMBlockingX); 4705 4706 CHECK_FSP(fsp,conn); 4707 4708 data = smb_buf(inbuf); 4709 4710 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) { 4711 /* we don't support these - and CANCEL_LOCK makes w2k 4712 and XP reboot so I don't really want to be 4713 compatible! (tridge) */ 4714 return ERROR_NT(NT_STATUS_UNSUCCESSFUL); 4715 } 4716 4717 if (locktype & LOCKING_ANDX_CANCEL_LOCK) { 4718 /* Need to make this like a cancel.... JRA. */ 4719 return ERROR_NT(NT_STATUS_UNSUCCESSFUL); 4720 } 4721 4722 /* Check if this is an oplock break on a file 4723 we have granted an oplock on. 4724 */ 4725 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) { 4726 /* Client can insist on breaking to none. */ 4727 BOOL break_to_none = (oplocklevel == 0); 4728 4729 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n", 4730 (unsigned int)oplocklevel, fsp->fnum )); 4731 4732 /* 4733 * Make sure we have granted an exclusive or batch oplock on this file. 4734 */ 4735 4736 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { 4737 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \ 4738no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name)); 4739 4740 /* if this is a pure oplock break request then don't send a reply */ 4741 if (num_locks == 0 && num_ulocks == 0) { 4742 END_PROFILE(SMBlockingX); 4743 return -1; 4744 } else { 4745 END_PROFILE(SMBlockingX); 4746 return ERROR_DOS(ERRDOS,ERRlock); 4747 } 4748 } 4749 4750 if (remove_oplock(fsp, break_to_none) == False) { 4751 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n", 4752 fsp->fsp_name )); 4753 } 4754 4755 /* if this is a pure oplock break request then don't send a reply */ 4756 if (num_locks == 0 && num_ulocks == 0) { 4757 /* Sanity check - ensure a pure oplock break is not a 4758 chained request. */ 4759 if(CVAL(inbuf,smb_vwv0) != 0xff) 4760 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n", 4761 (unsigned int)CVAL(inbuf,smb_vwv0) )); 4762 END_PROFILE(SMBlockingX); 4763 return -1; 4764 } 4765 } 4766 4767 /* 4768 * We do this check *after* we have checked this is not a oplock break 4769 * response message. JRA. 4770 */ 4771 4772 release_level_2_oplocks_on_change(fsp); 4773 4774 /* Data now points at the beginning of the list 4775 of smb_unlkrng structs */ 4776 for(i = 0; i < (int)num_ulocks; i++) { 4777 lock_pid = get_lock_pid( data, i, large_file_format); 4778 count = get_lock_count( data, i, large_file_format); 4779 offset = get_lock_offset( data, i, large_file_format, &err); 4780 4781 /* 4782 * There is no error code marked "stupid client bug".... :-). 4783 */ 4784 if(err) { 4785 END_PROFILE(SMBlockingX); 4786 return ERROR_DOS(ERRDOS,ERRnoaccess); 4787 } 4788 4789 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n", 4790 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name )); 4791 4792 status = do_unlock(fsp,conn,lock_pid,count,offset); 4793 if (NT_STATUS_V(status)) { 4794 END_PROFILE(SMBlockingX); 4795 return ERROR_NT(status); 4796 } 4797 } 4798 4799 /* Setup the timeout in seconds. */ 4800 4801 lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000); 4802 4803 /* Now do any requested locks */ 4804 data += ((large_file_format ? 20 : 10)*num_ulocks); 4805 4806 /* Data now points at the beginning of the list 4807 of smb_lkrng structs */ 4808 4809 for(i = 0; i < (int)num_locks; i++) { 4810 lock_pid = get_lock_pid( data, i, large_file_format); 4811 count = get_lock_count( data, i, large_file_format); 4812 offset = get_lock_offset( data, i, large_file_format, &err); 4813 4814 /* 4815 * There is no error code marked "stupid client bug".... :-). 4816 */ 4817 if(err) { 4818 END_PROFILE(SMBlockingX); 4819 return ERROR_DOS(ERRDOS,ERRnoaccess); 4820 } 4821 4822 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n", 4823 (double)offset, (double)count, (unsigned int)lock_pid, 4824 fsp->fsp_name, (int)lock_timeout )); 4825 4826 status = do_lock_spin(fsp,conn,lock_pid, count,offset, 4827 ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &my_lock_ctx); 4828 if (NT_STATUS_V(status)) { 4829 /* 4830 * Interesting fact found by IFSTEST /t LockOverlappedTest... 4831 * Even if it's our own lock context, we need to wait here as 4832 * there may be an unlock on the way. 4833 * So I removed a "&& !my_lock_ctx" from the following 4834 * if statement. JRA. 4835 */ 4836 if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) { 4837 /* 4838 * A blocking lock was requested. Package up 4839 * this smb into a queued request and push it 4840 * onto the blocking lock queue. 4841 */ 4842 if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) { 4843 END_PROFILE(SMBlockingX); 4844 return -1; 4845 } 4846 } 4847 break; 4848 } 4849 } 4850 4851 /* If any of the above locks failed, then we must unlock 4852 all of the previous locks (X/Open spec). */ 4853 if (i != num_locks && num_locks != 0) { 4854 /* 4855 * Ensure we don't do a remove on the lock that just failed, 4856 * as under POSIX rules, if we have a lock already there, we 4857 * will delete it (and we shouldn't) ..... 4858 */ 4859 for(i--; i >= 0; i--) { 4860 lock_pid = get_lock_pid( data, i, large_file_format); 4861 count = get_lock_count( data, i, large_file_format); 4862 offset = get_lock_offset( data, i, large_file_format, &err); 4863 4864 /* 4865 * There is no error code marked "stupid client bug".... :-). 4866 */ 4867 if(err) { 4868 END_PROFILE(SMBlockingX); 4869 return ERROR_DOS(ERRDOS,ERRnoaccess); 4870 } 4871 4872 do_unlock(fsp,conn,lock_pid,count,offset); 4873 } 4874 END_PROFILE(SMBlockingX); 4875 return ERROR_NT(status); 4876 } 4877 4878 set_message(outbuf,2,0,True); 4879 4880 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n", 4881 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) ); 4882 4883 END_PROFILE(SMBlockingX); 4884 return chain_reply(inbuf,outbuf,length,bufsize); 4885} 4886 4887/**************************************************************************** 4888 Reply to a SMBreadbmpx (read block multiplex) request. 4889****************************************************************************/ 4890 4891int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) 4892{ 4893 ssize_t nread = -1; 4894 ssize_t total_read; 4895 char *data; 4896 SMB_OFF_T startpos; 4897 int outsize; 4898 size_t maxcount; 4899 int max_per_packet; 4900 size_t tcount; 4901 int pad; 4902 files_struct *fsp = file_fsp(inbuf,smb_vwv0); 4903 START_PROFILE(SMBreadBmpx); 4904 4905 /* this function doesn't seem to work - disable by default */ 4906 if (!lp_readbmpx()) { 4907 END_PROFILE(SMBreadBmpx); 4908 return ERROR_DOS(ERRSRV,ERRuseSTD); 4909 } 4910 4911 outsize = set_message(outbuf,8,0,True); 4912 4913 CHECK_FSP(fsp,conn); 4914 CHECK_READ(fsp); 4915 4916 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1); 4917 maxcount = SVAL(inbuf,smb_vwv3); 4918 4919 data = smb_buf(outbuf); 4920 pad = ((long)data)%4; 4921 if (pad) 4922 pad = 4 - pad; 4923 data += pad; 4924 4925 max_per_packet = bufsize-(outsize+pad); 4926 tcount = maxcount; 4927 total_read = 0; 4928 4929 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) { 4930 END_PROFILE(SMBreadBmpx); 4931 return ERROR_DOS(ERRDOS,ERRlock); 4932 } 4933 4934 do { 4935 size_t N = MIN(max_per_packet,tcount-total_read); 4936 4937 nread = read_file(fsp,data,startpos,N); 4938 4939 if (nread <= 0) 4940 nread = 0; 4941 4942 if (nread < (ssize_t)N) 4943 tcount = total_read + nread; 4944 4945 set_message(outbuf,8,nread,False); 4946 SIVAL(outbuf,smb_vwv0,startpos); 4947 SSVAL(outbuf,smb_vwv2,tcount); 4948 SSVAL(outbuf,smb_vwv6,nread); 4949 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf)); 4950 4951 if (!send_smb(smbd_server_fd(),outbuf)) 4952 exit_server("reply_readbmpx: send_smb failed."); 4953 4954 total_read += nread; 4955 startpos += nread; 4956 } while (total_read < (ssize_t)tcount); 4957 4958 END_PROFILE(SMBreadBmpx); 4959 return(-1); 4960} 4961 4962/**************************************************************************** 4963 Reply to a SMBsetattrE. 4964****************************************************************************/ 4965 4966int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize) 4967{ 4968 struct utimbuf unix_times; 4969 int outsize = 0; 4970 files_struct *fsp = file_fsp(inbuf,smb_vwv0); 4971 START_PROFILE(SMBsetattrE); 4972 4973 outsize = set_message(outbuf,0,0,True); 4974 4975 if(!fsp || (fsp->conn != conn)) { 4976 END_PROFILE(SMBgetattrE); 4977 return ERROR_DOS(ERRDOS,ERRbadfid); 4978 } 4979 4980 /* 4981 * Convert the DOS times into unix times. Ignore create 4982 * time as UNIX can't set this. 4983 */ 4984 4985 unix_times.actime = make_unix_date2(inbuf+smb_vwv3); 4986 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5); 4987 4988 /* 4989 * Patch from Ray Frush <frush@engr.colostate.edu> 4990 * Sometimes times are sent as zero - ignore them. 4991 */ 4992 4993 if (null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) { 4994 /* Ignore request */ 4995 if( DEBUGLVL( 3 ) ) { 4996 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum); 4997 dbgtext( "ignoring zero request - not setting timestamps of 0\n" ); 4998 } 4999 END_PROFILE(SMBsetattrE); 5000 return(outsize); 5001 } else if (!null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) { 5002 /* set modify time = to access time if modify time was unset */ 5003 unix_times.modtime = unix_times.actime; 5004 } 5005 5006 /* Set the date on this file */ 5007 /* Should we set pending modtime here ? JRA */ 5008 if(file_utime(conn, fsp->fsp_name, &unix_times)) { 5009 END_PROFILE(SMBsetattrE); 5010 return ERROR_DOS(ERRDOS,ERRnoaccess); 5011 } 5012 5013 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n", 5014 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) ); 5015 5016 END_PROFILE(SMBsetattrE); 5017 return(outsize); 5018} 5019 5020 5021/* Back from the dead for OS/2..... JRA. */ 5022 5023/**************************************************************************** 5024 Reply to a SMBwritebmpx (write block multiplex primary) request. 5025****************************************************************************/ 5026 5027int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize) 5028{ 5029 size_t numtowrite; 5030 ssize_t nwritten = -1; 5031 int outsize = 0; 5032 SMB_OFF_T startpos; 5033 size_t tcount; 5034 BOOL write_through; 5035 int smb_doff; 5036 char *data; 5037 files_struct *fsp = file_fsp(inbuf,smb_vwv0); 5038 START_PROFILE(SMBwriteBmpx); 5039 5040 CHECK_FSP(fsp,conn); 5041 CHECK_WRITE(fsp); 5042 CHECK_ERROR(fsp); 5043 5044 tcount = SVAL(inbuf,smb_vwv1); 5045 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3); 5046 write_through = BITSETW(inbuf+smb_vwv7,0); 5047 numtowrite = SVAL(inbuf,smb_vwv10); 5048 smb_doff = SVAL(inbuf,smb_vwv11); 5049 5050 data = smb_base(inbuf) + smb_doff; 5051 5052 /* If this fails we need to send an SMBwriteC response, 5053 not an SMBwritebmpx - set this up now so we don't forget */ 5054 SCVAL(outbuf,smb_com,SMBwritec); 5055 5056 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) { 5057 END_PROFILE(SMBwriteBmpx); 5058 return(ERROR_DOS(ERRDOS,ERRlock)); 5059 } 5060 5061 nwritten = write_file(fsp,data,startpos,numtowrite); 5062 5063 if(lp_syncalways(SNUM(conn)) || write_through) 5064 sync_file(conn,fsp); 5065 5066 if(nwritten < (ssize_t)numtowrite) { 5067 END_PROFILE(SMBwriteBmpx); 5068 return(UNIXERROR(ERRHRD,ERRdiskfull)); 5069 } 5070 5071 /* If the maximum to be written to this file 5072 is greater than what we just wrote then set 5073 up a secondary struct to be attached to this 5074 fd, we will use this to cache error messages etc. */ 5075 5076 if((ssize_t)tcount > nwritten) { 5077 write_bmpx_struct *wbms; 5078 if(fsp->wbmpx_ptr != NULL) 5079 wbms = fsp->wbmpx_ptr; /* Use an existing struct */ 5080 else 5081 wbms = SMB_MALLOC_P(write_bmpx_struct); 5082 if(!wbms) { 5083 DEBUG(0,("Out of memory in reply_readmpx\n")); 5084 END_PROFILE(SMBwriteBmpx); 5085 return(ERROR_DOS(ERRSRV,ERRnoresource)); 5086 } 5087 wbms->wr_mode = write_through; 5088 wbms->wr_discard = False; /* No errors yet */ 5089 wbms->wr_total_written = nwritten; 5090 wbms->wr_errclass = 0; 5091 wbms->wr_error = 0; 5092 fsp->wbmpx_ptr = wbms; 5093 } 5094 5095 /* We are returning successfully, set the message type back to 5096 SMBwritebmpx */ 5097 SCVAL(outbuf,smb_com,SMBwriteBmpx); 5098 5099 outsize = set_message(outbuf,1,0,True); 5100 5101 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */ 5102 5103 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n", 5104 fsp->fnum, (int)numtowrite, (int)nwritten ) ); 5105 5106 if (write_through && tcount==nwritten) { 5107 /* We need to send both a primary and a secondary response */ 5108 smb_setlen(outbuf,outsize - 4); 5109 if (!send_smb(smbd_server_fd(),outbuf)) 5110 exit_server("reply_writebmpx: send_smb failed."); 5111 5112 /* Now the secondary */ 5113 outsize = set_message(outbuf,1,0,True); 5114 SCVAL(outbuf,smb_com,SMBwritec); 5115 SSVAL(outbuf,smb_vwv0,nwritten); 5116 } 5117 5118 END_PROFILE(SMBwriteBmpx); 5119 return(outsize); 5120} 5121 5122/**************************************************************************** 5123 Reply to a SMBwritebs (write block multiplex secondary) request. 5124****************************************************************************/ 5125 5126int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) 5127{ 5128 size_t numtowrite; 5129 ssize_t nwritten = -1; 5130 int outsize = 0; 5131 SMB_OFF_T startpos; 5132 size_t tcount; 5133 BOOL write_through; 5134 int smb_doff; 5135 char *data; 5136 write_bmpx_struct *wbms; 5137 BOOL send_response = False; 5138 files_struct *fsp = file_fsp(inbuf,smb_vwv0); 5139 START_PROFILE(SMBwriteBs); 5140 5141 CHECK_FSP(fsp,conn); 5142 CHECK_WRITE(fsp); 5143 5144 tcount = SVAL(inbuf,smb_vwv1); 5145 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2); 5146 numtowrite = SVAL(inbuf,smb_vwv6); 5147 smb_doff = SVAL(inbuf,smb_vwv7); 5148 5149 data = smb_base(inbuf) + smb_doff; 5150 5151 /* We need to send an SMBwriteC response, not an SMBwritebs */ 5152 SCVAL(outbuf,smb_com,SMBwritec); 5153 5154 /* This fd should have an auxiliary struct attached, 5155 check that it does */ 5156 wbms = fsp->wbmpx_ptr; 5157 if(!wbms) { 5158 END_PROFILE(SMBwriteBs); 5159 return(-1); 5160 } 5161 5162 /* If write through is set we can return errors, else we must cache them */ 5163 write_through = wbms->wr_mode; 5164 5165 /* Check for an earlier error */ 5166 if(wbms->wr_discard) { 5167 END_PROFILE(SMBwriteBs); 5168 return -1; /* Just discard the packet */ 5169 } 5170 5171 nwritten = write_file(fsp,data,startpos,numtowrite); 5172 5173 if(lp_syncalways(SNUM(conn)) || write_through) 5174 sync_file(conn,fsp); 5175 5176 if (nwritten < (ssize_t)numtowrite) { 5177 if(write_through) { 5178 /* We are returning an error - we can delete the aux struct */ 5179 if (wbms) 5180 free((char *)wbms); 5181 fsp->wbmpx_ptr = NULL; 5182 END_PROFILE(SMBwriteBs); 5183 return(ERROR_DOS(ERRHRD,ERRdiskfull)); 5184 } 5185 END_PROFILE(SMBwriteBs); 5186 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull)); 5187 } 5188 5189 /* Increment the total written, if this matches tcount 5190 we can discard the auxiliary struct (hurrah !) and return a writeC */ 5191 wbms->wr_total_written += nwritten; 5192 if(wbms->wr_total_written >= tcount) { 5193 if (write_through) { 5194 outsize = set_message(outbuf,1,0,True); 5195 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written); 5196 send_response = True; 5197 } 5198 5199 free((char *)wbms); 5200 fsp->wbmpx_ptr = NULL; 5201 } 5202 5203 if(send_response) { 5204 END_PROFILE(SMBwriteBs); 5205 return(outsize); 5206 } 5207 5208 END_PROFILE(SMBwriteBs); 5209 return(-1); 5210} 5211 5212/**************************************************************************** 5213 Reply to a SMBgetattrE. 5214****************************************************************************/ 5215 5216int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize) 5217{ 5218 SMB_STRUCT_STAT sbuf; 5219 int outsize = 0; 5220 int mode; 5221 files_struct *fsp = file_fsp(inbuf,smb_vwv0); 5222 START_PROFILE(SMBgetattrE); 5223 5224 outsize = set_message(outbuf,11,0,True); 5225 5226 if(!fsp || (fsp->conn != conn)) { 5227 END_PROFILE(SMBgetattrE); 5228 return ERROR_DOS(ERRDOS,ERRbadfid); 5229 } 5230 5231 /* Do an fstat on this file */ 5232 if(fsp_stat(fsp, &sbuf)) { 5233 END_PROFILE(SMBgetattrE); 5234 return(UNIXERROR(ERRDOS,ERRnoaccess)); 5235 } 5236 5237 mode = dos_mode(conn,fsp->fsp_name,&sbuf); 5238 5239 /* 5240 * Convert the times into dos times. Set create 5241 * date to be last modify date as UNIX doesn't save 5242 * this. 5243 */ 5244 5245 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)))); 5246 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime); 5247 /* Should we check pending modtime here ? JRA */ 5248 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime); 5249 5250 if (mode & aDIR) { 5251 SIVAL(outbuf,smb_vwv6,0); 5252 SIVAL(outbuf,smb_vwv8,0); 5253 } else { 5254 uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf); 5255 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size); 5256 SIVAL(outbuf,smb_vwv8,allocation_size); 5257 } 5258 SSVAL(outbuf,smb_vwv10, mode); 5259 5260 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum)); 5261 5262 END_PROFILE(SMBgetattrE); 5263 return(outsize); 5264} 5265