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