Changeset 988 for vendor/current/source3/smbd/close.c
- Timestamp:
- Nov 24, 2016, 1:14:11 PM (9 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
vendor/current/source3/smbd/close.c
r746 r988 25 25 #include "smbd/smbd.h" 26 26 #include "smbd/globals.h" 27 #include "smbd/scavenger.h" 27 28 #include "fake_file.h" 28 29 #include "transfer_file.h" 29 30 #include "auth.h" 30 31 #include "messages.h" 32 #include "../librpc/gen_ndr/open_files.h" 31 33 32 34 /**************************************************************************** … … 46 48 NTSTATUS status; 47 49 48 if (!*lp_magic script(SNUM(conn))) {50 if (!*lp_magic_script(talloc_tos(), SNUM(conn))) { 49 51 return NT_STATUS_OK; 50 52 } … … 62 64 } 63 65 64 if (!strequal(lp_magic script(SNUM(conn)),p)) {66 if (!strequal(lp_magic_script(talloc_tos(), SNUM(conn)),p)) { 65 67 status = NT_STATUS_OK; 66 68 goto out; 67 69 } 68 70 69 if (*lp_magic output(SNUM(conn))) {70 magic_output = lp_magic output(SNUM(conn));71 if (*lp_magic_output(talloc_tos(), SNUM(conn))) { 72 magic_output = lp_magic_output(talloc_tos(), SNUM(conn)); 71 73 } else { 72 74 magic_output = talloc_asprintf(ctx, … … 118 120 } 119 121 120 if (transfer_file(tmp_fd,outfd,( SMB_OFF_T)st.st_ex_size) == (SMB_OFF_T)-1) {122 if (transfer_file(tmp_fd,outfd,(off_t)st.st_ex_size) == (off_t)-1) { 121 123 int err = errno; 122 124 close(tmp_fd); … … 147 149 148 150 if (fsp->fh->fd != -1) { 149 if(flush_write_cache(fsp, CLOSE_FLUSH) == -1) {151 if(flush_write_cache(fsp, SAMBA_CLOSE_FLUSH) == -1) { 150 152 status = map_nt_error_from_unix(errno); 151 153 } … … 154 156 155 157 return status; 156 }157 158 /****************************************************************************159 If any deferred opens are waiting on this close, notify them.160 ****************************************************************************/161 162 static void notify_deferred_opens(struct messaging_context *msg_ctx,163 struct share_mode_lock *lck)164 {165 int i;166 167 if (!should_notify_deferred_opens()) {168 return;169 }170 171 for (i=0; i<lck->num_share_modes; i++) {172 struct share_mode_entry *e = &lck->share_modes[i];173 174 if (!is_deferred_open_entry(e)) {175 continue;176 }177 178 if (procid_is_me(&e->pid)) {179 /*180 * We need to notify ourself to retry the open. Do181 * this by finding the queued SMB record, moving it to182 * the head of the queue and changing the wait time to183 * zero.184 */185 schedule_deferred_open_message_smb(e->op_mid);186 } else {187 char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE];188 189 share_mode_entry_to_message(msg, e);190 191 messaging_send_buf(msg_ctx, e->pid, MSG_SMB_OPEN_RETRY,192 (uint8 *)msg,193 MSG_SMB_SHARE_MODE_ENTRY_SIZE);194 }195 }196 158 } 197 159 … … 233 195 for (i=0; i<num_streams; i++) { 234 196 int res; 235 struct smb_filename *smb_fname_stream = NULL;197 struct smb_filename *smb_fname_stream; 236 198 237 199 if (strequal(stream_info[i].name, "::$DATA")) { … … 239 201 } 240 202 241 status = create_synthetic_smb_fname(talloc_tos(), fname, 242 stream_info[i].name, NULL, 243 &smb_fname_stream); 244 245 if (!NT_STATUS_IS_OK(status)) { 203 smb_fname_stream = synthetic_smb_fname( 204 talloc_tos(), fname, stream_info[i].name, NULL); 205 206 if (smb_fname_stream == NULL) { 246 207 DEBUG(0, ("talloc_aprintf failed\n")); 208 status = NT_STATUS_NO_MEMORY; 247 209 goto fail; 248 210 } … … 274 236 { 275 237 connection_struct *conn = fsp->conn; 238 struct server_id self = messaging_server_id(conn->sconn->msg_ctx); 276 239 bool delete_file = false; 277 240 bool changed_user = false; … … 283 246 const struct security_token *del_nt_token = NULL; 284 247 bool got_tokens = false; 248 bool normal_close; 249 int ret_flock; 285 250 286 251 /* Ensure any pending write time updates are done. */ 287 252 if (fsp->update_write_time_event) { 288 update_write_time_handler( smbd_event_context(),253 update_write_time_handler(fsp->conn->sconn->ev_ctx, 289 254 fsp->update_write_time_event, 290 255 timeval_current(), … … 298 263 */ 299 264 300 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL, 301 NULL); 302 265 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id); 303 266 if (lck == NULL) { 304 267 DEBUG(0, ("close_remove_share_mode: Could not get share mode " 305 268 "lock for file %s\n", fsp_str_dbg(fsp))); 306 status = NT_STATUS_INVALID_PARAMETER; 307 goto done; 269 return NT_STATUS_INVALID_PARAMETER; 308 270 } 309 271 … … 312 274 "for file %s\n", 313 275 fsp_str_dbg(fsp))); 314 set_close_write_time(fsp, lck-> changed_write_time);276 set_close_write_time(fsp, lck->data->changed_write_time); 315 277 } else if (fsp->update_write_time_on_close) { 316 278 /* Someone had a pending write. */ … … 330 292 } 331 293 332 if (!del_share_mode(lck, fsp)) {333 DEBUG(0, ("close_remove_share_mode: Could not delete share "334 "entry for file %s\n",335 fsp_str_dbg(fsp)));336 }337 338 294 if (fsp->initial_delete_on_close && 339 295 !is_delete_on_close_set(lck, fsp->name_hash)) { … … 348 304 } 349 305 fsp->delete_on_close = true; 350 set_delete_on_close_lck(fsp, lck, True,306 set_delete_on_close_lck(fsp, lck, 351 307 get_current_nttok(conn), 352 308 get_current_utok(conn)); … … 363 319 If this is the case, then don't delete. If all opens are 364 320 POSIX delete now. */ 365 for (i=0; i<lck->num_share_modes; i++) { 366 struct share_mode_entry *e = &lck->share_modes[i]; 367 if (is_valid_share_mode_entry(e) && 368 e->name_hash == fsp->name_hash) { 369 if (fsp->posix_open && (e->flags & SHARE_MODE_FLAG_POSIX_OPEN)) { 370 continue; 371 } 372 delete_file = False; 373 break; 374 } 375 } 376 } 377 378 /* Notify any deferred opens waiting on this close. */ 379 notify_deferred_opens(conn->sconn->msg_ctx, lck); 380 reply_to_oplock_break_requests(fsp); 321 for (i=0; i<lck->data->num_share_modes; i++) { 322 struct share_mode_entry *e = &lck->data->share_modes[i]; 323 324 if (!is_valid_share_mode_entry(e)) { 325 continue; 326 } 327 if (e->name_hash != fsp->name_hash) { 328 continue; 329 } 330 if ((fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) 331 && (e->flags & SHARE_MODE_FLAG_POSIX_OPEN)) { 332 continue; 333 } 334 if (serverid_equal(&self, &e->pid) && 335 (e->share_file_id == fsp->fh->gen_id)) { 336 continue; 337 } 338 if (share_mode_stale_pid(lck->data, i)) { 339 continue; 340 } 341 delete_file = False; 342 break; 343 } 344 } 381 345 382 346 /* … … 385 349 */ 386 350 387 if (!(close_type == NORMAL_CLOSE || close_type == SHUTDOWN_CLOSE) || 388 !delete_file) { 389 TALLOC_FREE(lck); 390 return NT_STATUS_OK; 351 normal_close = (close_type == NORMAL_CLOSE || close_type == SHUTDOWN_CLOSE); 352 353 if (!normal_close || !delete_file) { 354 status = NT_STATUS_OK; 355 goto done; 391 356 } 392 357 … … 497 462 498 463 fsp->delete_on_close = false; 499 set_delete_on_close_lck(fsp, lck, false, NULL, NULL);464 reset_delete_on_close_lck(fsp, lck); 500 465 501 466 done: … … 504 469 /* unbecome user. */ 505 470 pop_sec_ctx(); 471 } 472 473 /* remove filesystem sharemodes */ 474 ret_flock = SMB_VFS_KERNEL_FLOCK(fsp, 0, 0); 475 if (ret_flock == -1) { 476 DEBUG(2, ("close_remove_share_mode: removing kernel flock for " 477 "%s failed: %s\n", fsp_str_dbg(fsp), 478 strerror(errno))); 479 } 480 481 if (!del_share_mode(lck, fsp)) { 482 DEBUG(0, ("close_remove_share_mode: Could not delete share " 483 "entry for file %s\n", fsp_str_dbg(fsp))); 506 484 } 507 485 … … 567 545 } 568 546 569 /* On close if we're changing the real file time we 570 * must update it in the open file db too. */ 571 (void)set_write_time(fsp->file_id, fsp->close_write_time); 572 573 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL, NULL); 547 /* 548 * get_existing_share_mode_lock() isn't really the right 549 * call here, as we're being called after 550 * close_remove_share_mode() inside close_normal_file() 551 * so it's quite normal to not have an existing share 552 * mode here. However, get_share_mode_lock() doesn't 553 * work because that will create a new share mode if 554 * one doesn't exist - so stick with this call (just 555 * ignore any error we get if the share mode doesn't 556 * exist. 557 */ 558 559 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id); 574 560 if (lck) { 561 /* On close if we're changing the real file time we 562 * must update it in the open file db too. */ 563 (void)set_write_time(fsp->file_id, fsp->close_write_time); 564 575 565 /* Close write times overwrite sticky write times 576 566 so we must replace any sticky write time here. */ 577 if (!null_timespec(lck-> changed_write_time)) {567 if (!null_timespec(lck->data->changed_write_time)) { 578 568 (void)set_sticky_write_time(fsp->file_id, fsp->close_write_time); 579 569 } … … 582 572 583 573 ft.mtime = fsp->close_write_time; 584 /* We must use NULL for the fsp handle here, as smb_set_file_time() 585 checks the fsp access_mask, which may not include FILE_WRITE_ATTRIBUTES. 586 As this is a close based update, we are not directly changing the 574 /* As this is a close based update, we are not directly changing the 587 575 file attributes from a client call, but indirectly from a write. */ 588 status = smb_set_file_time(fsp->conn, NULL, fsp->fsp_name, &ft, false);576 status = smb_set_file_time(fsp->conn, fsp, fsp->fsp_name, &ft, false); 589 577 if (!NT_STATUS_IS_OK(status)) { 590 578 DEBUG(10,("update_write_time_on_close: smb_set_file_time " … … 620 608 NTSTATUS tmp; 621 609 connection_struct *conn = fsp->conn; 622 623 if (close_type == ERROR_CLOSE) { 624 cancel_aio_by_fsp(fsp); 625 } else { 610 bool is_durable = false; 611 612 if (fsp->num_aio_requests != 0) { 613 614 if (close_type != SHUTDOWN_CLOSE) { 615 /* 616 * reply_close and the smb2 close must have 617 * taken care of this. No other callers of 618 * close_file should ever have created async 619 * I/O. 620 * 621 * We need to panic here because if we close() 622 * the fd while we have outstanding async I/O 623 * requests, in the worst case we could end up 624 * writing to the wrong file. 625 */ 626 DEBUG(0, ("fsp->num_aio_requests=%u\n", 627 fsp->num_aio_requests)); 628 smb_panic("can not close with outstanding aio " 629 "requests"); 630 } 631 626 632 /* 627 * If we're finishing async io on a close we can get a write 628 * error here, we must remember this. 633 * For shutdown close, just drop the async requests 634 * including a potential close request pending for 635 * this fsp. Drop the close request first, the 636 * destructor for the aio_requests would execute it. 629 637 */ 630 int ret = wait_for_aio_completion(fsp); 631 if (ret) { 632 status = ntstatus_keeperror( 633 status, map_nt_error_from_unix(ret)); 638 TALLOC_FREE(fsp->deferred_close); 639 640 while (fsp->num_aio_requests != 0) { 641 /* 642 * The destructor of the req will remove 643 * itself from the fsp. 644 * Don't use TALLOC_FREE here, this will overwrite 645 * what the destructor just wrote into 646 * aio_requests[0]. 647 */ 648 talloc_free(fsp->aio_requests[0]); 634 649 } 635 650 } … … 642 657 tmp = close_filestruct(fsp); 643 658 status = ntstatus_keeperror(status, tmp); 659 660 if (NT_STATUS_IS_OK(status) && fsp->op != NULL) { 661 is_durable = fsp->op->global->durable; 662 } 663 664 if (close_type != SHUTDOWN_CLOSE) { 665 is_durable = false; 666 } 667 668 if (is_durable) { 669 DATA_BLOB new_cookie = data_blob_null; 670 671 tmp = SMB_VFS_DURABLE_DISCONNECT(fsp, 672 fsp->op->global->backend_cookie, 673 fsp->op, 674 &new_cookie); 675 if (NT_STATUS_IS_OK(tmp)) { 676 struct timeval tv; 677 NTTIME now; 678 679 if (req != NULL) { 680 tv = req->request_time; 681 } else { 682 tv = timeval_current(); 683 } 684 now = timeval_to_nttime(&tv); 685 686 data_blob_free(&fsp->op->global->backend_cookie); 687 fsp->op->global->backend_cookie = new_cookie; 688 689 fsp->op->compat = NULL; 690 tmp = smbXsrv_open_close(fsp->op, now); 691 if (!NT_STATUS_IS_OK(tmp)) { 692 DEBUG(1, ("Failed to update smbXsrv_open " 693 "record when disconnecting durable " 694 "handle for file %s: %s - " 695 "proceeding with normal close\n", 696 fsp_str_dbg(fsp), nt_errstr(tmp))); 697 } 698 scavenger_schedule_disconnected(fsp); 699 } else { 700 DEBUG(1, ("Failed to disconnect durable handle for " 701 "file %s: %s - proceeding with normal " 702 "close\n", fsp_str_dbg(fsp), nt_errstr(tmp))); 703 } 704 if (!NT_STATUS_IS_OK(tmp)) { 705 is_durable = false; 706 } 707 } 708 709 if (is_durable) { 710 /* 711 * This is the case where we successfully disconnected 712 * a durable handle and closed the underlying file. 713 * In all other cases, we proceed with a genuine close. 714 */ 715 DEBUG(10, ("%s disconnected durable handle for file %s\n", 716 conn->session_info->unix_info->unix_name, 717 fsp_str_dbg(fsp))); 718 file_free(req, fsp); 719 return NT_STATUS_OK; 720 } 721 722 if (fsp->op != NULL) { 723 /* 724 * Make sure the handle is not marked as durable anymore 725 */ 726 fsp->op->global->durable = false; 727 } 644 728 645 729 if (fsp->print_file) { … … 652 736 /* Remove the oplock before potentially deleting the file. */ 653 737 if(fsp->oplock_type) { 654 re lease_file_oplock(fsp);738 remove_oplock(fsp); 655 739 } 656 740 … … 692 776 693 777 DEBUG(2,("%s closed file %s (numopen=%d) %s\n", 694 conn->session_info->unix_ name, fsp_str_dbg(fsp),778 conn->session_info->unix_info->unix_name, fsp_str_dbg(fsp), 695 779 conn->num_files_open - 1, 696 780 nt_errstr(status) )); … … 700 784 } 701 785 /**************************************************************************** 702 Static function used by reply_rmdir to delete an entire directory786 Function used by reply_rmdir to delete an entire directory 703 787 tree recursively. Return True on ok, False on fail. 704 788 ****************************************************************************/ 705 789 706 staticbool recursive_rmdir(TALLOC_CTX *ctx,707 708 790 bool recursive_rmdir(TALLOC_CTX *ctx, 791 connection_struct *conn, 792 struct smb_filename *smb_dname) 709 793 { 710 794 const char *dname = NULL; … … 725 809 char *fullname = NULL; 726 810 bool do_break = true; 727 NTSTATUS status;728 811 729 812 if (ISDOT(dname) || ISDOTDOT(dname)) { … … 748 831 } 749 832 750 s tatus = create_synthetic_smb_fname(talloc_tos(), fullname,751 NULL, NULL,752 &smb_dname_full);753 if (!NT_STATUS_IS_OK(status)) {833 smb_dname_full = synthetic_smb_fname(talloc_tos(), fullname, 834 NULL, NULL); 835 if (smb_dname_full == NULL) { 836 errno = ENOMEM; 754 837 goto err_break; 755 838 } … … 823 906 } 824 907 825 if(((errno == ENOTEMPTY)||(errno == EEXIST)) && *lp_veto_files( SNUM(conn))) {908 if(((errno == ENOTEMPTY)||(errno == EEXIST)) && *lp_veto_files(talloc_tos(), SNUM(conn))) { 826 909 /* 827 910 * Check to see if the only thing in this directory are … … 866 949 * Are we allowed to delete them ? */ 867 950 868 if(!lp_ recursive_veto_delete(SNUM(conn))) {951 if(!lp_delete_veto_files(SNUM(conn))) { 869 952 TALLOC_FREE(dir_hnd); 870 953 errno = ENOTEMPTY; … … 879 962 char *fullname = NULL; 880 963 bool do_break = true; 881 NTSTATUS status;882 964 883 965 if (ISDOT(dname) || ISDOTDOT(dname)) { … … 901 983 } 902 984 903 status = create_synthetic_smb_fname(talloc_tos(), 904 fullname, NULL, 905 NULL, 906 &smb_dname_full); 907 if (!NT_STATUS_IS_OK(status)) { 908 errno = map_errno_from_nt_status(status); 985 smb_dname_full = synthetic_smb_fname( 986 talloc_tos(), fullname, NULL, NULL); 987 if (smb_dname_full == NULL) { 988 errno = ENOMEM; 909 989 goto err_break; 910 990 } … … 964 1044 enum file_close_type close_type) 965 1045 { 1046 struct server_id self = messaging_server_id(fsp->conn->sconn->msg_ctx); 966 1047 struct share_mode_lock *lck = NULL; 967 1048 bool delete_dir = False; … … 970 1051 const struct security_token *del_nt_token = NULL; 971 1052 const struct security_unix_token *del_token = NULL; 1053 NTSTATUS notify_status; 1054 1055 if (fsp->conn->sconn->using_smb2) { 1056 notify_status = STATUS_NOTIFY_CLEANUP; 1057 } else { 1058 notify_status = NT_STATUS_OK; 1059 } 972 1060 973 1061 /* … … 976 1064 */ 977 1065 978 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL, 979 NULL); 980 1066 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id); 981 1067 if (lck == NULL) { 982 1068 DEBUG(0, ("close_directory: Could not get share mode lock for " 983 1069 "%s\n", fsp_str_dbg(fsp))); 984 status = NT_STATUS_INVALID_PARAMETER; 985 goto out; 986 } 987 988 if (!del_share_mode(lck, fsp)) { 989 DEBUG(0, ("close_directory: Could not delete share entry for " 990 "%s\n", fsp_str_dbg(fsp))); 1070 return NT_STATUS_INVALID_PARAMETER; 991 1071 } 992 1072 … … 1004 1084 send_stat_cache_delete_message(fsp->conn->sconn->msg_ctx, 1005 1085 fsp->fsp_name->base_name); 1006 set_delete_on_close_lck(fsp, lck, true,1086 set_delete_on_close_lck(fsp, lck, 1007 1087 get_current_nttok(fsp->conn), 1008 1088 get_current_utok(fsp->conn)); … … 1020 1100 /* See if others still have the dir open. If this is the 1021 1101 * case, then don't delete. If all opens are POSIX delete now. */ 1022 for (i=0; i<lck-> num_share_modes; i++) {1023 struct share_mode_entry *e = &lck-> share_modes[i];1102 for (i=0; i<lck->data->num_share_modes; i++) { 1103 struct share_mode_entry *e = &lck->data->share_modes[i]; 1024 1104 if (is_valid_share_mode_entry(e) && 1025 1105 e->name_hash == fsp->name_hash) { 1026 if (fsp->posix_open && (e->flags & SHARE_MODE_FLAG_POSIX_OPEN)) { 1106 if ((fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) && 1107 (e->flags & SHARE_MODE_FLAG_POSIX_OPEN)) 1108 { 1109 continue; 1110 } 1111 if (serverid_equal(&self, &e->pid) && 1112 (e->share_file_id == fsp->fh->gen_id)) { 1113 continue; 1114 } 1115 if (share_mode_stale_pid(lck->data, i)) { 1027 1116 continue; 1028 1117 } … … 1048 1137 del_nt_token); 1049 1138 1139 if (!del_share_mode(lck, fsp)) { 1140 DEBUG(0, ("close_directory: Could not delete share entry for " 1141 "%s\n", fsp_str_dbg(fsp))); 1142 } 1143 1050 1144 TALLOC_FREE(lck); 1051 1145 … … 1057 1151 DEBUG(5, ("delete_all_streams failed: %s\n", 1058 1152 nt_errstr(status))); 1059 goto out;1153 return status; 1060 1154 } 1061 1155 } … … 1075 1169 */ 1076 1170 1077 if (NT_STATUS_IS_OK(status)) {1078 remove_pending_change_notify_requests_by_fid(fsp, NT_STATUS_DELETE_PENDING);1171 if (NT_STATUS_IS_OK(status)) { 1172 notify_status = NT_STATUS_DELETE_PENDING; 1079 1173 } 1080 1174 } else { 1175 if (!del_share_mode(lck, fsp)) { 1176 DEBUG(0, ("close_directory: Could not delete share entry for " 1177 "%s\n", fsp_str_dbg(fsp))); 1178 } 1179 1081 1180 TALLOC_FREE(lck); 1082 remove_pending_change_notify_requests_by_fid(1083 fsp, NT_STATUS_OK); 1084 }1181 } 1182 1183 remove_pending_change_notify_requests_by_fid(fsp, notify_status); 1085 1184 1086 1185 status1 = fd_close(fsp); … … 1098 1197 file_free(req, fsp); 1099 1198 1100 out:1101 TALLOC_FREE(lck);1102 1199 if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(status1)) { 1103 1200 status = status1; … … 1153 1250 DATA_BLOB *data) 1154 1251 { 1155 struct smbd_server_connection *sconn;1156 1252 files_struct *fsp = NULL; 1157 1253 struct share_mode_entry e; 1158 1159 sconn = msg_ctx_to_sconn(msg_ctx); 1160 if (sconn == NULL) { 1161 DEBUG(1, ("could not find sconn\n")); 1162 return; 1163 } 1254 struct smbd_server_connection *sconn = 1255 talloc_get_type_abort(private_data, 1256 struct smbd_server_connection); 1164 1257 1165 1258 message_to_share_mode_entry(&e, (char *)data->data);
Note:
See TracChangeset
for help on using the changeset viewer.