locking/posix.c: Fixed double-free nasty crash bug found by insure.
[kamenim/samba-autobuild/.git] / source3 / locking / posix.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 3.0
4    Locking functions
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    POSIX locking support. Jeremy Allison (jeremy@valinux.com), Apr. 2000.
24 */
25
26 #include "includes.h"
27 extern int DEBUGLEVEL;
28 extern int global_smbpid;
29
30 /*
31  * The POSIX locking database handle.
32  */
33
34 static TDB_CONTEXT *posix_lock_tdb;
35
36 /*
37  * The pending close database handle.
38  */
39
40 static TDB_CONTEXT *posix_pending_close_tdb;
41
42 /*
43  * The data in POSIX lock records is an unsorted linear array of these
44  * records.  It is unnecessary to store the count as tdb provides the
45  * size of the record.
46  */
47
48 struct posix_lock {
49         int fd;
50         SMB_OFF_T start;
51         SMB_OFF_T size;
52         int lock_type;
53 };
54
55 /*
56  * The data in POSIX pending close records is an unsorted linear array of int
57  * records.  It is unnecessary to store the count as tdb provides the
58  * size of the record.
59  */
60
61 /* The key used in both the POSIX databases. */
62
63 struct posix_lock_key {
64         SMB_DEV_T device;
65         SMB_INO_T inode;
66 }; 
67
68 /*******************************************************************
69  Form a static locking key for a dev/inode pair.
70 ******************************************************************/
71
72 static TDB_DATA locking_key(SMB_DEV_T dev, SMB_INO_T inode)
73 {
74         static struct posix_lock_key key;
75         TDB_DATA kbuf;
76         key.device = dev;
77         key.inode = inode;
78         kbuf.dptr = (char *)&key;
79         kbuf.dsize = sizeof(key);
80         return kbuf;
81 }
82
83 /*******************************************************************
84  Convenience function to get a key from an fsp.
85 ******************************************************************/
86
87 static TDB_DATA locking_key_fsp(files_struct *fsp)
88 {
89         return locking_key(fsp->dev, fsp->inode);
90 }
91
92 /****************************************************************************
93  Add an fd to the pending close tdb.
94 ****************************************************************************/
95
96 static BOOL add_fd_to_close_entry(files_struct *fsp)
97 {
98         TDB_DATA kbuf = locking_key_fsp(fsp);
99         TDB_DATA dbuf;
100
101         dbuf.dptr = NULL;
102
103         dbuf = tdb_fetch(posix_pending_close_tdb, kbuf);
104
105         dbuf.dptr = Realloc(dbuf.dptr, dbuf.dsize + sizeof(int));
106         if (!dbuf.dptr) {
107                 DEBUG(0,("add_fd_to_close_entry: Realloc fail !\n"));
108                 return False;
109         }
110         memcpy(dbuf.dptr + dbuf.dsize, &fsp->fd, sizeof(int));
111         dbuf.dsize += sizeof(int);
112
113         if (tdb_store(posix_pending_close_tdb, kbuf, dbuf, TDB_REPLACE) == -1) {
114                 DEBUG(0,("add_fd_to_close_entry: tdb_store fail !\n"));
115         }
116
117         free(dbuf.dptr);
118         return True;
119 }
120
121 /****************************************************************************
122  Remove all fd entries for a specific dev/inode pair from the tdb.
123 ****************************************************************************/
124
125 static void delete_close_entries(files_struct *fsp)
126 {
127         TDB_DATA kbuf = locking_key_fsp(fsp);
128
129         if (tdb_delete(posix_pending_close_tdb, kbuf) == -1)
130                 DEBUG(0,("delete_close_entries: tdb_delete fail !\n"));
131 }
132
133 /****************************************************************************
134  Get the array of POSIX pending close records for an open fsp. Caller must
135  free. Returns number of entries.
136 ****************************************************************************/
137
138 static size_t get_posix_pending_close_entries(files_struct *fsp, int **entries)
139 {
140         TDB_DATA kbuf = locking_key_fsp(fsp);
141         TDB_DATA dbuf;
142         size_t count = 0;
143
144         *entries = NULL;
145         dbuf.dptr = NULL;
146
147         dbuf = tdb_fetch(posix_pending_close_tdb, kbuf);
148
149     if (!dbuf.dptr) {
150                 return 0;
151         }
152
153         *entries = (int *)dbuf.dptr;
154         count = (size_t)(dbuf.dsize / sizeof(int));
155
156         return count;
157 }
158
159 /****************************************************************************
160  Get the array of POSIX locks for an fsp. Caller must free. Returns
161  number of entries.
162 ****************************************************************************/
163
164 static size_t get_posix_lock_entries(files_struct *fsp, struct posix_lock **entries)
165 {
166         TDB_DATA kbuf = locking_key_fsp(fsp);
167         TDB_DATA dbuf;
168         size_t count = 0;
169
170         *entries = NULL;
171
172         dbuf.dptr = NULL;
173
174         dbuf = tdb_fetch(posix_lock_tdb, kbuf);
175
176     if (!dbuf.dptr) {
177                 return 0;
178         }
179
180         *entries = (struct posix_lock *)dbuf.dptr;
181         count = (size_t)(dbuf.dsize / sizeof(struct posix_lock));
182
183         return count;
184 }
185
186 /****************************************************************************
187  Deal with pending closes needed by POSIX locking support.
188 ****************************************************************************/
189
190 int fd_close_posix(struct connection_struct *conn, files_struct *fsp)
191 {
192         int saved_errno = 0;
193         int ret;
194         size_t count, i;
195         struct posix_lock *entries = NULL;
196         int *fd_array = NULL;
197
198         if (!lp_posix_locking(SNUM(conn))) {
199                 /*
200                  * No POSIX to worry about, just close.
201                  */
202                 ret = conn->vfs_ops.close(fsp->fd);
203                 fsp->fd = -1;
204                 return ret;
205         }
206
207         /*
208          * Get the number of outstanding POSIX locks on this dev/inode pair.
209          */
210
211         count = get_posix_lock_entries(fsp, &entries);
212         
213         if (count) {
214
215                 /*
216                  * There are outstanding locks on this dev/inode pair on other fds.
217                  * Add our fd to the pending close tdb and set fsp->fd to -1.
218                  */
219
220                 if (!add_fd_to_close_entry(fsp)) {
221                         free((char *)entries);
222                         return False;
223                 }
224
225                 free((char *)entries);
226                 fsp->fd = -1;
227                 return 0;
228         }
229
230         if(entries)
231                 free((char *)entries);
232
233         /*
234          * No outstanding POSIX locks. Get the pending close fd's
235          * from the tdb and close them all.
236          */
237
238         count = get_posix_pending_close_entries(fsp, &fd_array);
239
240         if (count) {
241                 DEBUG(10,("fd_close_posix: doing close on %u fd's.\n", (unsigned int)count ));
242
243                 for(i = 0; i < count; i++) {
244                         if (conn->vfs_ops.close(fd_array[i]) == -1) {
245                                 saved_errno = errno;
246                         }
247                 }
248
249                 /*
250                  * Delete all fd's stored in the tdb
251                  * for this dev/inode pair.
252                  */
253
254                 delete_close_entries(fsp);
255         }
256
257         if (fd_array)
258                 free((char *)fd_array);
259
260         /*
261          * Finally close the fd associated with this fsp.
262          */
263
264         ret = conn->vfs_ops.close(fsp->fd);
265
266         if (saved_errno != 0) {
267         errno = saved_errno;
268                 ret = -1;
269     } 
270
271         fsp->fd = -1;
272
273         return ret;
274 }
275
276 /****************************************************************************
277  Debugging aid :-).
278 ****************************************************************************/
279
280 static const char *posix_lock_type_name(int lock_type)
281 {
282         return (lock_type == F_RDLCK) ? "READ" : "WRITE";
283 }
284
285 /****************************************************************************
286  Add an entry into the POSIX locking tdb.
287 ****************************************************************************/
288
289 static BOOL add_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T size, int lock_type)
290 {
291         TDB_DATA kbuf = locking_key_fsp(fsp);
292         TDB_DATA dbuf;
293         struct posix_lock pl;
294
295         /*
296          * Now setup the new record.
297          */
298
299         pl.fd = fsp->fd;
300         pl.start = start;
301         pl.size = size;
302         pl.lock_type = lock_type;
303
304         dbuf.dptr = NULL;
305
306         dbuf = tdb_fetch(posix_lock_tdb, kbuf);
307
308         dbuf.dptr = Realloc(dbuf.dptr, dbuf.dsize + sizeof(pl));
309         if (!dbuf.dptr) {
310                 DEBUG(0,("add_posix_lock_entry: Realloc fail !\n"));
311                 goto fail;
312         }
313
314         memcpy(dbuf.dptr + dbuf.dsize, &pl, sizeof(pl));
315         dbuf.dsize += sizeof(pl);
316
317         if (tdb_store(posix_lock_tdb, kbuf, dbuf, TDB_REPLACE) == -1) {
318                 DEBUG(0,("add_posix_lock: Failed to add lock entry on file %s\n", fsp->fsp_name));
319                 goto fail;
320         }
321
322     free(dbuf.dptr);
323
324         DEBUG(10,("add_posix_lock: File %s: type = %s: start=%.0f size=%.0f:dev=%.0f inode=%.0f\n",
325                         fsp->fsp_name, posix_lock_type_name(lock_type), (double)start, (double)size,
326                         (double)fsp->dev, (double)fsp->inode ));
327
328     return True;
329
330  fail:
331     if (dbuf.dptr)
332                 free(dbuf.dptr);
333     return False;
334 }
335
336 /****************************************************************************
337  Delete an entry from the POSIX locking tdb.
338 ****************************************************************************/
339
340 static BOOL delete_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T size)
341 {
342         TDB_DATA kbuf = locking_key_fsp(fsp);
343         TDB_DATA dbuf;
344         struct posix_lock *locks;
345         size_t i, count;
346
347         dbuf.dptr = NULL;
348
349         dbuf = tdb_fetch(posix_lock_tdb, kbuf);
350
351         if (!dbuf.dptr) {
352                 DEBUG(10,("delete_posix_lock_entry: tdb_fetch failed !\n"));
353                 goto fail;
354         }
355
356         /* There are existing locks - find a match. */
357         locks = (struct posix_lock *)dbuf.dptr;
358         count = (size_t)(dbuf.dsize / sizeof(*locks));
359
360         for (i=0; i<count; i++) { 
361                 struct posix_lock *pl = &locks[i];
362
363                 if (pl->fd == fsp->fd &&
364                         pl->start == start &&
365                         pl->size == size) {
366                         /* Found it - delete it. */
367                         if (count == 1) {
368                                 tdb_delete(posix_lock_tdb, kbuf);
369                         } else {
370                                 if (i < count-1) {
371                                         memmove(&locks[i], &locks[i+1], sizeof(*locks)*((count-1) - i));
372                                 }
373                                 dbuf.dsize -= sizeof(*locks);
374                                 tdb_store(posix_lock_tdb, kbuf, dbuf, TDB_REPLACE);
375                         }
376
377                         free(dbuf.dptr);
378                         return True;
379                 }
380         }
381
382         /* We didn't find it. */
383
384  fail:
385     if (dbuf.dptr)
386                 free(dbuf.dptr);
387     return False;
388 }
389
390 /****************************************************************************
391  Utility function to map a lock type correctly depending on the open
392  mode of a file.
393 ****************************************************************************/
394
395 static int map_posix_lock_type( files_struct *fsp, enum brl_type lock_type)
396 {
397         if((lock_type == WRITE_LOCK) && !fsp->can_write) {
398                 /*
399                  * Many UNIX's cannot get a write lock on a file opened read-only.
400                  * Win32 locking semantics allow this.
401                  * Do the best we can and attempt a read-only lock.
402                  */
403                 DEBUG(10,("map_posix_lock_type: Downgrading write lock to read due to read-only file.\n"));
404                 return F_RDLCK;
405         } else if((lock_type == READ_LOCK) && !fsp->can_read) {
406                 /*
407                  * Ditto for read locks on write only files.
408                  */
409                 DEBUG(10,("map_posix_lock_type: Changing read lock to write due to write-only file.\n"));
410                 return F_WRLCK;
411         }
412
413   /*
414    * This return should be the most normal, as we attempt
415    * to always open files read/write.
416    */
417
418   return (lock_type == READ_LOCK) ? F_RDLCK : F_WRLCK;
419 }
420
421 /****************************************************************************
422  Check to see if the given unsigned lock range is within the possible POSIX
423  range. Modifies the given args to be in range if possible, just returns
424  False if not.
425 ****************************************************************************/
426
427 static BOOL posix_lock_in_range(SMB_OFF_T *offset_out, SMB_OFF_T *count_out,
428                                                                 SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count)
429 {
430         SMB_OFF_T offset;
431         SMB_OFF_T count;
432
433 #if defined(LARGE_SMB_OFF_T) && !defined(HAVE_BROKEN_FCNTL64_LOCKS)
434
435     SMB_OFF_T mask2 = ((SMB_OFF_T)0x4) << (SMB_OFF_T_BITS-4);
436     SMB_OFF_T mask = (mask2<<1);
437     SMB_OFF_T neg_mask = ~mask;
438
439         /*
440          * In this case SMB_OFF_T is 64 bits,
441          * and the underlying system can handle 64 bit signed locks.
442          * Cast to signed type.
443          */
444
445         offset = (SMB_OFF_T)u_offset;
446         count = (SMB_OFF_T)u_count;
447
448         /*
449          * Deal with a very common case of count of all ones.
450          * (lock entire file).
451          */
452
453         if(count == (SMB_OFF_T)-1)
454                 count &= ~mask;
455
456         /*
457          * POSIX lock ranges cannot be negative.
458          * Fail if any combination becomes negative.
459          */
460
461         if(offset < 0 || count < 0 || (offset + count < 0)) {
462                 DEBUG(10,("posix_lock_in_range: negative range: offset = %.0f, count = %.0f. Ignoring lock.\n",
463                                 (double)offset, (double)count ));
464                 return False;
465         }
466
467         /*
468          * In this case SMB_OFF_T is 64 bits, the offset and count
469          * fit within the positive range, and the underlying
470          * system can handle 64 bit locks. Just return as the
471          * cast values are ok.
472          */
473
474 #else /* !LARGE_SMB_OFF_T || HAVE_BROKEN_FCNTL64_LOCKS */
475
476         /*
477          * In this case either SMB_OFF_T is 32 bits,
478          * or the underlying system cannot handle 64 bit signed locks.
479          * Either way we have to try and mangle to fit within 31 bits.
480          * This is difficult.
481          */
482
483 #if defined(HAVE_BROKEN_FCNTL64_LOCKS)
484
485         /*
486          * SMB_OFF_T is 64 bits, but we need to use 31 bits due to
487          * broken large locking.
488          */
489
490         /*
491          * Deal with a very common case of count of all ones.
492          * (lock entire file).
493          */
494
495         if(u_count == (SMB_BIG_UINT)-1)
496                 count = 0x7FFFFFFF;
497
498         if(((u_offset >> 32) & 0xFFFFFFFF) || ((u_count >> 32) & 0xFFFFFFFF)) {
499                 DEBUG(10,("posix_lock_in_range: top 32 bits not zero. offset = %.0f, count = %.0f. Ignoring lock.\n",
500                                 (double)u_offset, (double)u_count ));
501                 /* Top 32 bits of offset or count were not zero. */
502                 return False;
503         }
504
505         /* Cast from 64 bits unsigned to 64 bits signed. */
506         offset = (SMB_OFF_T)u_offset;
507         count = (SMB_OFF_T)u_count;
508
509         /*
510          * Check if we are within the 2^31 range.
511          */
512
513         {
514                 int32 low_offset = (int32)offset;
515                 int32 low_count = (int32)count;
516
517                 if(low_offset < 0 || low_count < 0 || (low_offset + low_count < 0)) {
518                         DEBUG(10,("posix_lock_in_range: not within 2^31 range. low_offset = %d, low_count = %d. Ignoring lock.\n",
519                                         low_offset, low_count ));
520                         return False;
521                 }
522         }
523
524         /*
525          * Ok - we can map from a 64 bit number to a 31 bit lock.
526          */
527
528 #else /* HAVE_BROKEN_FCNTL64_LOCKS */
529
530         /*
531          * SMB_OFF_T is 32 bits.
532          */
533
534 #if defined(HAVE_LONGLONG)
535
536         /*
537          * SMB_BIG_UINT is 64 bits, we can do a 32 bit shift.
538          */
539
540         /*
541          * Deal with a very common case of count of all ones.
542          * (lock entire file).
543          */
544
545         if(u_count == (SMB_BIG_UINT)-1)
546                 count = 0x7FFFFFFF;
547
548         if(((u_offset >> 32) & 0xFFFFFFFF) || ((u_count >> 32) & 0xFFFFFFFF)) {
549                 DEBUG(10,("posix_lock_in_range: top 32 bits not zero. u_offset = %.0f, u_count = %.0f. Ignoring lock.\n",
550                                 (double)u_offset, (double)u_count ));
551                 return False;
552         }
553
554         /* Cast from 64 bits unsigned to 32 bits signed. */
555         offset = (SMB_OFF_T)u_offset;
556         count = (SMB_OFF_T)u_count;
557
558         /*
559          * Check if we are within the 2^31 range.
560          */
561
562         if(offset < 0 || count < 0 || (offset + count < 0)) {
563                 DEBUG(10,("posix_lock_in_range: not within 2^31 range. offset = %d, count = %d. Ignoring lock.\n",
564                                 (int)offset, (int)count ));
565                 return False;
566         }
567
568 #else /* HAVE_LONGLONG */
569
570         /*
571          * SMB_BIG_UINT and SMB_OFF_T are both 32 bits,
572          * just cast.
573          */
574
575         /*
576          * Deal with a very common case of count of all ones.
577          * (lock entire file).
578          */
579
580         if(u_count == (SMB_BIG_UINT)-1)
581                 count = 0x7FFFFFFF;
582
583         /* Cast from 32 bits unsigned to 32 bits signed. */
584         offset = (SMB_OFF_T)u_offset;
585         count = (SMB_OFF_T)u_count;
586
587         /*
588          * Check if we are within the 2^31 range.
589          */
590
591         if(offset < 0 || count < 0 || (offset + count < 0)) {
592                 DEBUG(10,("posix_lock_in_range: not within 2^31 range. offset = %d, count = %d. Ignoring lock.\n",
593                                 (int)offset, (int)count ));
594                 return False;
595         }
596
597 #endif /* HAVE_LONGLONG */
598 #endif /* LARGE_SMB_OFF_T */
599 #endif /* !LARGE_SMB_OFF_T || HAVE_BROKEN_FCNTL64_LOCKS */
600
601         /*
602          * The mapping was successful.
603          */
604
605         DEBUG(10,("posix_lock_in_range: offset_out = %.0f, count_out = %.0f\n",
606                         (double)offset, (double)count ));
607
608         *offset_out = offset;
609         *count_out = count;
610         
611         return True;
612 }
613
614 /****************************************************************************
615  POSIX function to see if a file region is locked. Returns True if the
616  region is locked, False otherwise.
617 ****************************************************************************/
618
619 BOOL is_posix_locked(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count, enum brl_type lock_type)
620 {
621         SMB_OFF_T offset;
622         SMB_OFF_T count;
623         int posix_lock_type = map_posix_lock_type(fsp,lock_type);
624
625         DEBUG(10,("is_posix_locked: File %s, offset = %.0f, count = %.0f, type = %s\n",
626                         fsp->fsp_name, (double)u_offset, (double)u_count, posix_lock_type_name(lock_type) ));
627
628         /*
629          * If the requested lock won't fit in the POSIX range, we will
630          * never set it, so presume it is not locked.
631          */
632
633         if(!posix_lock_in_range(&offset, &count, u_offset, u_count))
634                 return False;
635
636         /*
637          * Note that most UNIX's can *test* for a write lock on
638          * a read-only fd, just not *set* a write lock on a read-only
639          * fd. So we don't need to use map_lock_type here.
640          */ 
641
642         return fcntl_lock(fsp->fd,SMB_F_GETLK,offset,count,posix_lock_type);
643 }
644
645 /****************************************************************************
646  POSIX function to acquire a lock. Returns True if the
647  lock could be granted, False if not.
648 ****************************************************************************/
649
650 BOOL set_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count, enum brl_type lock_type)
651 {
652         SMB_OFF_T offset;
653         SMB_OFF_T count;
654         BOOL ret = True;
655         int posix_lock_type = map_posix_lock_type(fsp,lock_type);
656
657         DEBUG(5,("set_posix_lock: File %s, offset = %.0f, count = %.0f, type = %s\n",
658                         fsp->fsp_name, (double)u_offset, (double)u_count, posix_lock_type_name(lock_type) ));
659
660         /*
661          * If the requested lock won't fit in the POSIX range, we will
662          * pretend it was successful.
663          */
664
665         if(!posix_lock_in_range(&offset, &count, u_offset, u_count))
666                 return True;
667
668         /*
669          * Note that setting multiple overlapping locks on different
670          * file descriptors will not be held separately by the kernel (POSIX
671          * braindamage), but will be merged into one continuous lock
672          * range. We cope with this case in the release_posix_lock code
673          * below. JRA.
674          */
675
676     ret = fcntl_lock(fsp->fd,SMB_F_SETLK,offset,count,posix_lock_type);
677
678         if (ret)
679                 add_posix_lock_entry(fsp,offset,count,posix_lock_type);
680
681         return ret;
682 }
683
684 /*
685  * Structure used when splitting a lock range
686  * into a POSIX lock range. Doubly linked list.
687  */
688
689 struct unlock_list {
690     struct unlock_list *next;
691     struct unlock_list *prev;
692     SMB_OFF_T start;
693     SMB_OFF_T size;
694 };
695
696 /****************************************************************************
697  Create a list of lock ranges that don't overlap a given range. Used in calculating
698  POSIX lock unlocks. This is a difficult function that requires ASCII art to
699  understand it :-).
700 ****************************************************************************/
701
702 static struct unlock_list *posix_unlock_list(TALLOC_CTX *ctx, struct unlock_list *ulhead, files_struct *fsp)
703 {
704         TDB_DATA kbuf = locking_key_fsp(fsp);
705         TDB_DATA dbuf;
706         struct posix_lock *locks;
707         size_t num_locks, i;
708
709         dbuf.dptr = NULL;
710
711         dbuf = tdb_fetch(posix_lock_tdb, kbuf);
712
713         if (!dbuf.dptr) {
714                 return ulhead;
715         }
716         
717         locks = (struct posix_lock *)dbuf.dptr;
718         num_locks = (size_t)(dbuf.dsize / sizeof(*locks));
719
720         /*
721          * Check the current lock list on this dev/inode pair.
722          * Quit if the list is deleted.
723          */
724
725         DEBUG(10,("posix_unlock_list: curr: start=%.0f,size=%.0f\n",
726                 (double)ulhead->start, (double)ulhead->size ));
727
728         for (i=0; i<num_locks && ulhead; i++) {
729
730                 struct posix_lock *lock = &locks[i];
731                 struct unlock_list *ul_curr;
732
733                 /*
734                  * Walk the unlock list, checking for overlaps. Note that
735                  * the unlock list can expand within this loop if the current
736                  * range being examined needs to be split.
737                  */
738
739                 for (ul_curr = ulhead; ul_curr;) {
740
741                         DEBUG(10,("posix_unlock_list: lock: start=%.0f,size=%.0f:",
742                                 (double)lock->start, (double)lock->size ));
743
744                         if ( (ul_curr->start >= (lock->start + lock->size)) ||
745                                  (lock->start > (ul_curr->start + ul_curr->size))) {
746
747                                 /* No overlap with this lock - leave this range alone. */
748 /*********************************************
749                                              +---------+
750                                              | ul_curr |
751                                              +---------+
752                                 +-------+
753                                 | lock  |
754                                 +-------+
755 OR....
756              +---------+
757              | ul_curr |
758              +---------+
759 **********************************************/
760
761                                 DEBUG(10,("no overlap case.\n" ));
762
763                                 ul_curr = ul_curr->next;
764
765                         } else if ( (ul_curr->start >= lock->start) &&
766                                                 (ul_curr->start + ul_curr->size <= lock->start + lock->size) ) {
767
768                                 /*
769                                  * This unlock is completely overlapped by this existing lock range
770                                  * and thus should have no effect (not be unlocked). Delete it from the list.
771                                  */
772 /*********************************************
773                 +---------+
774                 | ul_curr |
775                 +---------+
776         +---------------------------+
777         |       lock                |
778         +---------------------------+
779 **********************************************/
780                                 /* Save the next pointer */
781                                 struct unlock_list *ul_next = ul_curr->next;
782
783                                 DEBUG(10,("delete case.\n" ));
784
785                                 DLIST_REMOVE(ulhead, ul_curr);
786                                 if(ulhead == NULL)
787                                         break; /* No more list... */
788
789                                 ul_curr = ul_next;
790                                 
791                         } else if ( (ul_curr->start >= lock->start) &&
792                                                 (ul_curr->start < lock->start + lock->size) &&
793                                                 (ul_curr->start + ul_curr->size > lock->start + lock->size) ) {
794
795                                 /*
796                                  * This unlock overlaps the existing lock range at the high end.
797                                  * Truncate by moving start to existing range end and reducing size.
798                                  */
799 /*********************************************
800                 +---------------+
801                 | ul_curr       |
802                 +---------------+
803         +---------------+
804         |    lock       |
805         +---------------+
806 BECOMES....
807                         +-------+
808                         |ul_curr|
809                         +-------+
810 **********************************************/
811
812                                 ul_curr->size = (ul_curr->start + ul_curr->size) - (lock->start + lock->size);
813                                 ul_curr->start = lock->start + lock->size;
814
815                                 DEBUG(10,("truncate high case: start=%.0f,size=%.0f\n",
816                                                                 (double)ul_curr->start, (double)ul_curr->size ));
817
818                                 ul_curr = ul_curr->next;
819
820                         } else if ( (ul_curr->start < lock->start) &&
821                                                 (ul_curr->start + ul_curr->size > lock->start) ) {
822
823                                 /*
824                                  * This unlock overlaps the existing lock range at the low end.
825                                  * Truncate by reducing size.
826                                  */
827 /*********************************************
828    +---------------+
829    | ul_curr       |
830    +---------------+
831            +---------------+
832            |    lock       |
833            +---------------+
834 BECOMES....
835    +-------+
836    |ul_curr|
837    +-------+
838 **********************************************/
839
840                                 ul_curr->size = lock->start - ul_curr->start;
841
842                                 DEBUG(10,("truncate low case: start=%.0f,size=%.0f\n",
843                                                                 (double)ul_curr->start, (double)ul_curr->size ));
844
845                                 ul_curr = ul_curr->next;
846                 
847                         } else if ( (ul_curr->start < lock->start) &&
848                                                 (ul_curr->start + ul_curr->size > lock->start + lock->size) ) {
849                                 /*
850                                  * Worst case scenario. Unlock request completely overlaps an existing
851                                  * lock range. Split the request into two, push the new (upper) request
852                                  * into the dlink list, and continue with the entry after ul_new (as we
853                                  * know that ul_new will not overlap with this lock).
854                                  */
855 /*********************************************
856         +---------------------------+
857         |       ul_curr             |
858         +---------------------------+
859                 +---------+
860                 | lock    |
861                 +---------+
862 BECOMES.....
863         +-------+         +---------+
864         |ul_curr|         |ul_new   |
865         +-------+         +---------+
866 **********************************************/
867                                 struct unlock_list *ul_new = (struct unlock_list *)talloc(ctx,
868                                                                                                         sizeof(struct unlock_list));
869
870                                 if(ul_new == NULL) {
871                                         DEBUG(0,("posix_unlock_list: talloc fail.\n"));
872                                         return NULL; /* The talloc_destroy takes care of cleanup. */
873                                 }
874
875                                 ZERO_STRUCTP(ul_new);
876                                 ul_new->start = lock->start + lock->size;
877                                 ul_new->size = ul_curr->start + ul_curr->size - ul_new->start;
878
879                                 /* Add into the dlink list after the ul_curr point - NOT at ulhead. */
880                                 DLIST_ADD(ul_curr, ul_new);
881
882                                 /* Truncate the ul_curr. */
883                                 ul_curr->size = lock->start - ul_curr->start;
884
885                                 DEBUG(10,("split case: curr: start=%.0f,size=%.0f \
886 new: start=%.0f,size=%.0f\n", (double)ul_curr->start, (double)ul_curr->size,
887                                                                 (double)ul_new->start, (double)ul_new->size ));
888
889                                 ul_curr = ul_new->next;
890
891                         } else {
892
893                                 /*
894                                  * This logic case should never happen. Ensure this is the
895                                  * case by forcing an abort.... Remove in production.
896                                  */
897
898                                 smb_panic("logic flaw in cases...\n");
899                         }
900                 } /* end for ( ul_curr = ulhead; ul_curr;) */
901         } /* end for (i=0; i<num_locks && ul_head; i++) */
902
903         if (dbuf.dptr)
904                 free(dbuf.dptr);
905         
906         return ulhead;
907 }
908
909 /****************************************************************************
910  POSIX function to release a lock. Returns True if the
911  lock could be released, False if not.
912 ****************************************************************************/
913
914 BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count)
915 {
916         SMB_OFF_T offset;
917         SMB_OFF_T count;
918         BOOL ret = True;
919         TALLOC_CTX *ul_ctx = NULL;
920         struct unlock_list *ulist = NULL;
921         struct unlock_list *ul = NULL;
922
923         DEBUG(5,("release_posix_lock: File %s, offset = %.0f, count = %.0f\n",
924                 fsp->fsp_name, (double)u_offset, (double)u_count ));
925
926         /*
927          * If the requested lock won't fit in the POSIX range, we will
928          * pretend it was successful.
929          */
930
931         if(!posix_lock_in_range(&offset, &count, u_offset, u_count))
932                 return True;
933
934         /*
935          * We treat this as one unlock request for POSIX accounting purposes even
936          * if it may have been split into multiple smaller POSIX unlock ranges.
937          */ 
938
939         delete_posix_lock_entry(fsp, offset, count);
940
941         if ((ul_ctx = talloc_init()) == NULL) {
942         DEBUG(0,("release_posix_lock: unable to init talloc context.\n"));
943                 return True; /* Not a fatal error. */
944         }
945
946         if ((ul = (struct unlock_list *)talloc(ul_ctx, sizeof(struct unlock_list))) == NULL) {
947                 DEBUG(0,("release_posix_lock: unable to talloc unlock list.\n"));
948                 talloc_destroy(ul_ctx);
949                 return True; /* Not a fatal error. */
950         }
951
952         /*
953          * Create the initial list entry containing the
954          * lock we want to remove.
955          */
956
957         ZERO_STRUCTP(ul);
958         ul->start = offset;
959         ul->size = count;
960
961         DLIST_ADD(ulist, ul);
962
963         /*
964          * The following call calculates if there are any
965          * overlapping locks held by this process on
966          * fd's open on the same file and creates a
967          * list of unlock ranges that will allow
968          * POSIX lock ranges to remain on the file whilst the
969          * unlocks are performed.
970          */
971
972         ulist = posix_unlock_list(ul_ctx, ulist, fsp);
973
974         /*
975          * Release the POSIX locks on the list of ranges returned.
976          */
977
978         for(; ulist; ulist = ulist->next) {
979                 offset = ulist->start;
980                 count = ulist->size;
981
982                 if(u_count == 0) {
983
984                         /*
985                          * This lock must overlap with an existing lock.
986                          * Don't do any POSIX call.
987                          */
988
989                         continue;
990                 }
991
992                 DEBUG(5,("release_posix_lock: Real unlock: offset = %.0f, count = %.0f\n",
993                         (double)offset, (double)count ));
994
995                 if (!fcntl_lock(fsp->fd,SMB_F_SETLK,offset,count,F_UNLCK))
996                         ret = False;
997         }
998
999         talloc_destroy(ul_ctx);
1000
1001         return ret;
1002 }
1003
1004 /****************************************************************************
1005  Remove all lock entries for a specific dev/inode pair from the tdb.
1006 ****************************************************************************/
1007
1008 static void delete_posix_lock_entries(files_struct *fsp)
1009 {
1010         TDB_DATA kbuf = locking_key_fsp(fsp);
1011
1012         if (tdb_delete(posix_lock_tdb, kbuf) == -1)
1013                 DEBUG(0,("delete_close_entries: tdb_delete fail !\n"));
1014 }
1015
1016 /****************************************************************************
1017  Debug function.
1018 ****************************************************************************/
1019
1020 static void dump_entry(struct posix_lock *pl)
1021 {
1022         DEBUG(10,("entry: start=%.0f, size=%.0f, type=%d, fd=%i\n",
1023                 (double)pl->start, (double)pl->size, (int)pl->lock_type, pl->fd ));
1024 }
1025
1026 /****************************************************************************
1027  Remove any locks on this fd. Called from file_close().
1028 ****************************************************************************/
1029
1030 void posix_locking_close_file(files_struct *fsp)
1031 {
1032         struct posix_lock *entries = NULL;
1033         size_t count, i;
1034
1035         /*
1036          * Optimization for the common case where we are the only
1037          * opener of a file. If all fd entries are our own, we don't
1038          * need to explicitly release all the locks via the POSIX functions,
1039          * we can just remove all the entries in the tdb and allow the
1040          * close to remove the real locks.
1041          */
1042
1043         count = get_posix_lock_entries(fsp, &entries);
1044
1045         if (count == 0) {
1046                 DEBUG(10,("posix_locking_close_file: file %s has no outstanding locks.\n", fsp->fsp_name ));
1047                 return;
1048         }
1049
1050         for (i = 0; i < count; i++) {
1051                 if (entries[i].fd != fsp->fd )
1052                         break;
1053
1054                 dump_entry(&entries[i]);
1055         }
1056
1057         if (i == count) {
1058                 /* All locks are ours. */
1059                 DEBUG(10,("posix_locking_close_file: file %s has %u outstanding locks, but all on one fd.\n", 
1060                         fsp->fsp_name, (unsigned int)count ));
1061                 free((char *)entries);
1062                 delete_posix_lock_entries(fsp);
1063                 return;
1064         }
1065
1066         /*
1067          * Difficult case. We need to delete all our locks, whilst leaving
1068          * all other POSIX locks in place.
1069          */
1070
1071         for (i = 0; i < count; i++) {
1072                 struct posix_lock *pl = &entries[i];
1073                 release_posix_lock(fsp, (SMB_BIG_UINT)pl->start, (SMB_BIG_UINT)pl->size );
1074         }
1075         free((char *)entries);
1076 }
1077
1078 /*******************************************************************
1079  Create the in-memory POSIX lock databases.
1080 ********************************************************************/
1081
1082 BOOL posix_locking_init(void)
1083 {
1084         if (posix_lock_tdb && posix_pending_close_tdb)
1085                 return True;
1086
1087         if (!posix_lock_tdb)
1088                 posix_lock_tdb = tdb_open(NULL, 0, TDB_INTERNAL,
1089                                           O_RDWR|O_CREAT, 0644);
1090     if (!posix_lock_tdb) {
1091         DEBUG(0,("Failed to open POSIX byte range locking database.\n"));
1092                 return False;
1093     }
1094         if (!posix_pending_close_tdb)
1095                 posix_pending_close_tdb = tdb_open(NULL, 0, TDB_INTERNAL,
1096                     O_RDWR|O_CREAT, 0644);
1097     if (!posix_pending_close_tdb) {
1098         DEBUG(0,("Failed to open POSIX pending close database.\n"));
1099                 return False;
1100     }
1101
1102         return True;
1103 }
1104
1105 /*******************************************************************
1106  Delete the in-memory POSIX lock databases.
1107 ********************************************************************/
1108
1109 BOOL posix_locking_end(void)
1110 {
1111     if (posix_lock_tdb && tdb_close(posix_lock_tdb) != 0)
1112                 return False;
1113     if (posix_pending_close_tdb && tdb_close(posix_pending_close_tdb) != 0)
1114                 return False;
1115         return True;
1116 }