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