1/* 2 Unix SMB/CIFS implementation. 3 Locking functions 4 Copyright (C) Andrew Tridgell 1992-2000 5 Copyright (C) Jeremy Allison 1992-2000 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 2 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program; if not, write to the Free Software 19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 21 Revision History: 22 23 12 aug 96: Erik.Devriendt@te6.siemens.be 24 added support for shared memory implementation of share mode locking 25 26 May 1997. Jeremy Allison (jallison@whistle.com). Modified share mode 27 locking to deal with multiple share modes per open file. 28 29 September 1997. Jeremy Allison (jallison@whistle.com). Added oplock 30 support. 31 32 rewrtten completely to use new tdb code. Tridge, Dec '99 33 34 Added POSIX locking support. Jeremy Allison (jeremy@valinux.com), Apr. 2000. 35*/ 36 37#include "includes.h" 38uint16 global_smbpid; 39 40/* the locking database handle */ 41static TDB_CONTEXT *tdb; 42 43struct locking_data { 44 union { 45 int num_share_mode_entries; 46 share_mode_entry dummy; /* Needed for alignment. */ 47 } u; 48 /* the following two entries are implicit 49 share_mode_entry modes[num_share_mode_entries]; 50 char file_name[]; 51 */ 52}; 53 54/**************************************************************************** 55 Debugging aid :-). 56****************************************************************************/ 57 58static const char *lock_type_name(enum brl_type lock_type) 59{ 60 return (lock_type == READ_LOCK) ? "READ" : "WRITE"; 61} 62 63/**************************************************************************** 64 Utility function called to see if a file region is locked. 65****************************************************************************/ 66 67BOOL is_locked(files_struct *fsp,connection_struct *conn, 68 SMB_BIG_UINT count,SMB_BIG_UINT offset, 69 enum brl_type lock_type) 70{ 71 int snum = SNUM(conn); 72 int strict_locking = lp_strict_locking(snum); 73 BOOL ret; 74 75 if (count == 0) 76 return(False); 77 78 if (!lp_locking(snum) || !strict_locking) 79 return(False); 80 81 if (strict_locking == Auto) { 82 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && (lock_type == READ_LOCK || lock_type == WRITE_LOCK)) { 83 DEBUG(10,("is_locked: optimisation - exclusive oplock on file %s\n", fsp->fsp_name )); 84 ret = 0; 85 } else if (LEVEL_II_OPLOCK_TYPE(fsp->oplock_type) && (lock_type == READ_LOCK)) { 86 DEBUG(10,("is_locked: optimisation - level II oplock on file %s\n", fsp->fsp_name )); 87 ret = 0; 88 } else { 89 ret = !brl_locktest(fsp->dev, fsp->inode, fsp->fnum, 90 global_smbpid, sys_getpid(), conn->cnum, 91 offset, count, lock_type); 92 } 93 } else { 94 ret = !brl_locktest(fsp->dev, fsp->inode, fsp->fnum, 95 global_smbpid, sys_getpid(), conn->cnum, 96 offset, count, lock_type); 97 } 98 99 DEBUG(10,("is_locked: brl start=%.0f len=%.0f %s for file %s\n", 100 (double)offset, (double)count, ret ? "locked" : "unlocked", 101 fsp->fsp_name )); 102 103 /* 104 * There is no lock held by an SMB daemon, check to 105 * see if there is a POSIX lock from a UNIX or NFS process. 106 */ 107 108 if(!ret && lp_posix_locking(snum)) { 109 ret = is_posix_locked(fsp, offset, count, lock_type); 110 111 DEBUG(10,("is_locked: posix start=%.0f len=%.0f %s for file %s\n", 112 (double)offset, (double)count, ret ? "locked" : "unlocked", 113 fsp->fsp_name )); 114 } 115 116 return ret; 117} 118 119/**************************************************************************** 120 Utility function called by locking requests. 121****************************************************************************/ 122 123static NTSTATUS do_lock(files_struct *fsp,connection_struct *conn, uint16 lock_pid, 124 SMB_BIG_UINT count,SMB_BIG_UINT offset,enum brl_type lock_type, BOOL *my_lock_ctx) 125{ 126 NTSTATUS status = NT_STATUS_LOCK_NOT_GRANTED; 127 128 if (!lp_locking(SNUM(conn))) 129 return NT_STATUS_OK; 130 131 /* NOTE! 0 byte long ranges ARE allowed and should be stored */ 132 133 DEBUG(10,("do_lock: lock type %s start=%.0f len=%.0f requested for file %s\n", 134 lock_type_name(lock_type), (double)offset, (double)count, fsp->fsp_name )); 135 136 if (OPEN_FSP(fsp) && fsp->can_lock && (fsp->conn == conn)) { 137 status = brl_lock(fsp->dev, fsp->inode, fsp->fnum, 138 lock_pid, sys_getpid(), conn->cnum, 139 offset, count, 140 lock_type, my_lock_ctx); 141 142 if (NT_STATUS_IS_OK(status) && lp_posix_locking(SNUM(conn))) { 143 144 /* 145 * Try and get a POSIX lock on this range. 146 * Note that this is ok if it is a read lock 147 * overlapping on a different fd. JRA. 148 */ 149 150 if (!set_posix_lock(fsp, offset, count, lock_type)) { 151 if (errno == EACCES || errno == EAGAIN) 152 status = NT_STATUS_FILE_LOCK_CONFLICT; 153 else 154 status = map_nt_error_from_unix(errno); 155 156 /* 157 * We failed to map - we must now remove the brl 158 * lock entry. 159 */ 160 (void)brl_unlock(fsp->dev, fsp->inode, fsp->fnum, 161 lock_pid, sys_getpid(), conn->cnum, 162 offset, count, False, 163 NULL, NULL); 164 } 165 } 166 } 167 168 return status; 169} 170 171/**************************************************************************** 172 Utility function called by locking requests. This is *DISGUSTING*. It also 173 appears to be "What Windows Does" (tm). Andrew, ever wonder why Windows 2000 174 is so slow on the locking tests...... ? This is the reason. Much though I hate 175 it, we need this. JRA. 176****************************************************************************/ 177 178NTSTATUS do_lock_spin(files_struct *fsp,connection_struct *conn, uint16 lock_pid, 179 SMB_BIG_UINT count,SMB_BIG_UINT offset,enum brl_type lock_type, BOOL *my_lock_ctx) 180{ 181 int j, maxj = lp_lock_spin_count(); 182 int sleeptime = lp_lock_sleep_time(); 183 NTSTATUS status, ret; 184 185 if (maxj <= 0) 186 maxj = 1; 187 188 ret = NT_STATUS_OK; /* to keep dumb compilers happy */ 189 190 for (j = 0; j < maxj; j++) { 191 status = do_lock(fsp, conn, lock_pid, count, offset, lock_type, my_lock_ctx); 192 if (!NT_STATUS_EQUAL(status, NT_STATUS_LOCK_NOT_GRANTED) && 193 !NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) { 194 return status; 195 } 196 /* if we do fail then return the first error code we got */ 197 if (j == 0) { 198 ret = status; 199 /* Don't spin if we blocked ourselves. */ 200 if (*my_lock_ctx) 201 return ret; 202 } 203 if (sleeptime) 204 sys_usleep(sleeptime); 205 } 206 return ret; 207} 208 209/* Struct passed to brl_unlock. */ 210struct posix_unlock_data_struct { 211 files_struct *fsp; 212 SMB_BIG_UINT offset; 213 SMB_BIG_UINT count; 214}; 215 216/**************************************************************************** 217 Function passed to brl_unlock to allow POSIX unlock to be done first. 218****************************************************************************/ 219 220static void posix_unlock(void *pre_data) 221{ 222 struct posix_unlock_data_struct *pdata = (struct posix_unlock_data_struct *)pre_data; 223 224 if (lp_posix_locking(SNUM(pdata->fsp->conn))) 225 release_posix_lock(pdata->fsp, pdata->offset, pdata->count); 226} 227 228/**************************************************************************** 229 Utility function called by unlocking requests. 230****************************************************************************/ 231 232NTSTATUS do_unlock(files_struct *fsp,connection_struct *conn, uint16 lock_pid, 233 SMB_BIG_UINT count,SMB_BIG_UINT offset) 234{ 235 BOOL ok = False; 236 struct posix_unlock_data_struct posix_data; 237 238 if (!lp_locking(SNUM(conn))) 239 return NT_STATUS_OK; 240 241 if (!OPEN_FSP(fsp) || !fsp->can_lock || (fsp->conn != conn)) { 242 return NT_STATUS_INVALID_HANDLE; 243 } 244 245 DEBUG(10,("do_unlock: unlock start=%.0f len=%.0f requested for file %s\n", 246 (double)offset, (double)count, fsp->fsp_name )); 247 248 /* 249 * Remove the existing lock record from the tdb lockdb 250 * before looking at POSIX locks. If this record doesn't 251 * match then don't bother looking to remove POSIX locks. 252 */ 253 254 posix_data.fsp = fsp; 255 posix_data.offset = offset; 256 posix_data.count = count; 257 258 ok = brl_unlock(fsp->dev, fsp->inode, fsp->fnum, 259 lock_pid, sys_getpid(), conn->cnum, offset, count, 260 False, posix_unlock, (void *)&posix_data); 261 262 if (!ok) { 263 DEBUG(10,("do_unlock: returning ERRlock.\n" )); 264 return NT_STATUS_RANGE_NOT_LOCKED; 265 } 266 return NT_STATUS_OK; 267} 268 269/**************************************************************************** 270 Remove any locks on this fd. Called from file_close(). 271****************************************************************************/ 272 273void locking_close_file(files_struct *fsp) 274{ 275 pid_t pid = sys_getpid(); 276 277 if (!lp_locking(SNUM(fsp->conn))) 278 return; 279 280 /* 281 * Just release all the brl locks, no need to release individually. 282 */ 283 284 brl_close(fsp->dev, fsp->inode, pid, fsp->conn->cnum, fsp->fnum); 285 286 if(lp_posix_locking(SNUM(fsp->conn))) { 287 288 /* 289 * Release all the POSIX locks. 290 */ 291 posix_locking_close_file(fsp); 292 293 } 294} 295 296/**************************************************************************** 297 Initialise the locking functions. 298****************************************************************************/ 299 300static int open_read_only; 301 302BOOL locking_init(int read_only) 303{ 304 brl_init(read_only); 305 306 if (tdb) 307 return True; 308 309 tdb = tdb_open_log(lock_path("locking.tdb"), 310 0, TDB_DEFAULT|(read_only?0x0:TDB_CLEAR_IF_FIRST), 311 read_only?O_RDONLY:O_RDWR|O_CREAT, 312 0644); 313 314 if (!tdb) { 315 DEBUG(0,("ERROR: Failed to initialise locking database\n")); 316 return False; 317 } 318 319 if (!posix_locking_init(read_only)) 320 return False; 321 322 open_read_only = read_only; 323 324 return True; 325} 326 327/******************************************************************* 328 Deinitialize the share_mode management. 329******************************************************************/ 330 331BOOL locking_end(void) 332{ 333 334 brl_shutdown(open_read_only); 335 if (tdb) { 336 337 if (tdb_close(tdb) != 0) 338 return False; 339 } 340 341 return True; 342} 343 344/******************************************************************* 345 Form a static locking key for a dev/inode pair. 346******************************************************************/ 347 348static TDB_DATA locking_key(SMB_DEV_T dev, SMB_INO_T inode) 349{ 350 static struct locking_key key; 351 TDB_DATA kbuf; 352 353 memset(&key, '\0', sizeof(key)); 354 key.dev = dev; 355 key.inode = inode; 356 kbuf.dptr = (char *)&key; 357 kbuf.dsize = sizeof(key); 358 return kbuf; 359} 360 361static TDB_DATA locking_key_fsp(files_struct *fsp) 362{ 363 return locking_key(fsp->dev, fsp->inode); 364} 365 366/******************************************************************* 367 Lock a hash bucket entry. 368******************************************************************/ 369 370BOOL lock_share_entry(connection_struct *conn, 371 SMB_DEV_T dev, SMB_INO_T inode) 372{ 373 return tdb_chainlock(tdb, locking_key(dev, inode)) == 0; 374} 375 376/******************************************************************* 377 Unlock a hash bucket entry. 378******************************************************************/ 379 380void unlock_share_entry(connection_struct *conn, 381 SMB_DEV_T dev, SMB_INO_T inode) 382{ 383 tdb_chainunlock(tdb, locking_key(dev, inode)); 384} 385 386/******************************************************************* 387 Lock a hash bucket entry. use a fsp for convenience 388******************************************************************/ 389 390BOOL lock_share_entry_fsp(files_struct *fsp) 391{ 392 return tdb_chainlock(tdb, locking_key(fsp->dev, fsp->inode)) == 0; 393} 394 395/******************************************************************* 396 Unlock a hash bucket entry. 397******************************************************************/ 398 399void unlock_share_entry_fsp(files_struct *fsp) 400{ 401 tdb_chainunlock(tdb, locking_key(fsp->dev, fsp->inode)); 402} 403 404/******************************************************************* 405 Print out a share mode. 406********************************************************************/ 407 408char *share_mode_str(int num, share_mode_entry *e) 409{ 410 static pstring share_str; 411 412 slprintf(share_str, sizeof(share_str)-1, "share_mode_entry[%d]: \ 413pid = %lu, share_mode = 0x%x, desired_access = 0x%x, port = 0x%x, type= 0x%x, file_id = %lu, dev = 0x%x, inode = %.0f", 414 num, (unsigned long)e->pid, e->share_mode, (unsigned int)e->desired_access, e->op_port, e->op_type, e->share_file_id, 415 (unsigned int)e->dev, (double)e->inode ); 416 417 return share_str; 418} 419 420/******************************************************************* 421 Print out a share mode table. 422********************************************************************/ 423 424static void print_share_mode_table(struct locking_data *data) 425{ 426 int num_share_modes = data->u.num_share_mode_entries; 427 share_mode_entry *shares = (share_mode_entry *)(data + 1); 428 int i; 429 430 for (i = 0; i < num_share_modes; i++) { 431 share_mode_entry *entry_p = &shares[i]; 432 DEBUG(10,("print_share_mode_table: %s\n", share_mode_str(i, entry_p) )); 433 } 434} 435 436/******************************************************************* 437 Get all share mode entries for a dev/inode pair. 438********************************************************************/ 439 440int get_share_modes(connection_struct *conn, 441 SMB_DEV_T dev, SMB_INO_T inode, 442 share_mode_entry **pp_shares) 443{ 444 TDB_DATA dbuf; 445 struct locking_data *data; 446 int num_share_modes; 447 share_mode_entry *shares = NULL; 448 TDB_DATA key = locking_key(dev, inode); 449 *pp_shares = NULL; 450 451 dbuf = tdb_fetch(tdb, key); 452 if (!dbuf.dptr) 453 return 0; 454 455 data = (struct locking_data *)dbuf.dptr; 456 num_share_modes = data->u.num_share_mode_entries; 457 if(num_share_modes) { 458 pstring fname; 459 int i; 460 int del_count = 0; 461 462 shares = (share_mode_entry *)memdup(dbuf.dptr + sizeof(*data), 463 num_share_modes * sizeof(share_mode_entry)); 464 465 if (!shares) { 466 SAFE_FREE(dbuf.dptr); 467 return 0; 468 } 469 470 /* Save off the associated filename. */ 471 pstrcpy(fname, dbuf.dptr + sizeof(*data) + num_share_modes * sizeof(share_mode_entry)); 472 473 /* 474 * Ensure that each entry has a real process attached. 475 */ 476 477 for (i = 0; i < num_share_modes; ) { 478 share_mode_entry *entry_p = &shares[i]; 479 if (process_exists(entry_p->pid)) { 480 DEBUG(10,("get_share_modes: %s\n", share_mode_str(i, entry_p) )); 481 i++; 482 } else { 483 DEBUG(10,("get_share_modes: deleted %s\n", share_mode_str(i, entry_p) )); 484 if (num_share_modes - i - 1 > 0) { 485 memcpy( &shares[i], &shares[i+1], 486 sizeof(share_mode_entry) * (num_share_modes - i - 1)); 487 } 488 num_share_modes--; 489 del_count++; 490 } 491 } 492 493 /* Did we delete any ? If so, re-store in tdb. */ 494 if (del_count) { 495 data->u.num_share_mode_entries = num_share_modes; 496 497 if (num_share_modes) { 498 memcpy(dbuf.dptr + sizeof(*data), shares, 499 num_share_modes * sizeof(share_mode_entry)); 500 /* Append the filename. */ 501 pstrcpy(dbuf.dptr + sizeof(*data) + num_share_modes * sizeof(share_mode_entry), fname); 502 } 503 504 /* The record has shrunk a bit */ 505 dbuf.dsize -= del_count * sizeof(share_mode_entry); 506 507 if (data->u.num_share_mode_entries == 0) { 508 if (tdb_delete(tdb, key) == -1) { 509 SAFE_FREE(shares); 510 SAFE_FREE(dbuf.dptr); 511 return 0; 512 } 513 } else { 514 if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1) { 515 SAFE_FREE(shares); 516 SAFE_FREE(dbuf.dptr); 517 return 0; 518 } 519 } 520 } 521 } 522 523 SAFE_FREE(dbuf.dptr); 524 *pp_shares = shares; 525 return num_share_modes; 526} 527 528/******************************************************************* 529 Fill a share mode entry. 530********************************************************************/ 531 532static void fill_share_mode(char *p, files_struct *fsp, uint16 port, uint16 op_type) 533{ 534 share_mode_entry *e = (share_mode_entry *)p; 535 void *x = &e->time; /* Needed to force alignment. p may not be aligned.... */ 536 537 memset(e, '\0', sizeof(share_mode_entry)); 538 e->pid = sys_getpid(); 539 e->share_mode = fsp->share_mode; 540 e->desired_access = fsp->desired_access; 541 e->op_port = port; 542 e->op_type = op_type; 543 memcpy(x, &fsp->open_time, sizeof(struct timeval)); 544 e->share_file_id = fsp->file_id; 545 e->dev = fsp->dev; 546 e->inode = fsp->inode; 547} 548 549/******************************************************************* 550 Check if two share mode entries are identical, ignoring oplock 551 and port info and desired_access. 552********************************************************************/ 553 554BOOL share_modes_identical( share_mode_entry *e1, share_mode_entry *e2) 555{ 556#if 1 /* JRA PARANOIA TEST - REMOVE LATER */ 557 if (e1->pid == e2->pid && 558 e1->share_file_id == e2->share_file_id && 559 e1->dev == e2->dev && 560 e1->inode == e2->inode && 561 (e1->share_mode & ~DELETE_ON_CLOSE_FLAG) != (e2->share_mode & ~DELETE_ON_CLOSE_FLAG)) { 562 DEBUG(0,("PANIC: share_modes_identical: share_mode missmatch (e1 = %u, e2 = %u). Logic error.\n", 563 (unsigned int)(e1->share_mode & ~DELETE_ON_CLOSE_FLAG), 564 (unsigned int)(e2->share_mode & ~DELETE_ON_CLOSE_FLAG) )); 565 smb_panic("PANIC: share_modes_identical logic error.\n"); 566 } 567#endif 568 569 return (e1->pid == e2->pid && 570 (e1->share_mode & ~DELETE_ON_CLOSE_FLAG) == (e2->share_mode & ~DELETE_ON_CLOSE_FLAG) && 571 e1->dev == e2->dev && 572 e1->inode == e2->inode && 573 e1->share_file_id == e2->share_file_id ); 574} 575 576/******************************************************************* 577 Delete a specific share mode. Return the number 578 of entries left, and a memdup'ed copy of the entry deleted (if required). 579 Ignore if no entry deleted. 580********************************************************************/ 581 582ssize_t del_share_entry( SMB_DEV_T dev, SMB_INO_T inode, 583 share_mode_entry *entry, share_mode_entry **ppse) 584{ 585 TDB_DATA dbuf; 586 struct locking_data *data; 587 int i, del_count=0; 588 share_mode_entry *shares; 589 ssize_t count = 0; 590 TDB_DATA key = locking_key(dev, inode); 591 592 if (ppse) 593 *ppse = NULL; 594 595 /* read in the existing share modes */ 596 dbuf = tdb_fetch(tdb, key); 597 if (!dbuf.dptr) 598 return -1; 599 600 data = (struct locking_data *)dbuf.dptr; 601 shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data)); 602 603 /* 604 * Find any with this pid and delete it 605 * by overwriting with the rest of the data 606 * from the record. 607 */ 608 609 DEBUG(10,("del_share_entry: num_share_modes = %d\n", data->u.num_share_mode_entries )); 610 611 for (i=0;i<data->u.num_share_mode_entries;) { 612 if (share_modes_identical(&shares[i], entry)) { 613 DEBUG(10,("del_share_entry: deleted %s\n", 614 share_mode_str(i, &shares[i]) )); 615 if (ppse) 616 *ppse = memdup(&shares[i], sizeof(*shares)); 617 data->u.num_share_mode_entries--; 618 if ((dbuf.dsize - (sizeof(*data) + (i+1)*sizeof(*shares))) > 0) { 619 memmove(&shares[i], &shares[i+1], 620 dbuf.dsize - (sizeof(*data) + (i+1)*sizeof(*shares))); 621 } 622 del_count++; 623 624 DEBUG(10,("del_share_entry: deleting entry %d\n", i )); 625 626 } else { 627 i++; 628 } 629 } 630 631 if (del_count) { 632 /* the record may have shrunk a bit */ 633 dbuf.dsize -= del_count * sizeof(*shares); 634 635 count = (ssize_t)data->u.num_share_mode_entries; 636 637 /* store it back in the database */ 638 if (data->u.num_share_mode_entries == 0) { 639 if (tdb_delete(tdb, key) == -1) 640 count = -1; 641 } else { 642 if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1) 643 count = -1; 644 } 645 } 646 DEBUG(10,("del_share_entry: Remaining table.\n")); 647 print_share_mode_table((struct locking_data *)dbuf.dptr); 648 SAFE_FREE(dbuf.dptr); 649 return count; 650} 651 652/******************************************************************* 653 Del the share mode of a file for this process. Return the number 654 of entries left, and a memdup'ed copy of the entry deleted. 655********************************************************************/ 656 657ssize_t del_share_mode(files_struct *fsp, share_mode_entry **ppse) 658{ 659 share_mode_entry entry; 660 661 /* 662 * Fake up a share_mode_entry for comparisons. 663 */ 664 665 fill_share_mode((char *)&entry, fsp, 0, 0); 666 return del_share_entry(fsp->dev, fsp->inode, &entry, ppse); 667} 668 669/******************************************************************* 670 Set the share mode of a file. Return False on fail, True on success. 671********************************************************************/ 672 673BOOL set_share_mode(files_struct *fsp, uint16 port, uint16 op_type) 674{ 675 TDB_DATA dbuf; 676 struct locking_data *data; 677 char *p=NULL; 678 int size; 679 TDB_DATA key = locking_key_fsp(fsp); 680 BOOL ret = True; 681 682 /* read in the existing share modes if any */ 683 dbuf = tdb_fetch(tdb, key); 684 if (!dbuf.dptr) { 685 size_t offset; 686 /* we'll need to create a new record */ 687 pstring fname; 688 689 pstrcpy(fname, fsp->conn->connectpath); 690 pstrcat(fname, "/"); 691 pstrcat(fname, fsp->fsp_name); 692 693 size = sizeof(*data) + sizeof(share_mode_entry) + strlen(fname) + 1; 694 p = (char *)SMB_MALLOC(size); 695 if (!p) 696 return False; 697 data = (struct locking_data *)p; 698 data->u.num_share_mode_entries = 1; 699 700 DEBUG(10,("set_share_mode: creating entry for file %s. num_share_modes = 1\n", 701 fsp->fsp_name )); 702 703 offset = sizeof(*data) + sizeof(share_mode_entry); 704 safe_strcpy(p + offset, fname, size - offset - 1); 705 fill_share_mode(p + sizeof(*data), fsp, port, op_type); 706 dbuf.dptr = p; 707 dbuf.dsize = size; 708 if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1) 709 ret = False; 710 711 print_share_mode_table((struct locking_data *)p); 712 713 SAFE_FREE(p); 714 return ret; 715 } 716 717 /* we're adding to an existing entry - this is a bit fiddly */ 718 data = (struct locking_data *)dbuf.dptr; 719 720 data->u.num_share_mode_entries++; 721 722 DEBUG(10,("set_share_mode: adding entry for file %s. new num_share_modes = %d\n", 723 fsp->fsp_name, data->u.num_share_mode_entries )); 724 725 size = dbuf.dsize + sizeof(share_mode_entry); 726 p = SMB_MALLOC(size); 727 if (!p) { 728 SAFE_FREE(dbuf.dptr); 729 return False; 730 } 731 memcpy(p, dbuf.dptr, sizeof(*data)); 732 fill_share_mode(p + sizeof(*data), fsp, port, op_type); 733 memcpy(p + sizeof(*data) + sizeof(share_mode_entry), dbuf.dptr + sizeof(*data), 734 dbuf.dsize - sizeof(*data)); 735 SAFE_FREE(dbuf.dptr); 736 dbuf.dptr = p; 737 dbuf.dsize = size; 738 if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1) 739 ret = False; 740 print_share_mode_table((struct locking_data *)p); 741 SAFE_FREE(p); 742 return ret; 743} 744 745/******************************************************************* 746 A generic in-place modification call for share mode entries. 747********************************************************************/ 748 749static BOOL mod_share_mode( SMB_DEV_T dev, SMB_INO_T inode, share_mode_entry *entry, 750 void (*mod_fn)(share_mode_entry *, SMB_DEV_T, SMB_INO_T, void *), 751 void *param) 752{ 753 TDB_DATA dbuf; 754 struct locking_data *data; 755 int i; 756 share_mode_entry *shares; 757 BOOL need_store=False; 758 BOOL ret = True; 759 TDB_DATA key = locking_key(dev, inode); 760 761 /* read in the existing share modes */ 762 dbuf = tdb_fetch(tdb, key); 763 if (!dbuf.dptr) 764 return False; 765 766 data = (struct locking_data *)dbuf.dptr; 767 shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data)); 768 769 /* find any with our pid and call the supplied function */ 770 for (i=0;i<data->u.num_share_mode_entries;i++) { 771 if (share_modes_identical(entry, &shares[i])) { 772 mod_fn(&shares[i], dev, inode, param); 773 need_store=True; 774 } 775 } 776 777 /* if the mod fn was called then store it back */ 778 if (need_store) { 779 if (data->u.num_share_mode_entries == 0) { 780 if (tdb_delete(tdb, key) == -1) 781 ret = False; 782 } else { 783 if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1) 784 ret = False; 785 } 786 } 787 788 SAFE_FREE(dbuf.dptr); 789 return ret; 790} 791 792/******************************************************************* 793 Static function that actually does the work for the generic function 794 below. 795********************************************************************/ 796 797static void remove_share_oplock_fn(share_mode_entry *entry, SMB_DEV_T dev, SMB_INO_T inode, 798 void *param) 799{ 800 DEBUG(10,("remove_share_oplock_fn: removing oplock info for entry dev=%x ino=%.0f\n", 801 (unsigned int)dev, (double)inode )); 802 /* Delete the oplock info. */ 803 entry->op_port = 0; 804 entry->op_type = NO_OPLOCK; 805} 806 807/******************************************************************* 808 Remove an oplock port and mode entry from a share mode. 809********************************************************************/ 810 811BOOL remove_share_oplock(files_struct *fsp) 812{ 813 share_mode_entry entry; 814 /* 815 * Fake up an entry for comparisons... 816 */ 817 fill_share_mode((char *)&entry, fsp, 0, 0); 818 return mod_share_mode(fsp->dev, fsp->inode, &entry, remove_share_oplock_fn, NULL); 819} 820 821/******************************************************************* 822 Static function that actually does the work for the generic function 823 below. 824********************************************************************/ 825 826static void downgrade_share_oplock_fn(share_mode_entry *entry, SMB_DEV_T dev, SMB_INO_T inode, 827 void *param) 828{ 829 DEBUG(10,("downgrade_share_oplock_fn: downgrading oplock info for entry dev=%x ino=%.0f\n", 830 (unsigned int)dev, (double)inode )); 831 entry->op_type = LEVEL_II_OPLOCK; 832} 833 834/******************************************************************* 835 Downgrade a oplock type from exclusive to level II. 836********************************************************************/ 837 838BOOL downgrade_share_oplock(files_struct *fsp) 839{ 840 share_mode_entry entry; 841 /* 842 * Fake up an entry for comparisons... 843 */ 844 fill_share_mode((char *)&entry, fsp, 0, 0); 845 return mod_share_mode(fsp->dev, fsp->inode, &entry, downgrade_share_oplock_fn, NULL); 846} 847 848/******************************************************************* 849 Get/Set the delete on close flag in a set of share modes. 850 Return False on fail, True on success. 851********************************************************************/ 852 853BOOL modify_delete_flag( SMB_DEV_T dev, SMB_INO_T inode, BOOL delete_on_close) 854{ 855 TDB_DATA dbuf; 856 struct locking_data *data; 857 int i; 858 share_mode_entry *shares; 859 TDB_DATA key = locking_key(dev, inode); 860 861 /* read in the existing share modes */ 862 dbuf = tdb_fetch(tdb, key); 863 if (!dbuf.dptr) 864 return False; 865 866 data = (struct locking_data *)dbuf.dptr; 867 shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data)); 868 869 /* Set/Unset the delete on close element. */ 870 for (i=0;i<data->u.num_share_mode_entries;i++,shares++) { 871 shares->share_mode = (delete_on_close ? 872 (shares->share_mode | DELETE_ON_CLOSE_FLAG) : 873 (shares->share_mode & ~DELETE_ON_CLOSE_FLAG) ); 874 } 875 876 /* store it back */ 877 if (data->u.num_share_mode_entries) { 878 if (tdb_store(tdb, key, dbuf, TDB_REPLACE)==-1) { 879 SAFE_FREE(dbuf.dptr); 880 return False; 881 } 882 } 883 884 SAFE_FREE(dbuf.dptr); 885 return True; 886} 887 888/******************************************************************* 889 Print out a deferred open entry. 890********************************************************************/ 891 892char *deferred_open_str(int num, deferred_open_entry *e) 893{ 894 static pstring de_str; 895 896 slprintf(de_str, sizeof(de_str)-1, "deferred_open_entry[%d]: \ 897pid = %lu, mid = %u, dev = 0x%x, inode = %.0f, port = %u, time = [%u.%06u]", 898 num, (unsigned long)e->pid, (unsigned int)e->mid, (unsigned int)e->dev, (double)e->inode, 899 (unsigned int)e->port, 900 (unsigned int)e->time.tv_sec, (unsigned int)e->time.tv_usec ); 901 902 return de_str; 903} 904 905/* Internal data structures for deferred opens... */ 906 907struct de_locking_key { 908 char name[4]; 909 SMB_DEV_T dev; 910 SMB_INO_T inode; 911}; 912 913struct deferred_open_data { 914 union { 915 int num_deferred_open_entries; 916 deferred_open_entry dummy; /* Needed for alignment. */ 917 } u; 918 /* the following two entries are implicit 919 deferred_open_entry de_entries[num_deferred_open_entries]; 920 char file_name[]; 921 */ 922}; 923 924/******************************************************************* 925 Print out a deferred open table. 926********************************************************************/ 927 928static void print_deferred_open_table(struct deferred_open_data *data) 929{ 930 int num_de_entries = data->u.num_deferred_open_entries; 931 deferred_open_entry *de_entries = (deferred_open_entry *)(data + 1); 932 int i; 933 934 for (i = 0; i < num_de_entries; i++) { 935 deferred_open_entry *entry_p = &de_entries[i]; 936 DEBUG(10,("print_deferred_open_table: %s\n", deferred_open_str(i, entry_p) )); 937 } 938} 939 940 941/******************************************************************* 942 Form a static deferred open locking key for a dev/inode pair. 943******************************************************************/ 944 945static TDB_DATA deferred_open_locking_key(SMB_DEV_T dev, SMB_INO_T inode) 946{ 947 static struct de_locking_key key; 948 TDB_DATA kbuf; 949 950 memset(&key, '\0', sizeof(key)); 951 memcpy(&key.name[0], "DOE", 4); 952 key.dev = dev; 953 key.inode = inode; 954 kbuf.dptr = (char *)&key; 955 kbuf.dsize = sizeof(key); 956 return kbuf; 957} 958 959/******************************************************************* 960 Get all deferred open entries for a dev/inode pair. 961********************************************************************/ 962 963int get_deferred_opens(connection_struct *conn, 964 SMB_DEV_T dev, SMB_INO_T inode, 965 deferred_open_entry **pp_de_entries) 966{ 967 TDB_DATA dbuf; 968 struct deferred_open_data *data; 969 int num_de_entries; 970 deferred_open_entry *de_entries = NULL; 971 TDB_DATA key = deferred_open_locking_key(dev, inode); 972 973 *pp_de_entries = NULL; 974 975 dbuf = tdb_fetch(tdb, key); 976 if (!dbuf.dptr) 977 return 0; 978 979 data = (struct deferred_open_data *)dbuf.dptr; 980 num_de_entries = data->u.num_deferred_open_entries; 981 if(num_de_entries) { 982 pstring fname; 983 int i; 984 int del_count = 0; 985 986 de_entries = (deferred_open_entry *)memdup(dbuf.dptr + sizeof(*data), 987 num_de_entries * sizeof(deferred_open_entry)); 988 989 if (!de_entries) { 990 SAFE_FREE(dbuf.dptr); 991 return 0; 992 } 993 994 /* Save off the associated filename. */ 995 pstrcpy(fname, dbuf.dptr + sizeof(*data) + num_de_entries * sizeof(deferred_open_entry)); 996 997 /* 998 * Ensure that each entry has a real process attached. 999 */ 1000 1001 for (i = 0; i < num_de_entries; ) { 1002 deferred_open_entry *entry_p = &de_entries[i]; 1003 if (process_exists(entry_p->pid)) { 1004 DEBUG(10,("get_deferred_opens: %s\n", deferred_open_str(i, entry_p) )); 1005 i++; 1006 } else { 1007 DEBUG(10,("get_deferred_opens: deleted %s\n", deferred_open_str(i, entry_p) )); 1008 if (num_de_entries - i - 1 > 0) { 1009 memcpy( &de_entries[i], &de_entries[i+1], 1010 sizeof(deferred_open_entry) * (num_de_entries - i - 1)); 1011 } 1012 num_de_entries--; 1013 del_count++; 1014 } 1015 } 1016 1017 /* Did we delete any ? If so, re-store in tdb. */ 1018 if (del_count) { 1019 data->u.num_deferred_open_entries = num_de_entries; 1020 1021 if (num_de_entries) { 1022 memcpy(dbuf.dptr + sizeof(*data), de_entries, 1023 num_de_entries * sizeof(deferred_open_entry)); 1024 /* Append the filename. */ 1025 pstrcpy(dbuf.dptr + sizeof(*data) + num_de_entries * sizeof(deferred_open_entry), fname); 1026 } 1027 1028 /* The record has shrunk a bit */ 1029 dbuf.dsize -= del_count * sizeof(deferred_open_entry); 1030 1031 if (data->u.num_deferred_open_entries == 0) { 1032 if (tdb_delete(tdb, key) == -1) { 1033 SAFE_FREE(de_entries); 1034 SAFE_FREE(dbuf.dptr); 1035 return 0; 1036 } 1037 } else { 1038 if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1) { 1039 SAFE_FREE(de_entries); 1040 SAFE_FREE(dbuf.dptr); 1041 return 0; 1042 } 1043 } 1044 } 1045 } 1046 1047 SAFE_FREE(dbuf.dptr); 1048 *pp_de_entries = de_entries; 1049 return num_de_entries; 1050} 1051 1052/******************************************************************* 1053 Check if two deferred open entries are identical. 1054********************************************************************/ 1055 1056static BOOL deferred_open_entries_identical( deferred_open_entry *e1, deferred_open_entry *e2) 1057{ 1058 return (e1->pid == e2->pid && 1059 e1->mid == e2->mid && 1060 e1->port == e2->port && 1061 e1->dev == e2->dev && 1062 e1->inode == e2->inode && 1063 e1->time.tv_sec == e2->time.tv_sec && 1064 e1->time.tv_usec == e2->time.tv_usec); 1065} 1066 1067/******************************************************************* 1068 Delete a specific deferred open entry. 1069 Ignore if no entry deleted. 1070********************************************************************/ 1071 1072BOOL delete_deferred_open_entry(deferred_open_entry *entry) 1073{ 1074 TDB_DATA dbuf; 1075 struct deferred_open_data *data; 1076 int i, del_count=0; 1077 deferred_open_entry *de_entries; 1078 BOOL ret = True; 1079 TDB_DATA key = deferred_open_locking_key(entry->dev, entry->inode); 1080 1081 /* read in the existing share modes */ 1082 dbuf = tdb_fetch(tdb, key); 1083 if (!dbuf.dptr) 1084 return -1; 1085 1086 data = (struct deferred_open_data *)dbuf.dptr; 1087 de_entries = (deferred_open_entry *)(dbuf.dptr + sizeof(*data)); 1088 1089 /* 1090 * Find any with this pid and delete it 1091 * by overwriting with the rest of the data 1092 * from the record. 1093 */ 1094 1095 DEBUG(10,("delete_deferred_open_entry: num_deferred_open_entries = %d\n", 1096 data->u.num_deferred_open_entries )); 1097 1098 for (i=0;i<data->u.num_deferred_open_entries;) { 1099 if (deferred_open_entries_identical(&de_entries[i], entry)) { 1100 DEBUG(10,("delete_deferred_open_entry: deleted %s\n", 1101 deferred_open_str(i, &de_entries[i]) )); 1102 1103 data->u.num_deferred_open_entries--; 1104 if ((dbuf.dsize - (sizeof(*data) + (i+1)*sizeof(*de_entries))) > 0) { 1105 memmove(&de_entries[i], &de_entries[i+1], 1106 dbuf.dsize - (sizeof(*data) + (i+1)*sizeof(*de_entries))); 1107 } 1108 del_count++; 1109 1110 DEBUG(10,("delete_deferred_open_entry: deleting entry %d\n", i )); 1111 1112 } else { 1113 i++; 1114 } 1115 } 1116 1117 SMB_ASSERT(del_count == 0 || del_count == 1); 1118 1119 if (del_count) { 1120 /* the record may have shrunk a bit */ 1121 dbuf.dsize -= del_count * sizeof(*de_entries); 1122 1123 /* store it back in the database */ 1124 if (data->u.num_deferred_open_entries == 0) { 1125 if (tdb_delete(tdb, key) == -1) 1126 ret = False; 1127 } else { 1128 if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1) 1129 ret = False; 1130 } 1131 } 1132 DEBUG(10,("delete_deferred_open_entry: Remaining table.\n")); 1133 print_deferred_open_table((struct deferred_open_data*)dbuf.dptr); 1134 SAFE_FREE(dbuf.dptr); 1135 return ret; 1136} 1137 1138/******************************************************************* 1139 Fill a deferred open entry. 1140********************************************************************/ 1141 1142static void fill_deferred_open(char *p, uint16 mid, struct timeval *ptv, SMB_DEV_T dev, SMB_INO_T inode, uint16 port) 1143{ 1144 deferred_open_entry *e = (deferred_open_entry *)p; 1145 void *x = &e->time; /* Needed to force alignment. p may not be aligned.... */ 1146 1147 memset(e, '\0', sizeof(deferred_open_entry)); 1148 e->mid = mid; 1149 e->pid = sys_getpid(); 1150 memcpy(x, ptv, sizeof(struct timeval)); 1151 e->dev = dev; 1152 e->inode = inode; 1153 e->port = port; 1154} 1155 1156/******************************************************************* 1157 Add a deferred open record. Return False on fail, True on success. 1158********************************************************************/ 1159 1160BOOL add_deferred_open(uint16 mid, struct timeval *ptv, SMB_DEV_T dev, SMB_INO_T inode, uint16 port, const char *fname) 1161{ 1162 TDB_DATA dbuf; 1163 struct deferred_open_data *data; 1164 char *p=NULL; 1165 int size; 1166 TDB_DATA key = deferred_open_locking_key(dev, inode); 1167 BOOL ret = True; 1168 1169 /* read in the existing deferred open records if any */ 1170 dbuf = tdb_fetch(tdb, key); 1171 if (!dbuf.dptr) { 1172 size_t offset; 1173 /* we'll need to create a new record */ 1174 1175 size = sizeof(*data) + sizeof(deferred_open_entry) + strlen(fname) + 1; 1176 p = (char *)SMB_MALLOC(size); 1177 if (!p) 1178 return False; 1179 data = (struct deferred_open_data *)p; 1180 data->u.num_deferred_open_entries = 1; 1181 1182 DEBUG(10,("add_deferred_open: creating entry for file %s. num_deferred_open_entries = 1\n", 1183 fname )); 1184 1185 offset = sizeof(*data) + sizeof(deferred_open_entry); 1186 safe_strcpy(p + offset, fname, size - offset - 1); 1187 fill_deferred_open(p + sizeof(*data), mid, ptv, dev, inode, port); 1188 dbuf.dptr = p; 1189 dbuf.dsize = size; 1190 if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1) 1191 ret = False; 1192 1193 print_deferred_open_table((struct deferred_open_data *)p); 1194 1195 SAFE_FREE(p); 1196 return ret; 1197 } 1198 1199 /* we're adding to an existing entry - this is a bit fiddly */ 1200 data = (struct deferred_open_data *)dbuf.dptr; 1201 1202 data->u.num_deferred_open_entries++; 1203 1204 DEBUG(10,("add_deferred_open: adding entry for file %s. new num_deferred_open_entries = %d\n", 1205 fname, data->u.num_deferred_open_entries )); 1206 1207 size = dbuf.dsize + sizeof(deferred_open_entry); 1208 p = SMB_MALLOC(size); 1209 if (!p) { 1210 SAFE_FREE(dbuf.dptr); 1211 return False; 1212 } 1213 memcpy(p, dbuf.dptr, sizeof(*data)); 1214 fill_deferred_open(p + sizeof(*data), mid, ptv, dev, inode, port); 1215 memcpy(p + sizeof(*data) + sizeof(deferred_open_entry), dbuf.dptr + sizeof(*data), 1216 dbuf.dsize - sizeof(*data)); 1217 SAFE_FREE(dbuf.dptr); 1218 dbuf.dptr = p; 1219 dbuf.dsize = size; 1220 if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1) 1221 ret = False; 1222 print_deferred_open_table((struct deferred_open_data *)p); 1223 SAFE_FREE(p); 1224 return ret; 1225} 1226 1227/**************************************************************************** 1228 Traverse the whole database with this function, calling traverse_callback 1229 on each share mode 1230****************************************************************************/ 1231 1232static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, 1233 void* state) 1234{ 1235 struct locking_data *data; 1236 share_mode_entry *shares; 1237 char *name; 1238 int i; 1239 1240 SHAREMODE_FN(traverse_callback) = (SHAREMODE_FN_CAST())state; 1241 1242 /* Ensure this is a locking_key record. */ 1243 if (kbuf.dsize != sizeof(struct locking_key)) 1244 return 0; 1245 1246 data = (struct locking_data *)dbuf.dptr; 1247 shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data)); 1248 name = dbuf.dptr + sizeof(*data) + data->u.num_share_mode_entries*sizeof(*shares); 1249 1250 for (i=0;i<data->u.num_share_mode_entries;i++) { 1251 traverse_callback(&shares[i], name); 1252 } 1253 return 0; 1254} 1255 1256/******************************************************************* 1257 Call the specified function on each entry under management by the 1258 share mode system. 1259********************************************************************/ 1260 1261int share_mode_forall(SHAREMODE_FN(fn)) 1262{ 1263 if (!tdb) 1264 return 0; 1265 return tdb_traverse(tdb, traverse_fn, (void*)fn); 1266} 1267