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