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