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