Cleanups: (merge from HEAD)
[sfrench/samba-autobuild/.git] / source / locking / locking.c
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"
38 uint16 global_smbpid;
39
40 /* the locking database handle */
41 static TDB_CONTEXT *tdb;
42
43 /****************************************************************************
44  Debugging aid :-).
45 ****************************************************************************/
46
47 static const char *lock_type_name(enum brl_type lock_type)
48 {
49         return (lock_type == READ_LOCK) ? "READ" : "WRITE";
50 }
51
52 /****************************************************************************
53  Utility function called to see if a file region is locked.
54  If check_self is True, then checks on our own fd with the same locking context
55  are still made. If check_self is False, then checks are not made on our own fd
56  with the same locking context are not made.
57 ****************************************************************************/
58
59 BOOL is_locked(files_struct *fsp,connection_struct *conn,
60                SMB_BIG_UINT count,SMB_BIG_UINT offset, 
61                enum brl_type lock_type, BOOL check_self)
62 {
63         int snum = SNUM(conn);
64         BOOL ret;
65         
66         if (count == 0)
67                 return(False);
68
69         if (!lp_locking(snum) || !lp_strict_locking(snum))
70                 return(False);
71
72         ret = !brl_locktest(fsp->dev, fsp->inode, fsp->fnum,
73                              global_smbpid, sys_getpid(), conn->cnum, 
74                              offset, count, lock_type, check_self);
75
76         DEBUG(10,("is_locked: brl start=%.0f len=%.0f %s for file %s\n",
77                         (double)offset, (double)count, ret ? "locked" : "unlocked",
78                         fsp->fsp_name ));
79
80         /*
81          * There is no lock held by an SMB daemon, check to
82          * see if there is a POSIX lock from a UNIX or NFS process.
83          */
84
85         if(!ret && lp_posix_locking(snum)) {
86                 ret = is_posix_locked(fsp, offset, count, lock_type);
87
88                 DEBUG(10,("is_locked: posix start=%.0f len=%.0f %s for file %s\n",
89                                 (double)offset, (double)count, ret ? "locked" : "unlocked",
90                                 fsp->fsp_name ));
91         }
92
93         return ret;
94 }
95
96 /****************************************************************************
97  Utility function called by locking requests.
98 ****************************************************************************/
99
100 static NTSTATUS do_lock(files_struct *fsp,connection_struct *conn, uint16 lock_pid,
101                  SMB_BIG_UINT count,SMB_BIG_UINT offset,enum brl_type lock_type)
102 {
103         NTSTATUS status = NT_STATUS_LOCK_NOT_GRANTED;
104
105         if (!lp_locking(SNUM(conn)))
106                 return NT_STATUS_OK;
107
108         /* NOTE! 0 byte long ranges ARE allowed and should be stored  */
109
110         DEBUG(10,("do_lock: lock type %s start=%.0f len=%.0f requested for file %s\n",
111                   lock_type_name(lock_type), (double)offset, (double)count, fsp->fsp_name ));
112
113         if (OPEN_FSP(fsp) && fsp->can_lock && (fsp->conn == conn)) {
114                 status = brl_lock(fsp->dev, fsp->inode, fsp->fnum,
115                                   lock_pid, sys_getpid(), conn->cnum, 
116                                   offset, count, 
117                                   lock_type);
118
119                 if (NT_STATUS_IS_OK(status) && lp_posix_locking(SNUM(conn))) {
120
121                         /*
122                          * Try and get a POSIX lock on this range.
123                          * Note that this is ok if it is a read lock
124                          * overlapping on a different fd. JRA.
125                          */
126
127                         if (!set_posix_lock(fsp, offset, count, lock_type)) {
128                                 status = NT_STATUS_LOCK_NOT_GRANTED;
129                                 /*
130                                  * We failed to map - we must now remove the brl
131                                  * lock entry.
132                                  */
133                                 (void)brl_unlock(fsp->dev, fsp->inode, fsp->fnum,
134                                                                 lock_pid, sys_getpid(), conn->cnum, 
135                                                                 offset, count);
136                         }
137                 }
138         }
139
140         return status;
141 }
142
143 /****************************************************************************
144  Utility function called by locking requests. This is *DISGUSTING*. It also
145  appears to be "What Windows Does" (tm). Andrew, ever wonder why Windows 2000
146  is so slow on the locking tests...... ? This is the reason. Much though I hate
147  it, we need this. JRA.
148 ****************************************************************************/
149
150 NTSTATUS do_lock_spin(files_struct *fsp,connection_struct *conn, uint16 lock_pid,
151                  SMB_BIG_UINT count,SMB_BIG_UINT offset,enum brl_type lock_type)
152 {
153         int j, maxj = lp_lock_spin_count();
154         int sleeptime = lp_lock_sleep_time();
155         NTSTATUS status, ret;
156
157         if (maxj <= 0)
158                 maxj = 1;
159
160         ret = NT_STATUS_OK; /* to keep dumb compilers happy */
161
162         for (j = 0; j < maxj; j++) {
163                 status = do_lock(fsp, conn, lock_pid, count, offset, lock_type);
164                 if (!NT_STATUS_EQUAL(status, NT_STATUS_LOCK_NOT_GRANTED) &&
165                     !NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
166                         return status;
167                 }
168                 /* if we do fail then return the first error code we got */
169                 if (j == 0) {
170                         ret = status;
171                 }
172                 if (sleeptime)
173                         sys_usleep(sleeptime);
174         }
175         return ret;
176 }
177
178 /****************************************************************************
179  Utility function called by unlocking requests.
180 ****************************************************************************/
181
182 NTSTATUS do_unlock(files_struct *fsp,connection_struct *conn, uint16 lock_pid,
183                    SMB_BIG_UINT count,SMB_BIG_UINT offset)
184 {
185         BOOL ok = False;
186         
187         if (!lp_locking(SNUM(conn)))
188                 return NT_STATUS_OK;
189         
190         if (!OPEN_FSP(fsp) || !fsp->can_lock || (fsp->conn != conn)) {
191                 return NT_STATUS_INVALID_HANDLE;
192         }
193         
194         DEBUG(10,("do_unlock: unlock start=%.0f len=%.0f requested for file %s\n",
195                   (double)offset, (double)count, fsp->fsp_name ));
196
197         /*
198          * Remove the existing lock record from the tdb lockdb
199          * before looking at POSIX locks. If this record doesn't
200          * match then don't bother looking to remove POSIX locks.
201          */
202
203         ok = brl_unlock(fsp->dev, fsp->inode, fsp->fnum,
204                         lock_pid, sys_getpid(), conn->cnum, offset, count);
205    
206         if (!ok) {
207                 DEBUG(10,("do_unlock: returning ERRlock.\n" ));
208                 return NT_STATUS_RANGE_NOT_LOCKED;
209         }
210
211         if (!lp_posix_locking(SNUM(conn)))
212                 return NT_STATUS_OK;
213
214         (void)release_posix_lock(fsp, offset, count);
215
216         return NT_STATUS_OK;
217 }
218
219 /****************************************************************************
220  Remove any locks on this fd. Called from file_close().
221 ****************************************************************************/
222
223 void locking_close_file(files_struct *fsp)
224 {
225         pid_t pid = sys_getpid();
226
227         if (!lp_locking(SNUM(fsp->conn)))
228                 return;
229
230         /*
231          * Just release all the brl locks, no need to release individually.
232          */
233
234         brl_close(fsp->dev, fsp->inode, pid, fsp->conn->cnum, fsp->fnum);
235
236         if(lp_posix_locking(SNUM(fsp->conn))) {
237
238                 /* 
239                  * Release all the POSIX locks.
240                  */
241                 posix_locking_close_file(fsp);
242
243         }
244 }
245
246 /****************************************************************************
247  Initialise the locking functions.
248 ****************************************************************************/
249
250 static int open_read_only;
251
252 BOOL locking_init(int read_only)
253 {
254         brl_init(read_only);
255
256         if (tdb)
257                 return True;
258
259         tdb = tdb_open_log(lock_path("locking.tdb"), 
260                        0, TDB_DEFAULT|(read_only?0x0:TDB_CLEAR_IF_FIRST), 
261                        read_only?O_RDONLY:O_RDWR|O_CREAT,
262                        0644);
263
264         if (!tdb) {
265                 DEBUG(0,("ERROR: Failed to initialise locking database\n"));
266                 return False;
267         }
268         
269         if (!posix_locking_init(read_only))
270                 return False;
271
272         open_read_only = read_only;
273
274         return True;
275 }
276
277 /*******************************************************************
278  Deinitialize the share_mode management.
279 ******************************************************************/
280
281 BOOL locking_end(void)
282 {
283
284         brl_shutdown(open_read_only);
285         if (tdb) {
286
287                 if (tdb_close(tdb) != 0)
288                         return False;
289         }
290
291         return True;
292 }
293
294 /*******************************************************************
295  Form a static locking key for a dev/inode pair.
296 ******************************************************************/
297
298 static TDB_DATA locking_key(SMB_DEV_T dev, SMB_INO_T inode)
299 {
300         static struct locking_key key;
301         TDB_DATA kbuf;
302
303         memset(&key, '\0', sizeof(key));
304         key.dev = dev;
305         key.inode = inode;
306         kbuf.dptr = (char *)&key;
307         kbuf.dsize = sizeof(key);
308         return kbuf;
309 }
310
311 static TDB_DATA locking_key_fsp(files_struct *fsp)
312 {
313         return locking_key(fsp->dev, fsp->inode);
314 }
315
316 /*******************************************************************
317  Lock a hash bucket entry.
318 ******************************************************************/
319
320 BOOL lock_share_entry(connection_struct *conn,
321                       SMB_DEV_T dev, SMB_INO_T inode)
322 {
323         return tdb_chainlock(tdb, locking_key(dev, inode)) == 0;
324 }
325
326 /*******************************************************************
327  Unlock a hash bucket entry.
328 ******************************************************************/
329
330 void unlock_share_entry(connection_struct *conn,
331                         SMB_DEV_T dev, SMB_INO_T inode)
332 {
333         tdb_chainunlock(tdb, locking_key(dev, inode));
334 }
335
336 /*******************************************************************
337  Lock a hash bucket entry. use a fsp for convenience
338 ******************************************************************/
339
340 BOOL lock_share_entry_fsp(files_struct *fsp)
341 {
342         return tdb_chainlock(tdb, locking_key(fsp->dev, fsp->inode)) == 0;
343 }
344
345 /*******************************************************************
346  Unlock a hash bucket entry.
347 ******************************************************************/
348
349 void unlock_share_entry_fsp(files_struct *fsp)
350 {
351         tdb_chainunlock(tdb, locking_key(fsp->dev, fsp->inode));
352 }
353
354 /*******************************************************************
355  Print out a share mode.
356 ********************************************************************/
357
358 static char *share_mode_str(int num, share_mode_entry *e)
359 {
360         static pstring share_str;
361
362         slprintf(share_str, sizeof(share_str)-1, "share_mode_entry[%d]: \
363 pid = %u, share_mode = 0x%x, desired_access = 0x%x, port = 0x%x, type= 0x%x, file_id = %lu, dev = 0x%x, inode = %.0f",
364         num, e->pid, e->share_mode, (unsigned int)e->desired_access, e->op_port, e->op_type, e->share_file_id,
365         (unsigned int)e->dev, (double)e->inode );
366
367         return share_str;
368 }
369
370 /*******************************************************************
371  Print out a share mode table.
372 ********************************************************************/
373
374 static void print_share_mode_table(struct locking_data *data)
375 {
376         int num_share_modes = data->u.num_share_mode_entries;
377         share_mode_entry *shares = (share_mode_entry *)(data + 1);
378         int i;
379
380         for (i = 0; i < num_share_modes; i++) {
381                 share_mode_entry *entry_p = &shares[i];
382                 DEBUG(10,("print_share_mode_table: %s\n", share_mode_str(i, entry_p) ));
383         }
384 }
385
386 /*******************************************************************
387  Get all share mode entries for a dev/inode pair.
388 ********************************************************************/
389
390 int get_share_modes(connection_struct *conn, 
391                     SMB_DEV_T dev, SMB_INO_T inode, 
392                     share_mode_entry **pp_shares)
393 {
394         TDB_DATA dbuf;
395         struct locking_data *data;
396         int num_share_modes;
397         share_mode_entry *shares = NULL;
398
399         *pp_shares = NULL;
400
401         dbuf = tdb_fetch(tdb, locking_key(dev, inode));
402         if (!dbuf.dptr)
403                 return 0;
404
405         data = (struct locking_data *)dbuf.dptr;
406         num_share_modes = data->u.num_share_mode_entries;
407         if(num_share_modes) {
408                 int i;
409                 int del_count = 0;
410
411                 shares = (share_mode_entry *)memdup(dbuf.dptr + sizeof(*data),  
412                                                 num_share_modes * sizeof(share_mode_entry));
413
414                 if (!shares) {
415                         SAFE_FREE(dbuf.dptr);
416                         return 0;
417                 }
418
419                 /*
420                  * Ensure that each entry has a real process attached.
421                  */
422
423                 for (i = 0; i < num_share_modes; ) {
424                         share_mode_entry *entry_p = &shares[i];
425                         if (process_exists(entry_p->pid)) {
426                                 DEBUG(10,("get_share_modes: %s\n", share_mode_str(i, entry_p) ));
427                                 i++;
428                         } else {
429                                 DEBUG(10,("get_share_modes: deleted %s\n", share_mode_str(i, entry_p) ));
430                                 memcpy( &shares[i], &shares[i+1],
431                                         sizeof(share_mode_entry) * (num_share_modes - i - 1));
432                                 num_share_modes--;
433                                 del_count++;
434                         }
435                 }
436
437                 /* Did we delete any ? If so, re-store in tdb. */
438                 if (del_count) {
439                         data->u.num_share_mode_entries = num_share_modes;
440                         
441                         if (num_share_modes)
442                                 memcpy(dbuf.dptr + sizeof(*data), shares,
443                                                 num_share_modes * sizeof(share_mode_entry));
444
445                         /* The record has shrunk a bit */
446                         dbuf.dsize -= del_count * sizeof(share_mode_entry);
447
448                         if (tdb_store(tdb, locking_key(dev, inode), dbuf, TDB_REPLACE) == -1) {
449                                 SAFE_FREE(shares);
450                                 SAFE_FREE(dbuf.dptr);
451                                 return 0;
452                         }
453                 }
454         }
455
456         SAFE_FREE(dbuf.dptr);
457         *pp_shares = shares;
458         return num_share_modes;
459 }
460
461 /*******************************************************************
462  Fill a share mode entry.
463 ********************************************************************/
464
465 static void fill_share_mode(char *p, files_struct *fsp, uint16 port, uint16 op_type)
466 {
467         share_mode_entry *e = (share_mode_entry *)p;
468         void *x = &e->time; /* Needed to force alignment. p may not be aligned.... */
469
470         memset(e, '\0', sizeof(share_mode_entry));
471         e->pid = sys_getpid();
472         e->share_mode = fsp->share_mode;
473         e->desired_access = fsp->desired_access;
474         e->op_port = port;
475         e->op_type = op_type;
476         memcpy(x, &fsp->open_time, sizeof(struct timeval));
477         e->share_file_id = fsp->file_id;
478         e->dev = fsp->dev;
479         e->inode = fsp->inode;
480 }
481
482 /*******************************************************************
483  Check if two share mode entries are identical, ignoring oplock 
484  and port info and desired_access.
485 ********************************************************************/
486
487 BOOL share_modes_identical( share_mode_entry *e1, share_mode_entry *e2)
488 {
489 #if 1 /* JRA PARANOIA TEST - REMOVE LATER */
490         if (e1->pid == e2->pid &&
491                 e1->share_file_id == e2->share_file_id &&
492                 e1->dev == e2->dev &&
493                 e1->inode == e2->inode &&
494                 (e1->share_mode & ~DELETE_ON_CLOSE_FLAG) != (e2->share_mode & ~DELETE_ON_CLOSE_FLAG)) {
495                         DEBUG(0,("PANIC: share_modes_identical: share_mode missmatch (e1 = %u, e2 = %u). Logic error.\n",
496                                 (unsigned int)(e1->share_mode & ~DELETE_ON_CLOSE_FLAG),
497                                 (unsigned int)(e2->share_mode & ~DELETE_ON_CLOSE_FLAG) ));
498                 smb_panic("PANIC: share_modes_identical logic error.\n");
499         }
500 #endif
501
502         return (e1->pid == e2->pid &&
503                 (e1->share_mode & ~DELETE_ON_CLOSE_FLAG) == (e2->share_mode & ~DELETE_ON_CLOSE_FLAG) &&
504                 e1->dev == e2->dev &&
505                 e1->inode == e2->inode &&
506                 e1->share_file_id == e2->share_file_id );
507 }
508
509 /*******************************************************************
510  Delete a specific share mode. Return the number
511  of entries left, and a memdup'ed copy of the entry deleted (if required).
512  Ignore if no entry deleted.
513 ********************************************************************/
514
515 ssize_t del_share_entry( SMB_DEV_T dev, SMB_INO_T inode,
516                         share_mode_entry *entry, share_mode_entry **ppse)
517 {
518         TDB_DATA dbuf;
519         struct locking_data *data;
520         int i, del_count=0;
521         share_mode_entry *shares;
522         ssize_t count = 0;
523
524         if (ppse)
525                 *ppse = NULL;
526
527         /* read in the existing share modes */
528         dbuf = tdb_fetch(tdb, locking_key(dev, inode));
529         if (!dbuf.dptr)
530                 return -1;
531
532         data = (struct locking_data *)dbuf.dptr;
533         shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data));
534
535         /*
536          * Find any with this pid and delete it
537          * by overwriting with the rest of the data 
538          * from the record.
539          */
540
541         DEBUG(10,("del_share_entry: num_share_modes = %d\n", data->u.num_share_mode_entries ));
542
543         for (i=0;i<data->u.num_share_mode_entries;) {
544                 if (share_modes_identical(&shares[i], entry)) {
545                         DEBUG(10,("del_share_entry: deleted %s\n",
546                                 share_mode_str(i, &shares[i]) ));
547                         if (ppse)
548                                 *ppse = memdup(&shares[i], sizeof(*shares));
549                         data->u.num_share_mode_entries--;
550                         memmove(&shares[i], &shares[i+1], 
551                                 dbuf.dsize - (sizeof(*data) + (i+1)*sizeof(*shares)));
552                         del_count++;
553
554                         DEBUG(10,("del_share_entry: deleting entry %d\n", i ));
555
556                 } else {
557                         i++;
558                 }
559         }
560
561         if (del_count) {
562                 /* the record may have shrunk a bit */
563                 dbuf.dsize -= del_count * sizeof(*shares);
564
565                 count = (ssize_t)data->u.num_share_mode_entries;
566
567                 /* store it back in the database */
568                 if (data->u.num_share_mode_entries == 0) {
569                         if (tdb_delete(tdb, locking_key(dev, inode)) == -1)
570                                 count = -1;
571                 } else {
572                         if (tdb_store(tdb, locking_key(dev, inode), dbuf, TDB_REPLACE) == -1)
573                                 count = -1;
574                 }
575         }
576         DEBUG(10,("del_share_entry: Remaining table.\n"));
577         print_share_mode_table((struct locking_data *)dbuf.dptr);
578         SAFE_FREE(dbuf.dptr);
579         return count;
580 }
581
582 /*******************************************************************
583  Del the share mode of a file for this process. Return the number
584  of entries left, and a memdup'ed copy of the entry deleted.
585 ********************************************************************/
586
587 ssize_t del_share_mode(files_struct *fsp, share_mode_entry **ppse)
588 {
589         share_mode_entry entry;
590
591         /*
592          * Fake up a share_mode_entry for comparisons.
593          */
594
595         fill_share_mode((char *)&entry, fsp, 0, 0);
596         return del_share_entry(fsp->dev, fsp->inode, &entry, ppse);
597 }
598
599 /*******************************************************************
600  Set the share mode of a file. Return False on fail, True on success.
601 ********************************************************************/
602
603 BOOL set_share_mode(files_struct *fsp, uint16 port, uint16 op_type)
604 {
605         TDB_DATA dbuf;
606         struct locking_data *data;
607         char *p=NULL;
608         int size;
609         BOOL ret = True;
610                 
611         /* read in the existing share modes if any */
612         dbuf = tdb_fetch(tdb, locking_key_fsp(fsp));
613         if (!dbuf.dptr) {
614                 size_t offset;
615                 /* we'll need to create a new record */
616                 pstring fname;
617
618                 pstrcpy(fname, fsp->conn->connectpath);
619                 pstrcat(fname, "/");
620                 pstrcat(fname, fsp->fsp_name);
621
622                 size = sizeof(*data) + sizeof(share_mode_entry) + strlen(fname) + 1;
623                 p = (char *)malloc(size);
624                 if (!p)
625                         return False;
626                 data = (struct locking_data *)p;
627                 data->u.num_share_mode_entries = 1;
628         
629                 DEBUG(10,("set_share_mode: creating entry for file %s. num_share_modes = 1\n",
630                         fsp->fsp_name ));
631
632                 offset = sizeof(*data) + sizeof(share_mode_entry);
633                 safe_strcpy(p + offset, fname, size - offset);
634                 fill_share_mode(p + sizeof(*data), fsp, port, op_type);
635                 dbuf.dptr = p;
636                 dbuf.dsize = size;
637                 if (tdb_store(tdb, locking_key_fsp(fsp), dbuf, TDB_REPLACE) == -1)
638                         ret = False;
639
640                 print_share_mode_table((struct locking_data *)p);
641
642                 SAFE_FREE(p);
643                 return ret;
644         }
645
646         /* we're adding to an existing entry - this is a bit fiddly */
647         data = (struct locking_data *)dbuf.dptr;
648
649         data->u.num_share_mode_entries++;
650         
651         DEBUG(10,("set_share_mode: adding entry for file %s. new num_share_modes = %d\n",
652                 fsp->fsp_name, data->u.num_share_mode_entries ));
653
654         size = dbuf.dsize + sizeof(share_mode_entry);
655         p = malloc(size);
656         if (!p) {
657                 SAFE_FREE(dbuf.dptr);
658                 return False;
659         }
660         memcpy(p, dbuf.dptr, sizeof(*data));
661         fill_share_mode(p + sizeof(*data), fsp, port, op_type);
662         memcpy(p + sizeof(*data) + sizeof(share_mode_entry), dbuf.dptr + sizeof(*data),
663                dbuf.dsize - sizeof(*data));
664         SAFE_FREE(dbuf.dptr);
665         dbuf.dptr = p;
666         dbuf.dsize = size;
667         if (tdb_store(tdb, locking_key_fsp(fsp), dbuf, TDB_REPLACE) == -1)
668                 ret = False;
669         print_share_mode_table((struct locking_data *)p);
670         SAFE_FREE(p);
671         return ret;
672 }
673
674 /*******************************************************************
675  A generic in-place modification call for share mode entries.
676 ********************************************************************/
677
678 static BOOL mod_share_mode( SMB_DEV_T dev, SMB_INO_T inode, share_mode_entry *entry,
679                            void (*mod_fn)(share_mode_entry *, SMB_DEV_T, SMB_INO_T, void *),
680                            void *param)
681 {
682         TDB_DATA dbuf;
683         struct locking_data *data;
684         int i;
685         share_mode_entry *shares;
686         BOOL need_store=False;
687         BOOL ret = True;
688
689         /* read in the existing share modes */
690         dbuf = tdb_fetch(tdb, locking_key(dev, inode));
691         if (!dbuf.dptr)
692                 return False;
693
694         data = (struct locking_data *)dbuf.dptr;
695         shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data));
696
697         /* find any with our pid and call the supplied function */
698         for (i=0;i<data->u.num_share_mode_entries;i++) {
699                 if (share_modes_identical(entry, &shares[i])) {
700                         mod_fn(&shares[i], dev, inode, param);
701                         need_store=True;
702                 }
703         }
704
705         /* if the mod fn was called then store it back */
706         if (need_store) {
707                 if (data->u.num_share_mode_entries == 0) {
708                         if (tdb_delete(tdb, locking_key(dev, inode)) == -1)
709                                 ret = False;
710                 } else {
711                         if (tdb_store(tdb, locking_key(dev, inode), dbuf, TDB_REPLACE) == -1)
712                                 ret = False;
713                 }
714         }
715
716         SAFE_FREE(dbuf.dptr);
717         return ret;
718 }
719
720 /*******************************************************************
721  Static function that actually does the work for the generic function
722  below.
723 ********************************************************************/
724
725 static void remove_share_oplock_fn(share_mode_entry *entry, SMB_DEV_T dev, SMB_INO_T inode, 
726                                    void *param)
727 {
728         DEBUG(10,("remove_share_oplock_fn: removing oplock info for entry dev=%x ino=%.0f\n",
729                   (unsigned int)dev, (double)inode ));
730         /* Delete the oplock info. */
731         entry->op_port = 0;
732         entry->op_type = NO_OPLOCK;
733 }
734
735 /*******************************************************************
736  Remove an oplock port and mode entry from a share mode.
737 ********************************************************************/
738
739 BOOL remove_share_oplock(files_struct *fsp)
740 {
741         share_mode_entry entry;
742         /*
743          * Fake up an entry for comparisons...
744          */
745         fill_share_mode((char *)&entry, fsp, 0, 0);
746         return mod_share_mode(fsp->dev, fsp->inode, &entry, remove_share_oplock_fn, NULL);
747 }
748
749 /*******************************************************************
750  Static function that actually does the work for the generic function
751  below.
752 ********************************************************************/
753
754 static void downgrade_share_oplock_fn(share_mode_entry *entry, SMB_DEV_T dev, SMB_INO_T inode, 
755                                    void *param)
756 {
757         DEBUG(10,("downgrade_share_oplock_fn: downgrading oplock info for entry dev=%x ino=%.0f\n",
758                   (unsigned int)dev, (double)inode ));
759         entry->op_type = LEVEL_II_OPLOCK;
760 }
761
762 /*******************************************************************
763  Downgrade a oplock type from exclusive to level II.
764 ********************************************************************/
765
766 BOOL downgrade_share_oplock(files_struct *fsp)
767 {
768         share_mode_entry entry;
769         /*
770          * Fake up an entry for comparisons...
771          */
772         fill_share_mode((char *)&entry, fsp, 0, 0);
773         return mod_share_mode(fsp->dev, fsp->inode, &entry, downgrade_share_oplock_fn, NULL);
774 }
775
776 /*******************************************************************
777  Get/Set the delete on close flag in a set of share modes.
778  Return False on fail, True on success.
779 ********************************************************************/
780
781 BOOL modify_delete_flag( SMB_DEV_T dev, SMB_INO_T inode, BOOL delete_on_close)
782 {
783         TDB_DATA dbuf;
784         struct locking_data *data;
785         int i;
786         share_mode_entry *shares;
787
788         /* read in the existing share modes */
789         dbuf = tdb_fetch(tdb, locking_key(dev, inode));
790         if (!dbuf.dptr)
791                 return False;
792
793         data = (struct locking_data *)dbuf.dptr;
794         shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data));
795
796         /* Set/Unset the delete on close element. */
797         for (i=0;i<data->u.num_share_mode_entries;i++,shares++) {
798                 shares->share_mode = (delete_on_close ?
799                             (shares->share_mode | DELETE_ON_CLOSE_FLAG) :
800                             (shares->share_mode & ~DELETE_ON_CLOSE_FLAG) );
801         }
802
803         /* store it back */
804         if (data->u.num_share_mode_entries) {
805                 if (tdb_store(tdb, locking_key(dev,inode), dbuf, TDB_REPLACE)==-1) {
806                         SAFE_FREE(dbuf.dptr);
807                         return False;
808                 }
809         }
810
811         SAFE_FREE(dbuf.dptr);
812         return True;
813 }
814
815 /****************************************************************************
816  Traverse the whole database with this function, calling traverse_callback
817  on each share mode
818 ****************************************************************************/
819
820 static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, 
821                        void* state)
822 {
823         struct locking_data *data;
824         share_mode_entry *shares;
825         char *name;
826         int i;
827
828         SHAREMODE_FN(traverse_callback) = (SHAREMODE_FN_CAST())state;
829
830         data = (struct locking_data *)dbuf.dptr;
831         shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data));
832         name = dbuf.dptr + sizeof(*data) + data->u.num_share_mode_entries*sizeof(*shares);
833
834         for (i=0;i<data->u.num_share_mode_entries;i++) {
835                 traverse_callback(&shares[i], name);
836         }
837         return 0;
838 }
839
840 /*******************************************************************
841  Call the specified function on each entry under management by the
842  share mode system.
843 ********************************************************************/
844
845 int share_mode_forall(SHAREMODE_FN(fn))
846 {
847         if (!tdb)
848                 return 0;
849         return tdb_traverse(tdb, traverse_fn, (void*)fn);
850 }