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