e10e8a1fa0ffc9f232426f595d2c4d84fe702752
[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 struct locking_data {
44         union {
45                 int num_share_mode_entries;
46                 share_mode_entry dummy; /* Needed for alignment. */
47         } u;
48         /* the following two entries are implicit
49            share_mode_entry modes[num_share_mode_entries];
50            char file_name[];
51         */
52 };
53
54 /****************************************************************************
55  Debugging aid :-).
56 ****************************************************************************/
57
58 static const char *lock_type_name(enum brl_type lock_type)
59 {
60         return (lock_type == READ_LOCK) ? "READ" : "WRITE";
61 }
62
63 /****************************************************************************
64  Utility function called to see if a file region is locked.
65 ****************************************************************************/
66
67 BOOL is_locked(files_struct *fsp,connection_struct *conn,
68                SMB_BIG_UINT count,SMB_BIG_UINT offset, 
69                enum brl_type lock_type)
70 {
71         int snum = SNUM(conn);
72         int strict_locking = lp_strict_locking(snum);
73         BOOL ret;
74         
75         if (count == 0)
76                 return(False);
77
78         if (!lp_locking(snum) || !strict_locking)
79                 return(False);
80
81         if (strict_locking == Auto) {
82                 if  (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && (lock_type == READ_LOCK || lock_type == WRITE_LOCK)) {
83                         DEBUG(10,("is_locked: optimisation - exclusive oplock on file %s\n", fsp->fsp_name ));
84                         ret = 0;
85                 } else if (LEVEL_II_OPLOCK_TYPE(fsp->oplock_type) && (lock_type == READ_LOCK)) {
86                         DEBUG(10,("is_locked: optimisation - level II oplock on file %s\n", fsp->fsp_name ));
87                         ret = 0;
88                 } else {
89                         ret = !brl_locktest(fsp->dev, fsp->inode, fsp->fnum,
90                                      global_smbpid, sys_getpid(), conn->cnum, 
91                                      offset, count, lock_type);
92                 }
93         } else {
94                 ret = !brl_locktest(fsp->dev, fsp->inode, fsp->fnum,
95                                 global_smbpid, sys_getpid(), conn->cnum,
96                                 offset, count, lock_type);
97         }
98
99         DEBUG(10,("is_locked: brl start=%.0f len=%.0f %s for file %s\n",
100                         (double)offset, (double)count, ret ? "locked" : "unlocked",
101                         fsp->fsp_name ));
102
103         /*
104          * There is no lock held by an SMB daemon, check to
105          * see if there is a POSIX lock from a UNIX or NFS process.
106          */
107
108         if(!ret && lp_posix_locking(snum)) {
109                 ret = is_posix_locked(fsp, offset, count, lock_type);
110
111                 DEBUG(10,("is_locked: posix start=%.0f len=%.0f %s for file %s\n",
112                                 (double)offset, (double)count, ret ? "locked" : "unlocked",
113                                 fsp->fsp_name ));
114         }
115
116         return ret;
117 }
118
119 /****************************************************************************
120  Utility function called by locking requests.
121 ****************************************************************************/
122
123 static NTSTATUS do_lock(files_struct *fsp,connection_struct *conn, uint16 lock_pid,
124                  SMB_BIG_UINT count,SMB_BIG_UINT offset,enum brl_type lock_type, BOOL *my_lock_ctx)
125 {
126         NTSTATUS status = NT_STATUS_LOCK_NOT_GRANTED;
127
128         if (!lp_locking(SNUM(conn)))
129                 return NT_STATUS_OK;
130
131         /* NOTE! 0 byte long ranges ARE allowed and should be stored  */
132
133         DEBUG(10,("do_lock: lock type %s start=%.0f len=%.0f requested for file %s\n",
134                   lock_type_name(lock_type), (double)offset, (double)count, fsp->fsp_name ));
135
136         if (OPEN_FSP(fsp) && fsp->can_lock && (fsp->conn == conn)) {
137                 status = brl_lock(fsp->dev, fsp->inode, fsp->fnum,
138                                   lock_pid, sys_getpid(), conn->cnum, 
139                                   offset, count, 
140                                   lock_type, my_lock_ctx);
141
142                 if (NT_STATUS_IS_OK(status) && lp_posix_locking(SNUM(conn))) {
143
144                         /*
145                          * Try and get a POSIX lock on this range.
146                          * Note that this is ok if it is a read lock
147                          * overlapping on a different fd. JRA.
148                          */
149
150                         if (!set_posix_lock(fsp, offset, count, lock_type)) {
151                                 if (errno == EACCES || errno == EAGAIN)
152                                         status = NT_STATUS_FILE_LOCK_CONFLICT;
153                                 else
154                                         status = map_nt_error_from_unix(errno);
155
156                                 /*
157                                  * We failed to map - we must now remove the brl
158                                  * lock entry.
159                                  */
160                                 (void)brl_unlock(fsp->dev, fsp->inode, fsp->fnum,
161                                                                 lock_pid, sys_getpid(), conn->cnum, 
162                                                                 offset, count, False,
163                                                                 NULL, NULL);
164                         }
165                 }
166         }
167
168         return status;
169 }
170
171 /****************************************************************************
172  Utility function called by locking requests. This is *DISGUSTING*. It also
173  appears to be "What Windows Does" (tm). Andrew, ever wonder why Windows 2000
174  is so slow on the locking tests...... ? This is the reason. Much though I hate
175  it, we need this. JRA.
176 ****************************************************************************/
177
178 NTSTATUS do_lock_spin(files_struct *fsp,connection_struct *conn, uint16 lock_pid,
179                  SMB_BIG_UINT count,SMB_BIG_UINT offset,enum brl_type lock_type, BOOL *my_lock_ctx)
180 {
181         int j, maxj = lp_lock_spin_count();
182         int sleeptime = lp_lock_sleep_time();
183         NTSTATUS status, ret;
184
185         if (maxj <= 0)
186                 maxj = 1;
187
188         ret = NT_STATUS_OK; /* to keep dumb compilers happy */
189
190         for (j = 0; j < maxj; j++) {
191                 status = do_lock(fsp, conn, lock_pid, count, offset, lock_type, my_lock_ctx);
192                 if (!NT_STATUS_EQUAL(status, NT_STATUS_LOCK_NOT_GRANTED) &&
193                     !NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
194                         return status;
195                 }
196                 /* if we do fail then return the first error code we got */
197                 if (j == 0) {
198                         ret = status;
199                         /* Don't spin if we blocked ourselves. */
200                         if (*my_lock_ctx)
201                                 return ret;
202                 }
203                 if (sleeptime)
204                         sys_usleep(sleeptime);
205         }
206         return ret;
207 }
208
209 /* Struct passed to brl_unlock. */
210 struct posix_unlock_data_struct {
211         files_struct *fsp;
212         SMB_BIG_UINT offset;
213         SMB_BIG_UINT count;
214 };
215
216 /****************************************************************************
217  Function passed to brl_unlock to allow POSIX unlock to be done first.
218 ****************************************************************************/
219
220 static void posix_unlock(void *pre_data)
221 {
222         struct posix_unlock_data_struct *pdata = (struct posix_unlock_data_struct *)pre_data;
223
224         if (lp_posix_locking(SNUM(pdata->fsp->conn)))
225                 release_posix_lock(pdata->fsp, pdata->offset, pdata->count);
226 }
227
228 /****************************************************************************
229  Utility function called by unlocking requests.
230 ****************************************************************************/
231
232 NTSTATUS do_unlock(files_struct *fsp,connection_struct *conn, uint16 lock_pid,
233                    SMB_BIG_UINT count,SMB_BIG_UINT offset)
234 {
235         BOOL ok = False;
236         struct posix_unlock_data_struct posix_data;
237         
238         if (!lp_locking(SNUM(conn)))
239                 return NT_STATUS_OK;
240         
241         if (!OPEN_FSP(fsp) || !fsp->can_lock || (fsp->conn != conn)) {
242                 return NT_STATUS_INVALID_HANDLE;
243         }
244         
245         DEBUG(10,("do_unlock: unlock start=%.0f len=%.0f requested for file %s\n",
246                   (double)offset, (double)count, fsp->fsp_name ));
247
248         /*
249          * Remove the existing lock record from the tdb lockdb
250          * before looking at POSIX locks. If this record doesn't
251          * match then don't bother looking to remove POSIX locks.
252          */
253
254         posix_data.fsp = fsp;
255         posix_data.offset = offset;
256         posix_data.count = count;
257
258         ok = brl_unlock(fsp->dev, fsp->inode, fsp->fnum,
259                         lock_pid, sys_getpid(), conn->cnum, offset, count,
260                         False, posix_unlock, (void *)&posix_data);
261    
262         if (!ok) {
263                 DEBUG(10,("do_unlock: returning ERRlock.\n" ));
264                 return NT_STATUS_RANGE_NOT_LOCKED;
265         }
266         return NT_STATUS_OK;
267 }
268
269 /****************************************************************************
270  Remove any locks on this fd. Called from file_close().
271 ****************************************************************************/
272
273 void locking_close_file(files_struct *fsp)
274 {
275         pid_t pid = sys_getpid();
276
277         if (!lp_locking(SNUM(fsp->conn)))
278                 return;
279
280         /*
281          * Just release all the brl locks, no need to release individually.
282          */
283
284         brl_close(fsp->dev, fsp->inode, pid, fsp->conn->cnum, fsp->fnum);
285
286         if(lp_posix_locking(SNUM(fsp->conn))) {
287
288                 /* 
289                  * Release all the POSIX locks.
290                  */
291                 posix_locking_close_file(fsp);
292
293         }
294 }
295
296 /****************************************************************************
297  Initialise the locking functions.
298 ****************************************************************************/
299
300 static int open_read_only;
301
302 BOOL locking_init(int read_only)
303 {
304         brl_init(read_only);
305
306         if (tdb)
307                 return True;
308
309         tdb = tdb_open_log(lock_path("locking.tdb"), 
310                        0, TDB_DEFAULT|(read_only?0x0:TDB_CLEAR_IF_FIRST), 
311                        read_only?O_RDONLY:O_RDWR|O_CREAT,
312                        0644);
313
314         if (!tdb) {
315                 DEBUG(0,("ERROR: Failed to initialise locking database\n"));
316                 return False;
317         }
318         
319         if (!posix_locking_init(read_only))
320                 return False;
321
322         open_read_only = read_only;
323
324         return True;
325 }
326
327 /*******************************************************************
328  Deinitialize the share_mode management.
329 ******************************************************************/
330
331 BOOL locking_end(void)
332 {
333
334         brl_shutdown(open_read_only);
335         if (tdb) {
336
337                 if (tdb_close(tdb) != 0)
338                         return False;
339         }
340
341         return True;
342 }
343
344 /*******************************************************************
345  Form a static locking key for a dev/inode pair.
346 ******************************************************************/
347
348 static TDB_DATA locking_key(SMB_DEV_T dev, SMB_INO_T inode)
349 {
350         static struct locking_key key;
351         TDB_DATA kbuf;
352
353         memset(&key, '\0', sizeof(key));
354         key.dev = dev;
355         key.inode = inode;
356         kbuf.dptr = (char *)&key;
357         kbuf.dsize = sizeof(key);
358         return kbuf;
359 }
360
361 static TDB_DATA locking_key_fsp(files_struct *fsp)
362 {
363         return locking_key(fsp->dev, fsp->inode);
364 }
365
366 /*******************************************************************
367  Lock a hash bucket entry.
368 ******************************************************************/
369
370 BOOL lock_share_entry(connection_struct *conn,
371                       SMB_DEV_T dev, SMB_INO_T inode)
372 {
373         return tdb_chainlock(tdb, locking_key(dev, inode)) == 0;
374 }
375
376 /*******************************************************************
377  Unlock a hash bucket entry.
378 ******************************************************************/
379
380 void unlock_share_entry(connection_struct *conn,
381                         SMB_DEV_T dev, SMB_INO_T inode)
382 {
383         tdb_chainunlock(tdb, locking_key(dev, inode));
384 }
385
386 /*******************************************************************
387  Lock a hash bucket entry. use a fsp for convenience
388 ******************************************************************/
389
390 BOOL lock_share_entry_fsp(files_struct *fsp)
391 {
392         return tdb_chainlock(tdb, locking_key(fsp->dev, fsp->inode)) == 0;
393 }
394
395 /*******************************************************************
396  Unlock a hash bucket entry.
397 ******************************************************************/
398
399 void unlock_share_entry_fsp(files_struct *fsp)
400 {
401         tdb_chainunlock(tdb, locking_key(fsp->dev, fsp->inode));
402 }
403
404 /*******************************************************************
405  Print out a share mode.
406 ********************************************************************/
407
408 char *share_mode_str(int num, share_mode_entry *e)
409 {
410         static pstring share_str;
411
412         slprintf(share_str, sizeof(share_str)-1, "share_mode_entry[%d]: \
413 pid = %lu, share_mode = 0x%x, desired_access = 0x%x, port = 0x%x, type= 0x%x, file_id = %lu, dev = 0x%x, inode = %.0f",
414         num, (unsigned long)e->pid, e->share_mode, (unsigned int)e->desired_access, e->op_port, e->op_type, e->share_file_id,
415         (unsigned int)e->dev, (double)e->inode );
416
417         return share_str;
418 }
419
420 /*******************************************************************
421  Print out a share mode table.
422 ********************************************************************/
423
424 static void print_share_mode_table(struct locking_data *data)
425 {
426         int num_share_modes = data->u.num_share_mode_entries;
427         share_mode_entry *shares = (share_mode_entry *)(data + 1);
428         int i;
429
430         for (i = 0; i < num_share_modes; i++) {
431                 share_mode_entry *entry_p = &shares[i];
432                 DEBUG(10,("print_share_mode_table: %s\n", share_mode_str(i, entry_p) ));
433         }
434 }
435
436 /*******************************************************************
437  Get all share mode entries for a dev/inode pair.
438 ********************************************************************/
439
440 int get_share_modes(connection_struct *conn, 
441                     SMB_DEV_T dev, SMB_INO_T inode, 
442                     share_mode_entry **pp_shares)
443 {
444         TDB_DATA dbuf;
445         struct locking_data *data;
446         int num_share_modes;
447         share_mode_entry *shares = NULL;
448         TDB_DATA key = locking_key(dev, inode);
449         *pp_shares = NULL;
450
451         dbuf = tdb_fetch(tdb, key);
452         if (!dbuf.dptr)
453                 return 0;
454
455         data = (struct locking_data *)dbuf.dptr;
456         num_share_modes = data->u.num_share_mode_entries;
457         if(num_share_modes) {
458                 pstring fname;
459                 int i;
460                 int del_count = 0;
461
462                 shares = (share_mode_entry *)memdup(dbuf.dptr + sizeof(*data),  
463                                                 num_share_modes * sizeof(share_mode_entry));
464
465                 if (!shares) {
466                         SAFE_FREE(dbuf.dptr);
467                         return 0;
468                 }
469
470                 /* Save off the associated filename. */
471                 pstrcpy(fname, dbuf.dptr + sizeof(*data) + num_share_modes * sizeof(share_mode_entry));
472
473                 /*
474                  * Ensure that each entry has a real process attached.
475                  */
476
477                 for (i = 0; i < num_share_modes; ) {
478                         share_mode_entry *entry_p = &shares[i];
479                         if (process_exists(entry_p->pid)) {
480                                 DEBUG(10,("get_share_modes: %s\n", share_mode_str(i, entry_p) ));
481                                 i++;
482                         } else {
483                                 DEBUG(10,("get_share_modes: deleted %s\n", share_mode_str(i, entry_p) ));
484                                 if (num_share_modes - i - 1 > 0) {
485                                         memcpy( &shares[i], &shares[i+1],
486                                                 sizeof(share_mode_entry) * (num_share_modes - i - 1));
487                                 }
488                                 num_share_modes--;
489                                 del_count++;
490                         }
491                 }
492
493                 /* Did we delete any ? If so, re-store in tdb. */
494                 if (del_count) {
495                         data->u.num_share_mode_entries = num_share_modes;
496                         
497                         if (num_share_modes) {
498                                 memcpy(dbuf.dptr + sizeof(*data), shares,
499                                                 num_share_modes * sizeof(share_mode_entry));
500                                 /* Append the filename. */
501                                 pstrcpy(dbuf.dptr + sizeof(*data) + num_share_modes * sizeof(share_mode_entry), fname);
502                         }
503
504                         /* The record has shrunk a bit */
505                         dbuf.dsize -= del_count * sizeof(share_mode_entry);
506
507                         if (data->u.num_share_mode_entries == 0) {
508                                 if (tdb_delete(tdb, key) == -1) {
509                                         SAFE_FREE(shares);
510                                         SAFE_FREE(dbuf.dptr);
511                                         return 0;
512                                 }
513                         } else {
514                                 if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1) {
515                                         SAFE_FREE(shares);
516                                         SAFE_FREE(dbuf.dptr);
517                                         return 0;
518                                 }
519                         }
520                 }
521         }
522
523         SAFE_FREE(dbuf.dptr);
524         *pp_shares = shares;
525         return num_share_modes;
526 }
527
528 /*******************************************************************
529  Fill a share mode entry.
530 ********************************************************************/
531
532 static void fill_share_mode(char *p, files_struct *fsp, uint16 port, uint16 op_type)
533 {
534         share_mode_entry *e = (share_mode_entry *)p;
535         void *x = &e->time; /* Needed to force alignment. p may not be aligned.... */
536
537         memset(e, '\0', sizeof(share_mode_entry));
538         e->pid = sys_getpid();
539         e->share_mode = fsp->share_mode;
540         e->desired_access = fsp->desired_access;
541         e->op_port = port;
542         e->op_type = op_type;
543         memcpy(x, &fsp->open_time, sizeof(struct timeval));
544         e->share_file_id = fsp->file_id;
545         e->dev = fsp->dev;
546         e->inode = fsp->inode;
547 }
548
549 /*******************************************************************
550  Check if two share mode entries are identical, ignoring oplock 
551  and port info and desired_access.
552 ********************************************************************/
553
554 BOOL share_modes_identical( share_mode_entry *e1, share_mode_entry *e2)
555 {
556 #if 1 /* JRA PARANOIA TEST - REMOVE LATER */
557         if (e1->pid == e2->pid &&
558                 e1->share_file_id == e2->share_file_id &&
559                 e1->dev == e2->dev &&
560                 e1->inode == e2->inode &&
561                 (e1->share_mode & ~DELETE_ON_CLOSE_FLAG) != (e2->share_mode & ~DELETE_ON_CLOSE_FLAG)) {
562                         DEBUG(0,("PANIC: share_modes_identical: share_mode missmatch (e1 = %u, e2 = %u). Logic error.\n",
563                                 (unsigned int)(e1->share_mode & ~DELETE_ON_CLOSE_FLAG),
564                                 (unsigned int)(e2->share_mode & ~DELETE_ON_CLOSE_FLAG) ));
565                 smb_panic("PANIC: share_modes_identical logic error.\n");
566         }
567 #endif
568
569         return (e1->pid == e2->pid &&
570                 (e1->share_mode & ~DELETE_ON_CLOSE_FLAG) == (e2->share_mode & ~DELETE_ON_CLOSE_FLAG) &&
571                 e1->dev == e2->dev &&
572                 e1->inode == e2->inode &&
573                 e1->share_file_id == e2->share_file_id );
574 }
575
576 /*******************************************************************
577  Delete a specific share mode. Return the number
578  of entries left, and a memdup'ed copy of the entry deleted (if required).
579  Ignore if no entry deleted.
580 ********************************************************************/
581
582 ssize_t del_share_entry( SMB_DEV_T dev, SMB_INO_T inode,
583                         share_mode_entry *entry, share_mode_entry **ppse)
584 {
585         TDB_DATA dbuf;
586         struct locking_data *data;
587         int i, del_count=0;
588         share_mode_entry *shares;
589         ssize_t count = 0;
590         TDB_DATA key = locking_key(dev, inode);
591
592         if (ppse)
593                 *ppse = NULL;
594
595         /* read in the existing share modes */
596         dbuf = tdb_fetch(tdb, key);
597         if (!dbuf.dptr)
598                 return -1;
599
600         data = (struct locking_data *)dbuf.dptr;
601         shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data));
602
603         /*
604          * Find any with this pid and delete it
605          * by overwriting with the rest of the data 
606          * from the record.
607          */
608
609         DEBUG(10,("del_share_entry: num_share_modes = %d\n", data->u.num_share_mode_entries ));
610
611         for (i=0;i<data->u.num_share_mode_entries;) {
612                 if (share_modes_identical(&shares[i], entry)) {
613                         DEBUG(10,("del_share_entry: deleted %s\n",
614                                 share_mode_str(i, &shares[i]) ));
615                         if (ppse)
616                                 *ppse = memdup(&shares[i], sizeof(*shares));
617                         data->u.num_share_mode_entries--;
618                         if ((dbuf.dsize - (sizeof(*data) + (i+1)*sizeof(*shares))) > 0) {
619                                 memmove(&shares[i], &shares[i+1], 
620                                         dbuf.dsize - (sizeof(*data) + (i+1)*sizeof(*shares)));
621                         }
622                         del_count++;
623
624                         DEBUG(10,("del_share_entry: deleting entry %d\n", i ));
625
626                 } else {
627                         i++;
628                 }
629         }
630
631         if (del_count) {
632                 /* the record may have shrunk a bit */
633                 dbuf.dsize -= del_count * sizeof(*shares);
634
635                 count = (ssize_t)data->u.num_share_mode_entries;
636
637                 /* store it back in the database */
638                 if (data->u.num_share_mode_entries == 0) {
639                         if (tdb_delete(tdb, key) == -1)
640                                 count = -1;
641                 } else {
642                         if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1)
643                                 count = -1;
644                 }
645         }
646         DEBUG(10,("del_share_entry: Remaining table.\n"));
647         print_share_mode_table((struct locking_data *)dbuf.dptr);
648         SAFE_FREE(dbuf.dptr);
649         return count;
650 }
651
652 /*******************************************************************
653  Del the share mode of a file for this process. Return the number
654  of entries left, and a memdup'ed copy of the entry deleted.
655 ********************************************************************/
656
657 ssize_t del_share_mode(files_struct *fsp, share_mode_entry **ppse)
658 {
659         share_mode_entry entry;
660
661         /*
662          * Fake up a share_mode_entry for comparisons.
663          */
664
665         fill_share_mode((char *)&entry, fsp, 0, 0);
666         return del_share_entry(fsp->dev, fsp->inode, &entry, ppse);
667 }
668
669 /*******************************************************************
670  Set the share mode of a file. Return False on fail, True on success.
671 ********************************************************************/
672
673 BOOL set_share_mode(files_struct *fsp, uint16 port, uint16 op_type)
674 {
675         TDB_DATA dbuf;
676         struct locking_data *data;
677         char *p=NULL;
678         int size;
679         TDB_DATA key = locking_key_fsp(fsp);
680         BOOL ret = True;
681                 
682         /* read in the existing share modes if any */
683         dbuf = tdb_fetch(tdb, key);
684         if (!dbuf.dptr) {
685                 size_t offset;
686                 /* we'll need to create a new record */
687                 pstring fname;
688
689                 pstrcpy(fname, fsp->conn->connectpath);
690                 pstrcat(fname, "/");
691                 pstrcat(fname, fsp->fsp_name);
692
693                 size = sizeof(*data) + sizeof(share_mode_entry) + strlen(fname) + 1;
694                 p = (char *)SMB_MALLOC(size);
695                 if (!p)
696                         return False;
697                 data = (struct locking_data *)p;
698                 data->u.num_share_mode_entries = 1;
699         
700                 DEBUG(10,("set_share_mode: creating entry for file %s. num_share_modes = 1\n",
701                         fsp->fsp_name ));
702
703                 offset = sizeof(*data) + sizeof(share_mode_entry);
704                 safe_strcpy(p + offset, fname, size - offset - 1);
705                 fill_share_mode(p + sizeof(*data), fsp, port, op_type);
706                 dbuf.dptr = p;
707                 dbuf.dsize = size;
708                 if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1)
709                         ret = False;
710
711                 print_share_mode_table((struct locking_data *)p);
712
713                 SAFE_FREE(p);
714                 return ret;
715         }
716
717         /* we're adding to an existing entry - this is a bit fiddly */
718         data = (struct locking_data *)dbuf.dptr;
719
720         data->u.num_share_mode_entries++;
721         
722         DEBUG(10,("set_share_mode: adding entry for file %s. new num_share_modes = %d\n",
723                 fsp->fsp_name, data->u.num_share_mode_entries ));
724
725         size = dbuf.dsize + sizeof(share_mode_entry);
726         p = SMB_MALLOC(size);
727         if (!p) {
728                 SAFE_FREE(dbuf.dptr);
729                 return False;
730         }
731         memcpy(p, dbuf.dptr, sizeof(*data));
732         fill_share_mode(p + sizeof(*data), fsp, port, op_type);
733         memcpy(p + sizeof(*data) + sizeof(share_mode_entry), dbuf.dptr + sizeof(*data),
734                dbuf.dsize - sizeof(*data));
735         SAFE_FREE(dbuf.dptr);
736         dbuf.dptr = p;
737         dbuf.dsize = size;
738         if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1)
739                 ret = False;
740         print_share_mode_table((struct locking_data *)p);
741         SAFE_FREE(p);
742         return ret;
743 }
744
745 /*******************************************************************
746  A generic in-place modification call for share mode entries.
747 ********************************************************************/
748
749 static BOOL mod_share_mode( SMB_DEV_T dev, SMB_INO_T inode, share_mode_entry *entry,
750                            void (*mod_fn)(share_mode_entry *, SMB_DEV_T, SMB_INO_T, void *),
751                            void *param)
752 {
753         TDB_DATA dbuf;
754         struct locking_data *data;
755         int i;
756         share_mode_entry *shares;
757         BOOL need_store=False;
758         BOOL ret = True;
759         TDB_DATA key = locking_key(dev, inode);
760
761         /* read in the existing share modes */
762         dbuf = tdb_fetch(tdb, key);
763         if (!dbuf.dptr)
764                 return False;
765
766         data = (struct locking_data *)dbuf.dptr;
767         shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data));
768
769         /* find any with our pid and call the supplied function */
770         for (i=0;i<data->u.num_share_mode_entries;i++) {
771                 if (share_modes_identical(entry, &shares[i])) {
772                         mod_fn(&shares[i], dev, inode, param);
773                         need_store=True;
774                 }
775         }
776
777         /* if the mod fn was called then store it back */
778         if (need_store) {
779                 if (data->u.num_share_mode_entries == 0) {
780                         if (tdb_delete(tdb, key) == -1)
781                                 ret = False;
782                 } else {
783                         if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1)
784                                 ret = False;
785                 }
786         }
787
788         SAFE_FREE(dbuf.dptr);
789         return ret;
790 }
791
792 /*******************************************************************
793  Static function that actually does the work for the generic function
794  below.
795 ********************************************************************/
796
797 static void remove_share_oplock_fn(share_mode_entry *entry, SMB_DEV_T dev, SMB_INO_T inode, 
798                                    void *param)
799 {
800         DEBUG(10,("remove_share_oplock_fn: removing oplock info for entry dev=%x ino=%.0f\n",
801                   (unsigned int)dev, (double)inode ));
802         /* Delete the oplock info. */
803         entry->op_port = 0;
804         entry->op_type = NO_OPLOCK;
805 }
806
807 /*******************************************************************
808  Remove an oplock port and mode entry from a share mode.
809 ********************************************************************/
810
811 BOOL remove_share_oplock(files_struct *fsp)
812 {
813         share_mode_entry entry;
814         /*
815          * Fake up an entry for comparisons...
816          */
817         fill_share_mode((char *)&entry, fsp, 0, 0);
818         return mod_share_mode(fsp->dev, fsp->inode, &entry, remove_share_oplock_fn, NULL);
819 }
820
821 /*******************************************************************
822  Static function that actually does the work for the generic function
823  below.
824 ********************************************************************/
825
826 static void downgrade_share_oplock_fn(share_mode_entry *entry, SMB_DEV_T dev, SMB_INO_T inode, 
827                                    void *param)
828 {
829         DEBUG(10,("downgrade_share_oplock_fn: downgrading oplock info for entry dev=%x ino=%.0f\n",
830                   (unsigned int)dev, (double)inode ));
831         entry->op_type = LEVEL_II_OPLOCK;
832 }
833
834 /*******************************************************************
835  Downgrade a oplock type from exclusive to level II.
836 ********************************************************************/
837
838 BOOL downgrade_share_oplock(files_struct *fsp)
839 {
840         share_mode_entry entry;
841         /*
842          * Fake up an entry for comparisons...
843          */
844         fill_share_mode((char *)&entry, fsp, 0, 0);
845         return mod_share_mode(fsp->dev, fsp->inode, &entry, downgrade_share_oplock_fn, NULL);
846 }
847
848 /*******************************************************************
849  Get/Set the delete on close flag in a set of share modes.
850  Return False on fail, True on success.
851 ********************************************************************/
852
853 BOOL modify_delete_flag( SMB_DEV_T dev, SMB_INO_T inode, BOOL delete_on_close)
854 {
855         TDB_DATA dbuf;
856         struct locking_data *data;
857         int i;
858         share_mode_entry *shares;
859         TDB_DATA key = locking_key(dev, inode);
860
861         /* read in the existing share modes */
862         dbuf = tdb_fetch(tdb, key);
863         if (!dbuf.dptr)
864                 return False;
865
866         data = (struct locking_data *)dbuf.dptr;
867         shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data));
868
869         /* Set/Unset the delete on close element. */
870         for (i=0;i<data->u.num_share_mode_entries;i++,shares++) {
871                 shares->share_mode = (delete_on_close ?
872                             (shares->share_mode | DELETE_ON_CLOSE_FLAG) :
873                             (shares->share_mode & ~DELETE_ON_CLOSE_FLAG) );
874         }
875
876         /* store it back */
877         if (data->u.num_share_mode_entries) {
878                 if (tdb_store(tdb, key, dbuf, TDB_REPLACE)==-1) {
879                         SAFE_FREE(dbuf.dptr);
880                         return False;
881                 }
882         }
883
884         SAFE_FREE(dbuf.dptr);
885         return True;
886 }
887
888 /*******************************************************************
889  Print out a deferred open entry.
890 ********************************************************************/
891
892 char *deferred_open_str(int num, deferred_open_entry *e)
893 {
894         static pstring de_str;
895
896         slprintf(de_str, sizeof(de_str)-1, "deferred_open_entry[%d]: \
897 pid = %lu, mid = %u, dev = 0x%x, inode = %.0f, port = %u, time = [%u.%06u]",
898                 num, (unsigned long)e->pid, (unsigned int)e->mid, (unsigned int)e->dev, (double)e->inode,
899                 (unsigned int)e->port,
900                 (unsigned int)e->time.tv_sec, (unsigned int)e->time.tv_usec );
901
902         return de_str;
903 }
904
905 /* Internal data structures for deferred opens... */
906
907 struct de_locking_key {
908         char name[4];
909         SMB_DEV_T dev;
910         SMB_INO_T inode;
911 };
912
913 struct deferred_open_data {
914         union {
915                 int num_deferred_open_entries;
916                 deferred_open_entry dummy; /* Needed for alignment. */
917         } u;
918         /* the following two entries are implicit
919            deferred_open_entry de_entries[num_deferred_open_entries];
920            char file_name[];
921         */
922 };
923
924 /*******************************************************************
925  Print out a deferred open table.
926 ********************************************************************/
927
928 static void print_deferred_open_table(struct deferred_open_data *data)
929 {
930         int num_de_entries = data->u.num_deferred_open_entries;
931         deferred_open_entry *de_entries = (deferred_open_entry *)(data + 1);
932         int i;
933
934         for (i = 0; i < num_de_entries; i++) {
935                 deferred_open_entry *entry_p = &de_entries[i];
936                 DEBUG(10,("print_deferred_open_table: %s\n", deferred_open_str(i, entry_p) ));
937         }
938 }
939
940
941 /*******************************************************************
942  Form a static deferred open locking key for a dev/inode pair.
943 ******************************************************************/
944
945 static TDB_DATA deferred_open_locking_key(SMB_DEV_T dev, SMB_INO_T inode)
946 {
947         static struct de_locking_key key;
948         TDB_DATA kbuf;
949
950         memset(&key, '\0', sizeof(key));
951         memcpy(&key.name[0], "DOE", 4);
952         key.dev = dev;
953         key.inode = inode;
954         kbuf.dptr = (char *)&key;
955         kbuf.dsize = sizeof(key);
956         return kbuf;
957 }
958
959 /*******************************************************************
960  Get all deferred open entries for a dev/inode pair.
961 ********************************************************************/
962
963 int get_deferred_opens(connection_struct *conn, 
964                     SMB_DEV_T dev, SMB_INO_T inode, 
965                     deferred_open_entry **pp_de_entries)
966 {
967         TDB_DATA dbuf;
968         struct deferred_open_data *data;
969         int num_de_entries;
970         deferred_open_entry *de_entries = NULL;
971         TDB_DATA key = deferred_open_locking_key(dev, inode);
972
973         *pp_de_entries = NULL;
974
975         dbuf = tdb_fetch(tdb, key);
976         if (!dbuf.dptr)
977                 return 0;
978
979         data = (struct deferred_open_data *)dbuf.dptr;
980         num_de_entries = data->u.num_deferred_open_entries;
981         if(num_de_entries) {
982                 pstring fname;
983                 int i;
984                 int del_count = 0;
985
986                 de_entries = (deferred_open_entry *)memdup(dbuf.dptr + sizeof(*data),   
987                                                 num_de_entries * sizeof(deferred_open_entry));
988
989                 if (!de_entries) {
990                         SAFE_FREE(dbuf.dptr);
991                         return 0;
992                 }
993
994                 /* Save off the associated filename. */
995                 pstrcpy(fname, dbuf.dptr + sizeof(*data) + num_de_entries * sizeof(deferred_open_entry));
996
997                 /*
998                  * Ensure that each entry has a real process attached.
999                  */
1000
1001                 for (i = 0; i < num_de_entries; ) {
1002                         deferred_open_entry *entry_p = &de_entries[i];
1003                         if (process_exists(entry_p->pid)) {
1004                                 DEBUG(10,("get_deferred_opens: %s\n", deferred_open_str(i, entry_p) ));
1005                                 i++;
1006                         } else {
1007                                 DEBUG(10,("get_deferred_opens: deleted %s\n", deferred_open_str(i, entry_p) ));
1008                                 if (num_de_entries - i - 1 > 0) {
1009                                         memcpy( &de_entries[i], &de_entries[i+1],
1010                                                 sizeof(deferred_open_entry) * (num_de_entries - i - 1));
1011                                 }
1012                                 num_de_entries--;
1013                                 del_count++;
1014                         }
1015                 }
1016
1017                 /* Did we delete any ? If so, re-store in tdb. */
1018                 if (del_count) {
1019                         data->u.num_deferred_open_entries = num_de_entries;
1020                         
1021                         if (num_de_entries) {
1022                                 memcpy(dbuf.dptr + sizeof(*data), de_entries,
1023                                                 num_de_entries * sizeof(deferred_open_entry));
1024                                 /* Append the filename. */
1025                                 pstrcpy(dbuf.dptr + sizeof(*data) + num_de_entries * sizeof(deferred_open_entry), fname);
1026                         }
1027
1028                         /* The record has shrunk a bit */
1029                         dbuf.dsize -= del_count * sizeof(deferred_open_entry);
1030
1031                         if (data->u.num_deferred_open_entries == 0) {
1032                                 if (tdb_delete(tdb, key) == -1) {
1033                                         SAFE_FREE(de_entries);
1034                                         SAFE_FREE(dbuf.dptr);
1035                                         return 0;
1036                                 }
1037                         } else {
1038                                 if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1) {
1039                                         SAFE_FREE(de_entries);
1040                                         SAFE_FREE(dbuf.dptr);
1041                                         return 0;
1042                                 }
1043                         }
1044                 }
1045         }
1046
1047         SAFE_FREE(dbuf.dptr);
1048         *pp_de_entries = de_entries;
1049         return num_de_entries;
1050 }
1051
1052 /*******************************************************************
1053  Check if two deferred open entries are identical.
1054 ********************************************************************/
1055
1056 static BOOL deferred_open_entries_identical( deferred_open_entry *e1, deferred_open_entry *e2)
1057 {
1058         return (e1->pid == e2->pid &&
1059                 e1->mid == e2->mid &&
1060                 e1->port == e2->port &&
1061                 e1->dev == e2->dev &&
1062                 e1->inode == e2->inode &&
1063                 e1->time.tv_sec == e2->time.tv_sec &&
1064                 e1->time.tv_usec == e2->time.tv_usec);
1065 }
1066
1067 /*******************************************************************
1068  Delete a specific deferred open entry.
1069  Ignore if no entry deleted.
1070 ********************************************************************/
1071
1072 BOOL delete_deferred_open_entry(deferred_open_entry *entry)
1073 {
1074         TDB_DATA dbuf;
1075         struct deferred_open_data *data;
1076         int i, del_count=0;
1077         deferred_open_entry *de_entries;
1078         BOOL ret = True;
1079         TDB_DATA key = deferred_open_locking_key(entry->dev, entry->inode);
1080
1081         /* read in the existing share modes */
1082         dbuf = tdb_fetch(tdb, key);
1083         if (!dbuf.dptr)
1084                 return -1;
1085
1086         data = (struct deferred_open_data *)dbuf.dptr;
1087         de_entries = (deferred_open_entry *)(dbuf.dptr + sizeof(*data));
1088
1089         /*
1090          * Find any with this pid and delete it
1091          * by overwriting with the rest of the data 
1092          * from the record.
1093          */
1094
1095         DEBUG(10,("delete_deferred_open_entry: num_deferred_open_entries = %d\n",
1096                 data->u.num_deferred_open_entries ));
1097
1098         for (i=0;i<data->u.num_deferred_open_entries;) {
1099                 if (deferred_open_entries_identical(&de_entries[i], entry)) {
1100                         DEBUG(10,("delete_deferred_open_entry: deleted %s\n",
1101                                 deferred_open_str(i, &de_entries[i]) ));
1102
1103                         data->u.num_deferred_open_entries--;
1104                         if ((dbuf.dsize - (sizeof(*data) + (i+1)*sizeof(*de_entries))) > 0) {
1105                                 memmove(&de_entries[i], &de_entries[i+1], 
1106                                         dbuf.dsize - (sizeof(*data) + (i+1)*sizeof(*de_entries)));
1107                         }
1108                         del_count++;
1109
1110                         DEBUG(10,("delete_deferred_open_entry: deleting entry %d\n", i ));
1111
1112                 } else {
1113                         i++;
1114                 }
1115         }
1116
1117         SMB_ASSERT(del_count == 0 || del_count == 1);
1118
1119         if (del_count) {
1120                 /* the record may have shrunk a bit */
1121                 dbuf.dsize -= del_count * sizeof(*de_entries);
1122
1123                 /* store it back in the database */
1124                 if (data->u.num_deferred_open_entries == 0) {
1125                         if (tdb_delete(tdb, key) == -1)
1126                                 ret = False;
1127                 } else {
1128                         if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1)
1129                                 ret = False;
1130                 }
1131         }
1132         DEBUG(10,("delete_deferred_open_entry: Remaining table.\n"));
1133         print_deferred_open_table((struct deferred_open_data*)dbuf.dptr);
1134         SAFE_FREE(dbuf.dptr);
1135         return ret;
1136 }
1137
1138 /*******************************************************************
1139  Fill a deferred open entry.
1140 ********************************************************************/
1141
1142 static void fill_deferred_open(char *p, uint16 mid, struct timeval *ptv, SMB_DEV_T dev, SMB_INO_T inode, uint16 port)
1143 {
1144         deferred_open_entry *e = (deferred_open_entry *)p;
1145         void *x = &e->time; /* Needed to force alignment. p may not be aligned.... */
1146
1147         memset(e, '\0', sizeof(deferred_open_entry));
1148         e->mid = mid;
1149         e->pid = sys_getpid();
1150         memcpy(x, ptv, sizeof(struct timeval));
1151         e->dev = dev;
1152         e->inode = inode;
1153         e->port = port;
1154 }
1155
1156 /*******************************************************************
1157  Add a deferred open record. Return False on fail, True on success.
1158 ********************************************************************/
1159
1160 BOOL add_deferred_open(uint16 mid, struct timeval *ptv, SMB_DEV_T dev, SMB_INO_T inode, uint16 port, const char *fname)
1161 {
1162         TDB_DATA dbuf;
1163         struct deferred_open_data *data;
1164         char *p=NULL;
1165         int size;
1166         TDB_DATA key = deferred_open_locking_key(dev, inode);
1167         BOOL ret = True;
1168                 
1169         /* read in the existing deferred open records if any */
1170         dbuf = tdb_fetch(tdb, key);
1171         if (!dbuf.dptr) {
1172                 size_t offset;
1173                 /* we'll need to create a new record */
1174
1175                 size = sizeof(*data) + sizeof(deferred_open_entry) + strlen(fname) + 1;
1176                 p = (char *)SMB_MALLOC(size);
1177                 if (!p)
1178                         return False;
1179                 data = (struct deferred_open_data *)p;
1180                 data->u.num_deferred_open_entries = 1;
1181         
1182                 DEBUG(10,("add_deferred_open: creating entry for file %s. num_deferred_open_entries = 1\n",
1183                         fname ));
1184
1185                 offset = sizeof(*data) + sizeof(deferred_open_entry);
1186                 safe_strcpy(p + offset, fname, size - offset - 1);
1187                 fill_deferred_open(p + sizeof(*data), mid, ptv, dev, inode, port);
1188                 dbuf.dptr = p;
1189                 dbuf.dsize = size;
1190                 if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1)
1191                         ret = False;
1192
1193                 print_deferred_open_table((struct deferred_open_data *)p);
1194
1195                 SAFE_FREE(p);
1196                 return ret;
1197         }
1198
1199         /* we're adding to an existing entry - this is a bit fiddly */
1200         data = (struct deferred_open_data *)dbuf.dptr;
1201
1202         data->u.num_deferred_open_entries++;
1203         
1204         DEBUG(10,("add_deferred_open: adding entry for file %s. new num_deferred_open_entries = %d\n",
1205                 fname, data->u.num_deferred_open_entries ));
1206
1207         size = dbuf.dsize + sizeof(deferred_open_entry);
1208         p = SMB_MALLOC(size);
1209         if (!p) {
1210                 SAFE_FREE(dbuf.dptr);
1211                 return False;
1212         }
1213         memcpy(p, dbuf.dptr, sizeof(*data));
1214         fill_deferred_open(p + sizeof(*data), mid, ptv, dev, inode, port);
1215         memcpy(p + sizeof(*data) + sizeof(deferred_open_entry), dbuf.dptr + sizeof(*data),
1216                dbuf.dsize - sizeof(*data));
1217         SAFE_FREE(dbuf.dptr);
1218         dbuf.dptr = p;
1219         dbuf.dsize = size;
1220         if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1)
1221                 ret = False;
1222         print_deferred_open_table((struct deferred_open_data *)p);
1223         SAFE_FREE(p);
1224         return ret;
1225 }
1226
1227 /****************************************************************************
1228  Traverse the whole database with this function, calling traverse_callback
1229  on each share mode
1230 ****************************************************************************/
1231
1232 static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, 
1233                        void* state)
1234 {
1235         struct locking_data *data;
1236         share_mode_entry *shares;
1237         char *name;
1238         int i;
1239
1240         SHAREMODE_FN(traverse_callback) = (SHAREMODE_FN_CAST())state;
1241
1242         /* Ensure this is a locking_key record. */
1243         if (kbuf.dsize != sizeof(struct locking_key))
1244                 return 0;
1245
1246         data = (struct locking_data *)dbuf.dptr;
1247         shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data));
1248         name = dbuf.dptr + sizeof(*data) + data->u.num_share_mode_entries*sizeof(*shares);
1249
1250         for (i=0;i<data->u.num_share_mode_entries;i++) {
1251                 traverse_callback(&shares[i], name);
1252         }
1253         return 0;
1254 }
1255
1256 /*******************************************************************
1257  Call the specified function on each entry under management by the
1258  share mode system.
1259 ********************************************************************/
1260
1261 int share_mode_forall(SHAREMODE_FN(fn))
1262 {
1263         if (!tdb)
1264                 return 0;
1265         return tdb_traverse(tdb, traverse_fn, (void*)fn);
1266 }