2 Unix SMB/Netbios implementation.
5 Copyright (C) Andrew Tridgell 1992-2000
6 Copyright (C) Jeremy Allison 1992-2000
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 12 aug 96: Erik.Devriendt@te6.siemens.be
25 added support for shared memory implementation of share mode locking
27 May 1997. Jeremy Allison (jallison@whistle.com). Modified share mode
28 locking to deal with multiple share modes per open file.
30 September 1997. Jeremy Allison (jallison@whistle.com). Added oplock
33 rewrtten completely to use new tdb code. Tridge, Dec '99
35 Added POSIX locking support. Jeremy Allison (jeremy@valinux.com), Apr. 2000.
39 extern int DEBUGLEVEL;
41 /* the locking database handle */
42 static TDB_CONTEXT *tdb;
47 * Doubly linked list to hold pending closes needed for
48 * POSIX locks. This may be changed to use a hash table (as
49 * in lib/hash.c if this is too slow in use.... JRA.
52 struct pending_closes {
53 struct pending_closes *next;
54 struct pending_closes *prev;
62 static struct pending_closes *pending_close_list = NULL;
64 /****************************************************************************
65 Find a dev/inode pair in the pending close list.
66 ****************************************************************************/
68 static struct pending_closes *find_pending_close_entry(SMB_DEV_T dev, SMB_INO_T inode)
70 struct pending_closes *pc;
72 for(pc = pending_close_list; pc; pc = pc->next) {
73 if (dev == pc->dev && inode == pc->inode) {
74 DLIST_PROMOTE(pending_close_list,pc);
82 /****************************************************************************
83 Add an fd into the pending close array.
84 ****************************************************************************/
86 static BOOL add_fd_to_close_entry(struct pending_closes *pc, int fd)
88 if ((pc->fd_array = (int *)Realloc(pc->fd_array, (pc->fd_array_size + 1)*sizeof(int))) == NULL) {
89 DEBUG(0,("add_fd_to_close_entry: Unable to increase fd_array !\n"));
93 pc->fd_array[pc->fd_array_size] = fd;
96 DEBUG(10,("add_fd_to_close_entry: added fd = %d, size = %u : dev = %.0f, ino = %.0f\n",
97 fd, (unsigned int)pc->fd_array_size, (double)pc->dev, (double)pc->inode ));
102 /****************************************************************************
103 Deal with pending closes needed by POSIX locking support.
104 ****************************************************************************/
106 BOOL fd_close_posix_locks(struct connection_struct *conn, files_struct *fsp)
108 struct pending_closes *pc;
112 if (!lp_posix_locking(SNUM(conn)))
115 pc = find_pending_close_entry(fsp->dev, fsp->inode);
119 * No other open with a POSIX lock on this dev/inode within this smbd.
125 if (pc->num_posix_locks) {
127 * There are outstanding locks on this dev/inode pair.
128 * Add our fd to the list and set fsp->fd to -1 to
132 if (!add_fd_to_close_entry(pc, fsp->fd))
139 DEBUG(10,("fd_close_posix_locks: doing close on %u fd's.\n", (unsigned int)pc->fd_array_size ));
142 * This is the last close. If there are pending fd's close them
143 * now. Save the errno just in case.
146 for(i = 0; i < pc->fd_array_size; i++) {
147 if (pc->fd_array[i] != -1) {
148 if (conn->vfs_ops.close(pc->fd_array[i]) == -1) {
155 free((char *)pc->fd_array);
157 DLIST_REMOVE(pending_close_list, pc);
161 if (saved_errno != 0) {
168 /****************************************************************************
169 A POSIX lock was granted. Increment the lock list count (create if needed).
170 ****************************************************************************/
172 static void increment_posix_lock_list(files_struct *fsp)
174 struct pending_closes *pc;
176 if ((pc = find_pending_close_entry(fsp->dev, fsp->inode)) == NULL) {
177 if (!(pc = (struct pending_closes *)malloc(sizeof(struct pending_closes)))) {
178 DEBUG(0,("increment_lock_list: malloc fail.\n"));
183 pc->inode = fsp->inode;
184 DLIST_ADD(pending_close_list, pc);
186 DEBUG(10,("increment_posix_lock_list: creating entry for file %s: dev = %.0f, ino = %.0f\n",
187 fsp->fsp_name, (double)fsp->dev, (double)fsp->inode ));
190 pc->num_posix_locks++;
192 DEBUG(10,("increment_posix_lock_list: entry for file %s: dev = %.0f, ino = %.0f, num_locks = %d\n",
193 fsp->fsp_name, (double)pc->dev, (double)pc->inode, pc->num_posix_locks ));
197 /****************************************************************************
198 A POSIX lock was granted. Decrement the lock list count.
199 ****************************************************************************/
201 static void decrement_posix_lock_list(files_struct *fsp)
203 struct pending_closes *pc;
205 pc = find_pending_close_entry(fsp->dev, fsp->inode);
208 smb_panic("decrement_lock_list: Unlock not found !\n");
211 pc->num_posix_locks--;
213 DEBUG(10,("decrement_posix_lock_list: entry for file %s: dev = %.0f, ino = %.0f, num_locks = %d\n",
214 fsp->fsp_name, (double)pc->dev, (double)pc->inode, pc->num_posix_locks ));
216 SMB_ASSERT(pc->num_posix_locks >= 0);
219 /****************************************************************************
221 ****************************************************************************/
223 static const char *lock_type_name(enum brl_type lock_type)
225 return (lock_type == READ_LOCK) ? "READ" : "WRITE";
228 /****************************************************************************
229 Utility function to map a lock type correctly depending on the open
231 ****************************************************************************/
233 static int map_posix_lock_type( files_struct *fsp, enum brl_type lock_type)
235 if((lock_type == WRITE_LOCK) && !fsp->can_write) {
237 * Many UNIX's cannot get a write lock on a file opened read-only.
238 * Win32 locking semantics allow this.
239 * Do the best we can and attempt a read-only lock.
241 DEBUG(10,("map_posix_lock_type: Downgrading write lock to read due to read-only file.\n"));
243 } else if((lock_type == READ_LOCK) && !fsp->can_read) {
245 * Ditto for read locks on write only files.
247 DEBUG(10,("map_posix_lock_type: Changing read lock to write due to write-only file.\n"));
252 * This return should be the most normal, as we attempt
253 * to always open files read/write.
256 return (lock_type == READ_LOCK) ? F_RDLCK : F_WRLCK;
259 /****************************************************************************
260 Check to see if the given unsigned lock range is within the possible POSIX
261 range. Modifies the given args to be in range if possible, just returns
263 ****************************************************************************/
265 static BOOL posix_lock_in_range(SMB_OFF_T *offset_out, SMB_OFF_T *count_out,
266 SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count)
271 #if defined(LARGE_SMB_OFF_T) && !defined(HAVE_BROKEN_FCNTL64_LOCKS)
273 SMB_OFF_T mask2 = ((SMB_OFF_T)0x4) << (SMB_OFF_T_BITS-4);
274 SMB_OFF_T mask = (mask2<<1);
275 SMB_OFF_T neg_mask = ~mask;
278 * In this case SMB_OFF_T is 64 bits,
279 * and the underlying system can handle 64 bit signed locks.
280 * Cast to signed type.
283 offset = (SMB_OFF_T)u_offset;
284 count = (SMB_OFF_T)u_count;
287 * Deal with a very common case of count of all ones.
288 * (lock entire file).
291 if(count == (SMB_OFF_T)-1)
295 * POSIX lock ranges cannot be negative.
296 * Fail if any combination becomes negative.
299 if(offset < 0 || count < 0 || (offset + count < 0)) {
300 DEBUG(10,("posix_lock_in_range: negative range: offset = %.0f, count = %.0f. Ignoring lock.\n",
301 (double)offset, (double)count ));
306 * In this case SMB_OFF_T is 64 bits, the offset and count
307 * fit within the positive range, and the underlying
308 * system can handle 64 bit locks. Just return as the
309 * cast values are ok.
312 #else /* !LARGE_SMB_OFF_T || HAVE_BROKEN_FCNTL64_LOCKS */
315 * In this case either SMB_OFF_T is 32 bits,
316 * or the underlying system cannot handle 64 bit signed locks.
317 * Either way we have to try and mangle to fit within 31 bits.
321 #if defined(HAVE_BROKEN_FCNTL64_LOCKS)
324 * SMB_OFF_T is 64 bits, but we need to use 31 bits due to
325 * broken large locking.
329 * Deal with a very common case of count of all ones.
330 * (lock entire file).
333 if(u_count == (SMB_BIG_UINT)-1)
336 if(((u_offset >> 32) & 0xFFFFFFFF) || ((u_count >> 32) & 0xFFFFFFFF)) {
337 DEBUG(10,("posix_lock_in_range: top 32 bits not zero. offset = %.0f, count = %.0f. Ignoring lock.\n",
338 (double)u_offset, (double)u_count ));
339 /* Top 32 bits of offset or count were not zero. */
343 /* Cast from 64 bits unsigned to 64 bits signed. */
344 offset = (SMB_OFF_T)u_offset;
345 count = (SMB_OFF_T)u_count;
348 * Check if we are within the 2^31 range.
352 int32 low_offset = (int32)offset;
353 int32 low_count = (int32)count;
355 if(low_offset < 0 || low_count < 0 || (low_offset + low_count < 0)) {
356 DEBUG(10,("posix_lock_in_range: not within 2^31 range. low_offset = %d, low_count = %d. Ignoring lock.\n",
357 low_offset, low_count ));
363 * Ok - we can map from a 64 bit number to a 31 bit lock.
366 #else /* HAVE_BROKEN_FCNTL64_LOCKS */
369 * SMB_OFF_T is 32 bits.
372 #if defined(HAVE_LONGLONG)
375 * SMB_BIG_UINT is 64 bits, we can do a 32 bit shift.
379 * Deal with a very common case of count of all ones.
380 * (lock entire file).
383 if(u_count == (SMB_BIG_UINT)-1)
386 if(((u_offset >> 32) & 0xFFFFFFFF) || ((u_count >> 32) & 0xFFFFFFFF)) {
387 DEBUG(10,("posix_lock_in_range: top 32 bits not zero. u_offset = %.0f, u_count = %.0f. Ignoring lock.\n",
388 (double)u_offset, (double)u_count ));
392 /* Cast from 64 bits unsigned to 32 bits signed. */
393 offset = (SMB_OFF_T)u_offset;
394 count = (SMB_OFF_T)u_count;
397 * Check if we are within the 2^31 range.
400 if(offset < 0 || count < 0 || (offset + count < 0)) {
401 DEBUG(10,("posix_lock_in_range: not within 2^31 range. offset = %d, count = %d. Ignoring lock.\n",
402 (int)offset, (int)count ));
406 #else /* HAVE_LONGLONG */
409 * SMB_BIG_UINT and SMB_OFF_T are both 32 bits,
414 * Deal with a very common case of count of all ones.
415 * (lock entire file).
418 if(u_count == (SMB_BIG_UINT)-1)
421 /* Cast from 32 bits unsigned to 32 bits signed. */
422 offset = (SMB_OFF_T)u_offset;
423 count = (SMB_OFF_T)u_count;
426 * Check if we are within the 2^31 range.
429 if(offset < 0 || count < 0 || (offset + count < 0)) {
430 DEBUG(10,("posix_lock_in_range: not within 2^31 range. offset = %d, count = %d. Ignoring lock.\n",
431 (int)offset, (int)count ));
435 #endif /* HAVE_LONGLONG */
436 #endif /* LARGE_SMB_OFF_T */
437 #endif /* !LARGE_SMB_OFF_T || HAVE_BROKEN_FCNTL64_LOCKS */
440 * The mapping was successful.
443 DEBUG(10,("posix_lock_in_range: offset_out = %.0f, count_out = %.0f\n",
444 (double)offset, (double)count ));
446 *offset_out = offset;
452 /****************************************************************************
453 POSIX function to see if a file region is locked. Returns True if the
454 region is locked, False otherwise.
455 ****************************************************************************/
457 static BOOL is_posix_locked(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count, enum brl_type lock_type)
462 DEBUG(10,("is_posix_locked: File %s, offset = %.0f, count = %.0f, type = %s\n",
463 fsp->fsp_name, (double)u_offset, (double)u_count, lock_type_name(lock_type) ));
466 * If the requested lock won't fit in the POSIX range, we will
467 * never set it, so presume it is not locked.
470 if(!posix_lock_in_range(&offset, &count, u_offset, u_count))
474 * Note that most UNIX's can *test* for a write lock on
475 * a read-only fd, just not *set* a write lock on a read-only
476 * fd. So we don't need to use map_lock_type here.
479 return fcntl_lock(fsp->fd,SMB_F_GETLK,offset,count,lock_type);
482 /****************************************************************************
483 POSIX function to acquire a lock. Returns True if the
484 lock could be granted, False if not.
485 ****************************************************************************/
487 static BOOL set_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count, enum brl_type lock_type)
493 DEBUG(5,("set_posix_lock: File %s, offset = %.0f, count = %.0f, type = %s\n",
494 fsp->fsp_name, (double)u_offset, (double)u_count, lock_type_name(lock_type) ));
497 * If the requested lock won't fit in the POSIX range, we will
498 * pretend it was successful.
501 if(!posix_lock_in_range(&offset, &count, u_offset, u_count))
505 * Note that setting multiple overlapping read locks on different
506 * file descriptors will not be held separately by the kernel (POSIX
507 * braindamage), but will be merged into one continuous read lock
508 * range. We cope with this case in the release_posix_lock code
512 ret = fcntl_lock(fsp->fd,SMB_F_SETLK,offset,count,map_posix_lock_type(fsp,lock_type));
517 /****************************************************************************
518 POSIX function to release a lock. Returns True if the
519 lock could be released, False if not.
520 ****************************************************************************/
522 static BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count)
528 DEBUG(5,("release_posix_lock: File %s, offset = %.0f, count = %.0f\n",
529 fsp->fsp_name, (double)u_offset, (double)u_count ));
534 * This lock must overlap with an existing read-only lock
535 * help by another fd. Don't do any POSIX call.
542 * If the requested lock won't fit in the POSIX range, we will
543 * pretend it was successful.
546 if(!posix_lock_in_range(&offset, &count, u_offset, u_count))
549 ret = fcntl_lock(fsp->fd,SMB_F_SETLK,offset,count,F_UNLCK);
554 /****************************************************************************
555 Utility function called to see if a file region is locked.
556 ****************************************************************************/
558 BOOL is_locked(files_struct *fsp,connection_struct *conn,
559 SMB_BIG_UINT count,SMB_BIG_UINT offset,
560 enum brl_type lock_type)
562 int snum = SNUM(conn);
568 if (!lp_locking(snum) || !lp_strict_locking(snum))
571 ret = !brl_locktest(fsp->dev, fsp->inode,
572 global_smbpid, getpid(), conn->cnum,
573 offset, count, lock_type);
576 * There is no lock held by an SMB daemon, check to
577 * see if there is a POSIX lock from a UNIX or NFS process.
580 if(!ret && lp_posix_locking(snum))
581 ret = is_posix_locked(fsp, offset, count, lock_type);
586 /****************************************************************************
587 Utility function called by locking requests.
588 ****************************************************************************/
590 BOOL do_lock(files_struct *fsp,connection_struct *conn,
591 SMB_BIG_UINT count,SMB_BIG_UINT offset,enum brl_type lock_type,
592 int *eclass,uint32 *ecode)
596 if (!lp_locking(SNUM(conn)))
601 *ecode = ERRnoaccess;
605 DEBUG(10,("do_lock: lock type %s start=%.0f len=%.0f requested for file %s\n",
606 lock_type_name(lock_type), (double)offset, (double)count, fsp->fsp_name ));
608 if (OPEN_FSP(fsp) && fsp->can_lock && (fsp->conn == conn)) {
609 ok = brl_lock(fsp->dev, fsp->inode, fsp->fnum,
610 global_smbpid, getpid(), conn->cnum,
614 if(ok && lp_posix_locking(SNUM(conn))) {
617 * Try and get a POSIX lock on this range.
618 * Note that this is ok if it is a read lock
619 * overlapping on a different fd. JRA.
622 if((ok = set_posix_lock(fsp, offset, count, lock_type)) == True)
623 increment_posix_lock_list(fsp);
626 * We failed to map - we must now remove the brl
629 (void)brl_unlock(fsp->dev, fsp->inode, fsp->fnum,
630 global_smbpid, getpid(), conn->cnum,
641 return True; /* Got lock */
644 /****************************************************************************
645 Utility function called by unlocking requests.
646 ****************************************************************************/
648 BOOL do_unlock(files_struct *fsp,connection_struct *conn,
649 SMB_BIG_UINT count,SMB_BIG_UINT offset,
650 int *eclass,uint32 *ecode)
653 TALLOC_CTX *ul_ctx = NULL;
654 struct unlock_list *ulist = NULL;
655 struct unlock_list *ul = NULL;
658 if (!lp_locking(SNUM(conn)))
661 if (!OPEN_FSP(fsp) || !fsp->can_lock || (fsp->conn != conn)) {
667 DEBUG(10,("do_unlock: unlock start=%.0f len=%.0f requested for file %s\n",
668 (double)offset, (double)count, fsp->fsp_name ));
671 * Remove the existing lock record from the tdb lockdb
672 * before looking at POSIX locks. If this record doesn't
673 * match then don't bother looking to remove POSIX locks.
678 ok = brl_unlock(fsp->dev, fsp->inode, fsp->fnum,
679 global_smbpid, pid, conn->cnum, offset, count);
687 if (!lp_posix_locking(SNUM(conn)))
690 if ((ul_ctx = talloc_init()) == NULL) {
691 DEBUG(0,("do_unlock: unable to init talloc context.\n"));
692 return True; /* Not a fatal error. */
695 if ((ul = (struct unlock_list *)talloc(ul_ctx, sizeof(struct unlock_list))) == NULL) {
696 DEBUG(0,("do_unlock: unable to talloc unlock list.\n"));
697 talloc_destroy(ul_ctx);
698 return True; /* Not a fatal error. */
702 * Create the initial list entry containing the
703 * lock we want to remove.
710 DLIST_ADD(ulist, ul);
713 * The following call calculates if there are any
714 * overlapping read locks held by this process on
715 * other fd's open on the same file and creates a
716 * list of unlock ranges that will allow other
717 * POSIX lock ranges to remain on the file whilst the
718 * unlocks are performed.
721 ulist = brl_unlock_list(ul_ctx, ulist, pid, fsp->dev, fsp->inode);
724 * Release the POSIX locks on the list of ranges returned.
727 for(; ulist; ulist = ulist->next)
728 (void)release_posix_lock(fsp, ulist->start, ulist->size);
730 talloc_destroy(ul_ctx);
733 * We treat this as one unlock request for POSIX accounting purposes even
734 * if it may have been split into multiple smaller POSIX unlock ranges.
737 decrement_posix_lock_list(fsp);
739 return True; /* Did unlock */
742 /****************************************************************************
743 Remove any locks on this fd. Called from file_close().
744 ****************************************************************************/
746 void locking_close_file(files_struct *fsp)
748 pid_t pid = getpid();
750 if (!lp_locking(SNUM(fsp->conn)))
753 if(lp_posix_locking(SNUM(fsp->conn))) {
755 TALLOC_CTX *ul_ctx = NULL;
756 struct unlock_list *ul = NULL;
760 if ((ul_ctx = talloc_init()) == NULL) {
761 DEBUG(0,("locking_close_file: unable to init talloc context.\n"));
766 * We need to release all POSIX locks we have on this
767 * fd. Get all our existing locks from the tdb locking database.
770 ul = brl_getlocklist(ul_ctx, fsp->dev, fsp->inode, pid, fsp->conn->cnum, fsp->fnum);
773 * Now unlock all of them. This will remove the brl entry also
777 for(; ul; ul = ul->next)
778 do_unlock(fsp,fsp->conn,ul->size,ul->start,&eclass,&ecode);
780 talloc_destroy(ul_ctx);
785 * Just release all the tdb locks, no need to release individually.
788 brl_close(fsp->dev, fsp->inode, pid, fsp->conn->cnum, fsp->fnum);
792 /****************************************************************************
793 Initialise the locking functions.
794 ****************************************************************************/
795 BOOL locking_init(int read_only)
799 if (tdb) return True;
801 tdb = tdb_open(lock_path("locking.tdb"),
802 0, TDB_CLEAR_IF_FIRST,
803 read_only?O_RDONLY:O_RDWR|O_CREAT,
807 DEBUG(0,("ERROR: Failed to initialise share modes\n"));
814 /*******************************************************************
815 Deinitialize the share_mode management.
816 ******************************************************************/
817 BOOL locking_end(void)
819 if (tdb && tdb_close(tdb) != 0) return False;
823 /*******************************************************************
824 form a static locking key for a dev/inode pair
825 ******************************************************************/
826 static TDB_DATA locking_key(SMB_DEV_T dev, SMB_INO_T inode)
828 static struct locking_key key;
832 kbuf.dptr = (char *)&key;
833 kbuf.dsize = sizeof(key);
836 static TDB_DATA locking_key_fsp(files_struct *fsp)
838 return locking_key(fsp->dev, fsp->inode);
841 /*******************************************************************
842 Lock a hash bucket entry.
843 ******************************************************************/
844 BOOL lock_share_entry(connection_struct *conn,
845 SMB_DEV_T dev, SMB_INO_T inode)
847 return tdb_lockchain(tdb, locking_key(dev, inode)) == 0;
850 /*******************************************************************
851 Unlock a hash bucket entry.
852 ******************************************************************/
853 BOOL unlock_share_entry(connection_struct *conn,
854 SMB_DEV_T dev, SMB_INO_T inode)
856 return tdb_unlockchain(tdb, locking_key(dev, inode)) == 0;
860 /*******************************************************************
861 Lock a hash bucket entry. use a fsp for convenience
862 ******************************************************************/
863 BOOL lock_share_entry_fsp(files_struct *fsp)
865 return tdb_lockchain(tdb, locking_key(fsp->dev, fsp->inode)) == 0;
868 /*******************************************************************
869 Unlock a hash bucket entry.
870 ******************************************************************/
871 BOOL unlock_share_entry_fsp(files_struct *fsp)
873 return tdb_unlockchain(tdb, locking_key(fsp->dev, fsp->inode)) == 0;
876 /*******************************************************************
877 Get all share mode entries for a dev/inode pair.
878 ********************************************************************/
879 int get_share_modes(connection_struct *conn,
880 SMB_DEV_T dev, SMB_INO_T inode,
881 share_mode_entry **shares)
884 struct locking_data *data;
889 dbuf = tdb_fetch(tdb, locking_key(dev, inode));
890 if (!dbuf.dptr) return 0;
892 data = (struct locking_data *)dbuf.dptr;
893 ret = data->num_share_mode_entries;
895 *shares = (share_mode_entry *)memdup(dbuf.dptr + sizeof(*data), ret * sizeof(**shares));
898 if (! *shares) return 0;
903 /*******************************************************************
904 Del the share mode of a file for this process
905 ********************************************************************/
906 void del_share_mode(files_struct *fsp)
909 struct locking_data *data;
911 share_mode_entry *shares;
912 pid_t pid = getpid();
914 /* read in the existing share modes */
915 dbuf = tdb_fetch(tdb, locking_key_fsp(fsp));
916 if (!dbuf.dptr) return;
918 data = (struct locking_data *)dbuf.dptr;
919 shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data));
921 /* find any with our pid and delete it by overwriting with the rest of the data
923 for (i=0;i<data->num_share_mode_entries;) {
924 if (shares[i].pid == pid &&
925 memcmp(&shares[i].time,
926 &fsp->open_time,sizeof(struct timeval)) == 0) {
927 data->num_share_mode_entries--;
928 memmove(&shares[i], &shares[i+1],
929 dbuf.dsize - (sizeof(*data) + (i+1)*sizeof(*shares)));
936 /* the record has shrunk a bit */
937 dbuf.dsize -= del_count * sizeof(*shares);
939 /* store it back in the database */
940 if (data->num_share_mode_entries == 0) {
941 tdb_delete(tdb, locking_key_fsp(fsp));
943 tdb_store(tdb, locking_key_fsp(fsp), dbuf, TDB_REPLACE);
949 /*******************************************************************
950 fill a share mode entry
951 ********************************************************************/
952 static void fill_share_mode(char *p, files_struct *fsp, uint16 port, uint16 op_type)
954 share_mode_entry *e = (share_mode_entry *)p;
956 e->share_mode = fsp->share_mode;
958 e->op_type = op_type;
959 memcpy((char *)&e->time, (char *)&fsp->open_time, sizeof(struct timeval));
962 /*******************************************************************
963 Set the share mode of a file. Return False on fail, True on success.
964 ********************************************************************/
965 BOOL set_share_mode(files_struct *fsp, uint16 port, uint16 op_type)
968 struct locking_data *data;
969 share_mode_entry *shares;
973 /* read in the existing share modes if any */
974 dbuf = tdb_fetch(tdb, locking_key_fsp(fsp));
976 /* we'll need to create a new record */
979 pstrcpy(fname, fsp->conn->connectpath);
981 pstrcat(fname, fsp->fsp_name);
983 size = sizeof(*data) + sizeof(*shares) + strlen(fname) + 1;
984 p = (char *)malloc(size);
985 data = (struct locking_data *)p;
986 shares = (share_mode_entry *)(p + sizeof(*data));
987 data->num_share_mode_entries = 1;
988 pstrcpy(p + sizeof(*data) + sizeof(*shares), fname);
989 fill_share_mode(p + sizeof(*data), fsp, port, op_type);
992 tdb_store(tdb, locking_key_fsp(fsp), dbuf, TDB_REPLACE);
997 /* we're adding to an existing entry - this is a bit fiddly */
998 data = (struct locking_data *)dbuf.dptr;
999 shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data));
1001 data->num_share_mode_entries++;
1002 size = dbuf.dsize + sizeof(*shares);
1004 memcpy(p, dbuf.dptr, sizeof(*data));
1005 fill_share_mode(p + sizeof(*data), fsp, port, op_type);
1006 memcpy(p + sizeof(*data) + sizeof(*shares), dbuf.dptr + sizeof(*data),
1007 dbuf.dsize - sizeof(*data));
1011 tdb_store(tdb, locking_key_fsp(fsp), dbuf, TDB_REPLACE);
1017 /*******************************************************************
1018 a generic in-place modification call for share mode entries
1019 ********************************************************************/
1020 static BOOL mod_share_mode(files_struct *fsp,
1021 void (*mod_fn)(share_mode_entry *, SMB_DEV_T, SMB_INO_T, void *),
1025 struct locking_data *data;
1027 share_mode_entry *shares;
1028 pid_t pid = getpid();
1031 /* read in the existing share modes */
1032 dbuf = tdb_fetch(tdb, locking_key_fsp(fsp));
1033 if (!dbuf.dptr) return False;
1035 data = (struct locking_data *)dbuf.dptr;
1036 shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data));
1038 /* find any with our pid and call the supplied function */
1039 for (i=0;i<data->num_share_mode_entries;i++) {
1040 if (pid == shares[i].pid &&
1041 shares[i].share_mode == fsp->share_mode &&
1042 memcmp(&shares[i].time,
1043 &fsp->open_time,sizeof(struct timeval)) == 0) {
1044 mod_fn(&shares[i], fsp->dev, fsp->inode, param);
1049 /* if the mod fn was called then store it back */
1051 if (data->num_share_mode_entries == 0) {
1052 tdb_delete(tdb, locking_key_fsp(fsp));
1054 tdb_store(tdb, locking_key_fsp(fsp), dbuf, TDB_REPLACE);
1063 /*******************************************************************
1064 Static function that actually does the work for the generic function
1066 ********************************************************************/
1067 static void remove_share_oplock_fn(share_mode_entry *entry, SMB_DEV_T dev, SMB_INO_T inode,
1070 DEBUG(10,("remove_share_oplock_fn: removing oplock info for entry dev=%x ino=%.0f\n",
1071 (unsigned int)dev, (double)inode ));
1072 /* Delete the oplock info. */
1074 entry->op_type = NO_OPLOCK;
1077 /*******************************************************************
1078 Remove an oplock port and mode entry from a share mode.
1079 ********************************************************************/
1080 BOOL remove_share_oplock(files_struct *fsp)
1082 return mod_share_mode(fsp, remove_share_oplock_fn, NULL);
1085 /*******************************************************************
1086 Static function that actually does the work for the generic function
1088 ********************************************************************/
1089 static void downgrade_share_oplock_fn(share_mode_entry *entry, SMB_DEV_T dev, SMB_INO_T inode,
1092 DEBUG(10,("downgrade_share_oplock_fn: downgrading oplock info for entry dev=%x ino=%.0f\n",
1093 (unsigned int)dev, (double)inode ));
1094 entry->op_type = LEVEL_II_OPLOCK;
1097 /*******************************************************************
1098 Downgrade a oplock type from exclusive to level II.
1099 ********************************************************************/
1100 BOOL downgrade_share_oplock(files_struct *fsp)
1102 return mod_share_mode(fsp, downgrade_share_oplock_fn, NULL);
1106 /*******************************************************************
1107 Static function that actually does the work for the generic function
1109 ********************************************************************/
1115 static void modify_share_mode_fn(share_mode_entry *entry, SMB_DEV_T dev, SMB_INO_T inode,
1118 struct mod_val *mvp = (struct mod_val *)param;
1120 DEBUG(10,("modify_share_mode_fn: changing share mode info from %x to %x for entry dev=%x ino=%.0f\n",
1121 entry->share_mode, mvp->new_share_mode, (unsigned int)dev, (double)inode ));
1122 DEBUG(10,("modify_share_mode_fn: changing oplock state from %x to %x for entry dev=%x ino=%.0f\n",
1123 entry->op_type, (int)mvp->new_oplock, (unsigned int)dev, (double)inode ));
1124 /* Change the share mode info. */
1125 entry->share_mode = mvp->new_share_mode;
1126 entry->op_type = mvp->new_oplock;
1129 /*******************************************************************
1130 Modify a share mode on a file. Used by the delete open file code.
1131 Return False on fail, True on success.
1132 ********************************************************************/
1133 BOOL modify_share_mode(files_struct *fsp, int new_mode, uint16 new_oplock)
1137 mv.new_share_mode = new_mode;
1138 mv.new_oplock = new_oplock;
1140 return mod_share_mode(fsp, modify_share_mode_fn, (void *)&mv);
1144 /****************************************************************************
1145 traverse the whole database with this function, calling traverse_callback
1147 ****************************************************************************/
1148 static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf,
1151 struct locking_data *data;
1152 share_mode_entry *shares;
1156 SHAREMODE_FN(traverse_callback) = (SHAREMODE_FN_CAST())state;
1158 data = (struct locking_data *)dbuf.dptr;
1159 shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data));
1160 name = dbuf.dptr + sizeof(*data) + data->num_share_mode_entries*sizeof(*shares);
1162 for (i=0;i<data->num_share_mode_entries;i++) {
1163 traverse_callback(&shares[i], name);
1168 /*******************************************************************
1169 Call the specified function on each entry under management by the
1171 ********************************************************************/
1172 int share_mode_forall(SHAREMODE_FN(fn))
1175 return tdb_traverse(tdb, traverse_fn, (void*)fn);