f29c1a6105a8874ff81797d013af412d64a559cc
[kai/samba.git] / source3 / locking / locking.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    Locking functions
5    Copyright (C) Andrew Tridgell 1992-1997
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
30 #include "includes.h"
31 extern int DEBUGLEVEL;
32 extern connection_struct Connections[];
33 extern files_struct Files[];
34
35 /****************************************************************************
36   utility function called to see if a file region is locked
37 ****************************************************************************/
38 BOOL is_locked(int fnum,int cnum,uint32 count,uint32 offset)
39 {
40   int snum = SNUM(cnum);
41
42   if (count == 0)
43     return(False);
44
45   if (!lp_locking(snum) || !lp_strict_locking(snum))
46     return(False);
47
48   return(fcntl_lock(Files[fnum].fd_ptr->fd,F_GETLK,offset,count,
49                    (Files[fnum].can_write?F_WRLCK:F_RDLCK)));
50 }
51
52
53 /****************************************************************************
54   utility function called by locking requests
55 ****************************************************************************/
56 BOOL do_lock(int fnum,int cnum,uint32 count,uint32 offset,int *eclass,uint32 *ecode)
57 {
58   BOOL ok = False;
59
60   if (!lp_locking(SNUM(cnum)))
61     return(True);
62
63   if (count == 0) {
64     *eclass = ERRDOS;
65     *ecode = ERRnoaccess;
66     return False;
67   }
68
69   if (Files[fnum].can_lock && OPEN_FNUM(fnum) && (Files[fnum].cnum == cnum))
70     ok = fcntl_lock(Files[fnum].fd_ptr->fd,F_SETLK,offset,count,
71                     (Files[fnum].can_write?F_WRLCK:F_RDLCK));
72
73   if (!ok) {
74     *eclass = ERRDOS;
75     *ecode = ERRlock;
76     return False;
77   }
78   return True; /* Got lock */
79 }
80
81
82 /****************************************************************************
83   utility function called by unlocking requests
84 ****************************************************************************/
85 BOOL do_unlock(int fnum,int cnum,uint32 count,uint32 offset,int *eclass,uint32 *ecode)
86 {
87   BOOL ok = False;
88
89   if (!lp_locking(SNUM(cnum)))
90     return(True);
91
92   if (Files[fnum].can_lock && OPEN_FNUM(fnum) && (Files[fnum].cnum == cnum))
93     ok = fcntl_lock(Files[fnum].fd_ptr->fd,F_SETLK,offset,count,F_UNLCK);
94    
95   if (!ok) {
96     *eclass = ERRDOS;
97     *ecode = ERRlock;
98     return False;
99   }
100   return True; /* Did unlock */
101 }
102
103 #ifdef FAST_SHARE_MODES
104 /*******************************************************************
105   initialize the shared memory for share_mode management 
106   ******************************************************************/
107 BOOL start_share_mode_mgmt(void)
108 {
109    pstring shmem_file_name;
110    
111   pstrcpy(shmem_file_name,lp_lockdir());
112   if (!directory_exist(shmem_file_name,NULL))
113     mkdir(shmem_file_name,0755);
114   trim_string(shmem_file_name,"","/");
115   if (!*shmem_file_name) return(False);
116   strcat(shmem_file_name, "/SHARE_MEM_FILE");
117   return smb_shm_open(shmem_file_name, lp_shmem_size());
118 }
119
120
121 /*******************************************************************
122   deinitialize the shared memory for share_mode management 
123   ******************************************************************/
124 BOOL stop_share_mode_mgmt(void)
125 {
126    return smb_shm_close();
127 }
128
129 /*******************************************************************
130   lock a hash bucket entry in shared memory for share_mode management 
131   ******************************************************************/
132 BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok)
133 {
134   return smb_shm_lock_hash_entry(HASH_ENTRY(dev, inode));
135 }
136
137 /*******************************************************************
138   unlock a hash bucket entry in shared memory for share_mode management 
139   ******************************************************************/
140 BOOL unlock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token token)
141 {
142   return smb_shm_unlock_hash_entry(HASH_ENTRY(dev, inode));
143 }
144
145 /*******************************************************************
146 get all share mode entries in shared memory for a dev/inode pair.
147 ********************************************************************/
148 int get_share_modes(int cnum, share_lock_token token, uint32 dev, uint32 inode, 
149                     min_share_mode_entry **old_shares)
150 {
151   smb_shm_offset_t *mode_array;
152   unsigned int hash_entry = HASH_ENTRY(dev, inode); 
153   share_mode_record *file_scanner_p;
154   share_mode_record *file_prev_p;
155   share_mode_entry *entry_scanner_p;
156   share_mode_entry *entry_prev_p;
157   int num_entries;
158   int num_entries_copied;
159   BOOL found = False;
160   min_share_mode_entry *share_array = (min_share_mode_entry *)0;
161
162   *old_shares = 0;
163
164   if(hash_entry > lp_shmem_hash_size() )
165   {
166     DEBUG(0, 
167       ("PANIC ERROR : get_share_modes (FAST_SHARE_MODES): hash_entry %d too large \
168 (max = %d)\n",
169       hash_entry, lp_shmem_hash_size() ));
170     return 0;
171   }
172
173   mode_array = (smb_shm_offset_t *)smb_shm_offset2addr(smb_shm_get_userdef_off());
174   
175   if(mode_array[hash_entry] == NULL_OFFSET)
176   {
177     DEBUG(5,("get_share_modes (FAST_SHARE_MODES): hash bucket %d empty\n", hash_entry));
178     return 0;
179   }
180
181   file_scanner_p = (share_mode_record *)smb_shm_offset2addr(mode_array[hash_entry]);
182   file_prev_p = file_scanner_p;
183   while(file_scanner_p)
184   {
185     if( (file_scanner_p->st_dev == dev) && (file_scanner_p->st_ino == inode) )
186     {
187       found = True;
188       break;
189     }
190     else
191     {
192       file_prev_p = file_scanner_p ;
193       file_scanner_p = (share_mode_record *)smb_shm_offset2addr(
194                                     file_scanner_p->next_offset);
195     }
196   }
197   
198   if(!found)
199   {
200     DEBUG(5,("get_share_modes (FAST_SHARE_MODES): no entry for \
201 file dev = %d, ino = %d in hash_bucket %d\n", dev, inode, hash_entry));
202     return (0);
203   }
204   
205   if(file_scanner_p->locking_version != LOCKING_VERSION)
206   {
207     DEBUG(0,("ERROR:get_share_modes (FAST_SHARE_MODES): Deleting old share mode \
208 record due to old locking version %d for file dev = %d, inode = %d in hash \
209 bucket %d\n", file_scanner_p->locking_version, dev, inode, hash_entry));
210     if(file_prev_p == file_scanner_p)
211       mode_array[hash_entry] = file_scanner_p->next_offset;
212     else
213       file_prev_p->next_offset = file_scanner_p->next_offset;
214     smb_shm_free(smb_shm_addr2offset(file_scanner_p));
215     return (0);
216   }
217
218   /* Allocate the old_shares array */
219   num_entries = file_scanner_p->num_share_mode_entries;
220   if(num_entries)
221   {
222     *old_shares = share_array = (min_share_mode_entry *)
223                  malloc(num_entries * sizeof(min_share_mode_entry));
224     if(*old_shares == 0)
225     {
226       DEBUG(0,("get_share_modes (FAST_SHARE_MODES): malloc fail !\n"));
227       return 0;
228     }
229   }
230
231   num_entries_copied = 0;
232   
233   entry_scanner_p = (share_mode_entry*)smb_shm_offset2addr(
234                                            file_scanner_p->share_mode_entries);
235   entry_prev_p = entry_scanner_p;
236   while(entry_scanner_p)
237   {
238     int pid = entry_scanner_p->pid;
239
240     if (pid && !process_exists(pid))
241     {
242       /* Delete this share mode entry */
243       share_mode_entry *delete_entry_p = entry_scanner_p;
244
245       if(entry_prev_p == entry_scanner_p)
246       {
247         /* We are at start of list */
248         file_scanner_p->share_mode_entries = entry_scanner_p->next_share_mode_entry;
249         entry_scanner_p = (share_mode_entry*)smb_shm_offset2addr(
250                                            file_scanner_p->share_mode_entries);
251         entry_prev_p = entry_scanner_p;
252       }
253       else
254       {
255         entry_prev_p->next_share_mode_entry = entry_scanner_p->next_share_mode_entry;
256         entry_scanner_p = (share_mode_entry*)
257                            smb_shm_offset2addr(entry_scanner_p->next_share_mode_entry);
258       }
259       /* Decrement the number of share mode entries on this share mode record */
260       file_scanner_p->num_share_mode_entries -= 1;
261
262       /* PARANOIA TEST */
263       if(file_scanner_p->num_share_mode_entries < 0)
264       {
265         DEBUG(0,("PANIC ERROR:get_share_mode (FAST_SHARE_MODES): num_share_mode_entries < 0 (%d) \
266 for dev = %d, ino = %d, hashbucket %d\n", file_scanner_p->num_share_mode_entries,
267              dev, inode, hash_entry));
268         return 0;
269       }
270
271       DEBUG(0,("get_share_modes (FAST_SHARE_MODES): process %d no longer exists and \
272 it left a share mode entry with mode 0x%X for file dev = %d, ino = %d in hash \
273 bucket %d (number of entries now = %d)\n", 
274             pid, entry_scanner_p->share_mode, dev, inode, hash_entry,
275             file_scanner_p->num_share_mode_entries));
276
277       smb_shm_free(smb_shm_addr2offset(delete_entry_p));
278     } 
279     else
280     {
281        /* This is a valid share mode entry and the process that
282            created it still exists. Copy it into the output array.
283        */
284        share_array[num_entries_copied].pid = entry_scanner_p->pid;
285        share_array[num_entries_copied].share_mode = entry_scanner_p->share_mode;
286        share_array[num_entries_copied].op_port = entry_scanner_p->op_port;
287        share_array[num_entries_copied].op_type = entry_scanner_p->op_type;
288        memcpy(&share_array[num_entries_copied].time, &entry_scanner_p->time,
289               sizeof(struct timeval));
290        num_entries_copied++;
291        DEBUG(5,("get_share_modes (FAST_SHARE_MODES): Read share mode \
292 record mode 0x%X pid=%d\n", entry_scanner_p->share_mode, entry_scanner_p->pid));
293        entry_prev_p = entry_scanner_p;
294        entry_scanner_p = (share_mode_entry *)
295                            smb_shm_offset2addr(entry_scanner_p->next_share_mode_entry);
296     }
297   }
298   
299   /* If no valid share mode entries were found then this record shouldn't exist ! */
300   if(num_entries_copied == 0)
301   {
302     DEBUG(0,("get_share_modes (FAST_SHARE_MODES): file with dev %d, inode %d in \
303 hash bucket %d has a share mode record but no entries - deleting\n", 
304                  dev, inode, hash_entry));
305     if(*old_shares)
306       free((char *)*old_shares);
307     *old_shares = 0;
308
309     if(file_prev_p == file_scanner_p)
310       mode_array[hash_entry] = file_scanner_p->next_offset;
311     else
312       file_prev_p->next_offset = file_scanner_p->next_offset;
313     smb_shm_free(smb_shm_addr2offset(file_scanner_p));
314   }
315
316   DEBUG(5,("get_share_modes (FAST_SHARE_MODES): file with dev %d, inode %d in \
317 hash bucket %d returning %d entries\n", dev, inode, hash_entry, num_entries_copied));
318
319   return(num_entries_copied);
320 }  
321
322 /*******************************************************************
323 del the share mode of a file.
324 ********************************************************************/
325 void del_share_mode(share_lock_token token, int fnum)
326 {
327   uint32 dev, inode;
328   smb_shm_offset_t *mode_array;
329   unsigned int hash_entry;
330   share_mode_record *file_scanner_p;
331   share_mode_record *file_prev_p;
332   share_mode_entry *entry_scanner_p;
333   share_mode_entry *entry_prev_p;
334   BOOL found = False;
335   int pid = getpid();
336
337   dev = Files[fnum].fd_ptr->dev;
338   inode = Files[fnum].fd_ptr->inode;
339
340   hash_entry = HASH_ENTRY(dev, inode);
341
342   if(hash_entry > lp_shmem_hash_size() )
343   {
344     DEBUG(0,
345       ("PANIC ERROR:del_share_mode (FAST_SHARE_MODES): hash_entry %d too large \
346 (max = %d)\n",
347       hash_entry, lp_shmem_hash_size() ));
348     return;
349   }
350
351   mode_array = (smb_shm_offset_t *)smb_shm_offset2addr(smb_shm_get_userdef_off());
352  
353   if(mode_array[hash_entry] == NULL_OFFSET)
354   {  
355     DEBUG(0,("PANIC ERROR:del_share_mode (FAST_SHARE_MODES): hash bucket %d empty\n", 
356                   hash_entry));
357     return;
358   }  
359   
360   file_scanner_p = (share_mode_record *)smb_shm_offset2addr(mode_array[hash_entry]);
361   file_prev_p = file_scanner_p;
362
363   while(file_scanner_p)
364   {
365     if( (file_scanner_p->st_dev == dev) && (file_scanner_p->st_ino == inode) )
366     {
367       found = True;
368       break;
369     }
370     else
371     {
372       file_prev_p = file_scanner_p ;
373       file_scanner_p = (share_mode_record *)
374                         smb_shm_offset2addr(file_scanner_p->next_offset);
375     }
376   }
377     
378   if(!found)
379   {
380      DEBUG(0,("ERROR:del_share_mode (FAST_SHARE_MODES): no entry found for dev %d, \
381 inode %d in hash bucket %d\n", dev, inode, hash_entry));
382      return;
383   }
384   
385   if(file_scanner_p->locking_version != LOCKING_VERSION)
386   {
387     DEBUG(0,("ERROR: del_share_modes (FAST_SHARE_MODES): Deleting old share mode \
388 record due to old locking version %d for file dev %d, inode %d hash bucket %d\n",
389        file_scanner_p->locking_version, dev, inode, hash_entry ));
390     if(file_prev_p == file_scanner_p)
391       mode_array[hash_entry] = file_scanner_p->next_offset;
392     else
393       file_prev_p->next_offset = file_scanner_p->next_offset;
394     smb_shm_free(smb_shm_addr2offset(file_scanner_p));
395     return;
396   }
397
398   found = False;
399   entry_scanner_p = (share_mode_entry*)smb_shm_offset2addr(
400                                          file_scanner_p->share_mode_entries);
401   entry_prev_p = entry_scanner_p;
402   while(entry_scanner_p)
403   {
404     if( (pid == entry_scanner_p->pid) && 
405           (memcmp(&entry_scanner_p->time, 
406                  &Files[fnum].open_time,sizeof(struct timeval)) == 0) )
407     {
408       found = True;
409       break;
410     }
411     else
412     {
413       entry_prev_p = entry_scanner_p;
414       entry_scanner_p = (share_mode_entry *)
415                           smb_shm_offset2addr(entry_scanner_p->next_share_mode_entry);
416     }
417   } 
418
419   if (found)
420   {
421     /* Decrement the number of entries in the record. */
422     file_scanner_p->num_share_mode_entries -= 1;
423
424     DEBUG(2,("del_share_modes (FAST_SHARE_MODES): \
425 Deleting share mode entry dev = %d, inode = %d in hash bucket %d (num entries now = %d)\n",
426               dev, inode, hash_entry, file_scanner_p->num_share_mode_entries));
427     if(entry_prev_p == entry_scanner_p)
428       /* We are at start of list */
429       file_scanner_p->share_mode_entries = entry_scanner_p->next_share_mode_entry;
430     else
431       entry_prev_p->next_share_mode_entry = entry_scanner_p->next_share_mode_entry;
432     smb_shm_free(smb_shm_addr2offset(entry_scanner_p));
433
434     /* PARANOIA TEST */
435     if(file_scanner_p->num_share_mode_entries < 0)
436     {
437       DEBUG(0,("PANIC ERROR:del_share_mode (FAST_SHARE_MODES): num_share_mode_entries < 0 (%d) \
438 for dev = %d, ino = %d, hashbucket %d\n", file_scanner_p->num_share_mode_entries,
439            dev, inode, hash_entry));
440       return;
441     }
442
443     /* If we deleted the last share mode entry then remove the share mode record. */
444     if(file_scanner_p->num_share_mode_entries == 0)
445     {
446       DEBUG(2,("del_share_modes (FAST_SHARE_MODES): num entries = 0, deleting share_mode \
447 record dev = %d, inode = %d in hash bucket %d\n", dev, inode, hash_entry));
448       if(file_prev_p == file_scanner_p)
449         mode_array[hash_entry] = file_scanner_p->next_offset;
450       else
451         file_prev_p->next_offset = file_scanner_p->next_offset;
452       smb_shm_free(smb_shm_addr2offset(file_scanner_p));
453     }
454   }
455   else
456   {
457     DEBUG(0,("ERROR: del_share_modes (FAST_SHARE_MODES): No share mode record found \
458 dev = %d, inode = %d in hash bucket %d\n", dev, inode, hash_entry));
459   }
460 }
461
462 /*******************************************************************
463 set the share mode of a file. Return False on fail, True on success.
464 ********************************************************************/
465 BOOL set_share_mode(share_lock_token token, int fnum, uint16 port, uint16 op_type)
466 {
467   files_struct *fs_p = &Files[fnum];
468   int32 dev, inode;
469   smb_shm_offset_t *mode_array;
470   unsigned int hash_entry;
471   share_mode_record *file_scanner_p;
472   share_mode_record *file_prev_p;
473   share_mode_entry *new_entry_p;
474   smb_shm_offset_t new_entry_offset;
475   BOOL found = False;
476
477   dev = fs_p->fd_ptr->dev;
478   inode = fs_p->fd_ptr->inode;
479
480   hash_entry = HASH_ENTRY(dev, inode);
481   if(hash_entry > lp_shmem_hash_size() )
482   {
483     DEBUG(0,
484       ("PANIC ERROR:set_share_mode (FAST_SHARE_MODES): hash_entry %d too large \
485 (max = %d)\n",
486       hash_entry, lp_shmem_hash_size() ));
487     return False;
488   }
489
490   mode_array = (smb_shm_offset_t *)smb_shm_offset2addr(smb_shm_get_userdef_off());
491
492   file_scanner_p = (share_mode_record *)smb_shm_offset2addr(mode_array[hash_entry]);
493   file_prev_p = file_scanner_p;
494   
495   while(file_scanner_p)
496   {
497     if( (file_scanner_p->st_dev == dev) && (file_scanner_p->st_ino == inode) )
498     {
499       found = True;
500       break;
501     }
502     else
503     {
504       file_prev_p = file_scanner_p ;
505       file_scanner_p = (share_mode_record *)
506                          smb_shm_offset2addr(file_scanner_p->next_offset);
507     }
508   }
509   
510   if(!found)
511   {
512     /* We must create a share_mode_record */
513     share_mode_record *new_mode_p = NULL;
514     smb_shm_offset_t new_offset = smb_shm_alloc( sizeof(share_mode_record) +
515                                         strlen(fs_p->name) + 1);
516     if(new_offset == NULL_OFFSET)
517     {
518       DEBUG(0,("ERROR:set_share_mode (FAST_SHARE_MODES): smb_shm_alloc fail !\n"));
519       return False;
520     }
521     new_mode_p = smb_shm_offset2addr(new_offset);
522     new_mode_p->locking_version = LOCKING_VERSION;
523     new_mode_p->st_dev = dev;
524     new_mode_p->st_ino = inode;
525     new_mode_p->num_share_mode_entries = 0;
526     new_mode_p->share_mode_entries = NULL_OFFSET;
527     strcpy(new_mode_p->file_name, fs_p->name);
528
529     /* Chain onto the start of the hash chain (in the hope we will be used first). */
530     new_mode_p->next_offset = mode_array[hash_entry];
531     mode_array[hash_entry] = new_offset;
532
533     file_scanner_p = new_mode_p;
534
535     DEBUG(3,("set_share_mode (FAST_SHARE_MODES): Created share record for %s (dev %d \
536 inode %d in hash bucket %d\n", fs_p->name, dev, inode, hash_entry));
537   }
538  
539   /* Now create the share mode entry */ 
540   new_entry_offset = smb_shm_alloc( sizeof(share_mode_entry));
541   if(new_entry_offset == NULL_OFFSET)
542   {
543     smb_shm_offset_t delete_offset = mode_array[hash_entry];
544     DEBUG(0,("ERROR:set_share_mode (FAST_SHARE_MODES): smb_shm_alloc fail 1!\n"));
545     /* Unlink the damaged record */
546     mode_array[hash_entry] = file_scanner_p->next_offset;
547     /* And delete it */
548     smb_shm_free( delete_offset );
549     return False;
550   }
551
552   new_entry_p = smb_shm_offset2addr(new_entry_offset);
553
554   new_entry_p->pid = getpid();
555   new_entry_p->share_mode = fs_p->share_mode;
556   new_entry_p->op_port = port;
557   new_entry_p->op_type = op_type;
558   memcpy( (char *)&new_entry_p->time, (char *)&fs_p->open_time, sizeof(struct timeval));
559
560   /* Chain onto the share_mode_record */
561   new_entry_p->next_share_mode_entry = file_scanner_p->share_mode_entries;
562   file_scanner_p->share_mode_entries = new_entry_offset;
563
564   /* PARANOIA TEST */
565   if(file_scanner_p->num_share_mode_entries < 0)
566   {
567     DEBUG(0,("PANIC ERROR:set_share_mode (FAST_SHARE_MODES): num_share_mode_entries < 0 (%d) \
568 for dev = %d, ino = %d, hashbucket %d\n", file_scanner_p->num_share_mode_entries,
569          dev, inode, hash_entry));
570     return False;
571   }
572
573   /* Increment the share_mode_entries counter */
574   file_scanner_p->num_share_mode_entries += 1;
575
576   DEBUG(3,("set_share_mode (FAST_SHARE_MODES): Created share entry for %s with mode \
577 0x%X pid=%d (num_entries now = %d)\n",fs_p->name, fs_p->share_mode, new_entry_p->pid,
578                              file_scanner_p->num_share_mode_entries));
579
580   return(True);
581 }
582
583 /*******************************************************************
584 Remove an oplock port and mode entry from a share mode.
585 ********************************************************************/
586 BOOL remove_share_oplock(int fnum, share_lock_token token)
587 {
588   uint32 dev, inode;
589   smb_shm_offset_t *mode_array;
590   unsigned int hash_entry;
591   share_mode_record *file_scanner_p;
592   share_mode_record *file_prev_p;
593   share_mode_entry *entry_scanner_p;
594   share_mode_entry *entry_prev_p;
595   BOOL found = False;
596   int pid = getpid();
597
598   dev = Files[fnum].fd_ptr->dev;
599   inode = Files[fnum].fd_ptr->inode;
600
601   hash_entry = HASH_ENTRY(dev, inode);
602
603   if(hash_entry > lp_shmem_hash_size() )
604   {
605     DEBUG(0,
606       ("PANIC ERROR:remove_share_oplock (FAST_SHARE_MODES): hash_entry %d too large \
607 (max = %d)\n",
608       hash_entry, lp_shmem_hash_size() ));
609     return False;
610   }
611
612   mode_array = (smb_shm_offset_t *)smb_shm_offset2addr(smb_shm_get_userdef_off());
613
614   if(mode_array[hash_entry] == NULL_OFFSET)
615   {
616     DEBUG(0,("PANIC ERROR:remove_share_oplock (FAST_SHARE_MODES): hash bucket %d empty\n",
617                   hash_entry));
618     return False;
619   } 
620     
621   file_scanner_p = (share_mode_record *)smb_shm_offset2addr(mode_array[hash_entry]);
622   file_prev_p = file_scanner_p;
623     
624   while(file_scanner_p)
625   { 
626     if( (file_scanner_p->st_dev == dev) && (file_scanner_p->st_ino == inode) )
627     {
628       found = True;
629       break;
630     }
631     else
632     {
633       file_prev_p = file_scanner_p ;
634       file_scanner_p = (share_mode_record *)
635                         smb_shm_offset2addr(file_scanner_p->next_offset);
636     }
637   } 
638    
639   if(!found)
640   { 
641      DEBUG(0,("ERROR:remove_share_oplock (FAST_SHARE_MODES): no entry found for dev %d, \
642 inode %d in hash bucket %d\n", dev, inode, hash_entry));
643      return False;
644   } 
645
646   if(file_scanner_p->locking_version != LOCKING_VERSION)
647   {
648     DEBUG(0,("ERROR: remove_share_oplock (FAST_SHARE_MODES): Deleting old share mode \
649 record due to old locking version %d for file dev %d, inode %d hash bucket %d\n",
650        file_scanner_p->locking_version, dev, inode, hash_entry ));
651     if(file_prev_p == file_scanner_p)
652       mode_array[hash_entry] = file_scanner_p->next_offset;
653     else
654       file_prev_p->next_offset = file_scanner_p->next_offset;
655     smb_shm_free(smb_shm_addr2offset(file_scanner_p));
656     return False;
657   }
658
659   found = False;
660   entry_scanner_p = (share_mode_entry*)smb_shm_offset2addr(
661                                          file_scanner_p->share_mode_entries);
662   entry_prev_p = entry_scanner_p;
663   while(entry_scanner_p)
664   {
665     if( (pid == entry_scanner_p->pid) && 
666         (entry_scanner_p->share_mode == Files[fnum].share_mode) &&
667         (memcmp(&entry_scanner_p->time, 
668                 &Files[fnum].open_time,sizeof(struct timeval)) == 0) )
669     {
670       /* Delete the oplock info. */
671       entry_scanner_p->op_port = 0;
672       entry_scanner_p->op_type = 0;
673       found = True;
674       break;
675     }
676     else
677     {
678       entry_prev_p = entry_scanner_p;
679       entry_scanner_p = (share_mode_entry *)
680                           smb_shm_offset2addr(entry_scanner_p->next_share_mode_entry);
681     }
682   } 
683
684   if(!found)
685   {
686     DEBUG(0,("ERROR: remove_share_oplock (FAST_SHARE_MODES): No oplock granted share \
687 mode record found dev = %d, inode = %d in hash bucket %d\n", dev, inode, hash_entry));
688     return False;
689   }
690
691   return True;
692 }
693
694 #else /* FAST_SHARE_MODES */
695
696 /* SHARE MODE LOCKS USING SLOW DESCRIPTION FILES */
697
698 /*******************************************************************
699   name a share file
700   ******************************************************************/
701 static BOOL share_name(int cnum, uint32 dev, uint32 inode, char *name)
702 {
703   strcpy(name,lp_lockdir());
704   standard_sub(cnum,name);
705   trim_string(name,"","/");
706   if (!*name) return(False);
707   name += strlen(name);
708   
709   sprintf(name,"/share.%u.%u",dev,inode);
710   return(True);
711 }
712
713 /*******************************************************************
714   lock a share mode file.
715   ******************************************************************/
716 BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok)
717 {
718   pstring fname;
719   int fd;
720
721   *ptok = (share_lock_token)-1;
722
723   if(!share_name(cnum, dev, inode, fname))
724     return False;
725
726   {
727     int old_umask;
728     unbecome_user();
729     old_umask = umask(0);
730 #ifdef SECURE_SHARE_MODES
731     fd = (share_lock_token)open(fname,O_RDWR|O_CREAT,0600);
732 #else /* SECURE_SHARE_MODES */
733     fd = (share_lock_token)open(fname,O_RDWR|O_CREAT,0666);
734 #endif /* SECURE_SHARE_MODES */
735     umask(old_umask);
736     if(!become_user(cnum,Connections[cnum].vuid))
737     {
738       DEBUG(0,("lock_share_entry: Can't become connected user!\n"));
739       close(fd);
740       return False;
741     }
742     /* We need to change directory back to the connection root. */
743     if (ChDir(Connections[cnum].connectpath) != 0)
744     {
745       DEBUG(0,("lock_share_entry: Can't change directory to %s (%s)\n",
746               Connections[cnum].connectpath, strerror(errno)));
747       close(fd);
748       return False;  
749     }
750   }
751
752   /* At this point we have an open fd to the share mode file. 
753      Lock the first byte exclusively to signify a lock. */
754   if(fcntl_lock(fd, F_SETLKW, 0, 1, F_WRLCK) == False)
755    {
756       DEBUG(0,("ERROR lock_share_entry: fcntl_lock failed with %s\n",
757                   strerror(errno)));   
758       close(fd);
759       return False;
760    }
761
762    *ptok = (share_lock_token)fd;
763    return True;
764 }
765
766 /*******************************************************************
767   unlock a share mode file.
768   ******************************************************************/
769 BOOL unlock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token token)
770 {
771   int fd = (int)token;
772   int ret = True;
773
774   /* token is the fd of the open share mode file. */
775   /* Unlock the first byte. */
776   if(fcntl_lock(fd, F_SETLKW, 0, 1, F_UNLCK) == False)
777    { 
778       DEBUG(0,("ERROR unlock_share_entry: fcntl_lock failed with %s\n",
779                       strerror(errno)));   
780       ret = False;
781    }
782  
783   close((int)token);
784   return ret;
785 }
786
787 /*******************************************************************
788 Force a share file to be deleted.
789 ********************************************************************/
790
791 static int delete_share_file( int cnum, char *fname )
792 {
793   unbecome_user();
794   if(unlink(fname) != 0)
795   {
796     DEBUG(0,("delete_share_file: Can't delete share file %s (%s)\n",
797             fname, strerror(errno)));
798   }
799
800   DEBUG(5,("delete_share_file: Deleted share file %s\n", fname));
801
802   if(!become_user(cnum,Connections[cnum].vuid))
803   {
804     DEBUG(0,("delete_share_file: Can't become connected user!\n"));
805     return -1;
806   }
807   /* We need to change directory back to the connection root. */
808   if (ChDir(Connections[cnum].connectpath) != 0)
809   {
810     DEBUG(0,("delete_share_file: Can't change directory to %s (%s)\n",
811             Connections[cnum].connectpath, strerror(errno)));
812     return -1;  
813   }
814   return 0;
815 }
816
817 /*******************************************************************
818 Read a share file into a buffer.
819 ********************************************************************/
820
821 static int read_share_file(int cnum, int fd, char *fname, char **out, BOOL *p_new_file)
822 {
823   struct stat sb;
824   char *buf;
825   int size;
826
827   *out = 0;
828   *p_new_file = False;
829
830   if(fstat(fd, &sb) != 0)
831   {
832     DEBUG(0,("ERROR: read_share_file: Failed to do stat on share file %s (%s)\n",
833                   fname, strerror(errno)));
834     return -1;
835   }
836
837   if(sb.st_size == 0)
838   {
839      *p_new_file = True;
840      return 0;
841   }
842
843   /* Allocate space for the file */
844   if((buf = (char *)malloc(sb.st_size)) == NULL)
845   {
846     DEBUG(0,("read_share_file: malloc for file size %d fail !\n", sb.st_size));
847     return -1;
848   }
849   
850   if(lseek(fd, 0, SEEK_SET) != 0)
851   {
852     DEBUG(0,("ERROR: read_share_file: Failed to reset position to 0 \
853 for share file %s (%s)\n", fname, strerror(errno)));
854     if(buf)
855       free(buf);
856     return -1;
857   }
858   
859   if (read(fd,buf,sb.st_size) != sb.st_size)
860   {
861     DEBUG(0,("ERROR: read_share_file: Failed to read share file %s (%s)\n",
862                fname, strerror(errno)));
863     if(buf)
864       free(buf);
865     return -1;
866   }
867   
868   if (IVAL(buf,SMF_VERSION_OFFSET) != LOCKING_VERSION) {
869     DEBUG(0,("ERROR: read_share_file: share file %s has incorrect \
870 locking version (was %d, should be %d).\n",fname, 
871                     IVAL(buf,SMF_VERSION_OFFSET), LOCKING_VERSION));
872    if(buf)
873       free(buf);
874     delete_share_file(cnum, fname);
875     return -1;
876   }
877
878   /* Sanity check for file contents */
879   size = sb.st_size;
880   size -= SMF_HEADER_LENGTH; /* Remove the header */
881
882   /* Remove the filename component. */
883   size -= SVAL(buf, SMF_FILENAME_LEN_OFFSET);
884
885   /* The remaining size must be a multiple of SMF_ENTRY_LENGTH - error if not. */
886   if((size % SMF_ENTRY_LENGTH) != 0)
887   {
888     DEBUG(0,("ERROR: read_share_file: share file %s is an incorrect length - \
889 deleting it.\n", fname));
890     if(buf)
891       free(buf);
892     delete_share_file(cnum, fname);
893     return -1;
894   }
895
896   *out = buf;
897   return 0;
898 }
899
900 /*******************************************************************
901 get all share mode entries in a share file for a dev/inode pair.
902 ********************************************************************/
903 int get_share_modes(int cnum, share_lock_token token, uint32 dev, uint32 inode, 
904                     min_share_mode_entry **old_shares)
905 {
906   int fd = (int)token;
907   pstring fname;
908   int i;
909   int num_entries;
910   int num_entries_copied;
911   int newsize;
912   min_share_mode_entry *share_array;
913   char *buf = 0;
914   char *base = 0;
915   BOOL new_file;
916
917   *old_shares = 0;
918
919   /* Read the share file header - this is of the form:
920      0   -  locking version.
921      4   -  number of share mode entries.
922      8   -  2 byte name length
923      [n bytes] file name (zero terminated).
924
925    Followed by <n> share mode entries of the form :
926
927      0   -  tv_sec
928      4   -  tv_usec
929      8   -  share_mode
930     12   -  pid
931     16   -  oplock port (if oplocks in use) - 2 bytes.
932   */
933
934   share_name(cnum, dev, inode, fname);
935
936   if(read_share_file( cnum, fd, fname, &buf, &new_file) != 0)
937   {
938     DEBUG(0,("ERROR: get_share_modes: Failed to read share file %s\n",
939                   fname));
940     return 0;
941   }
942
943   if(new_file == True)
944     return 0;
945
946   num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET);
947
948   DEBUG(5,("get_share_modes: share file %s has %d share mode entries.\n",
949             fname, num_entries));
950
951   /* PARANOIA TEST */
952   if(num_entries < 0)
953   {
954     DEBUG(0,("PANIC ERROR:get_share_mode: num_share_mode_entries < 0 (%d) \
955 for share file %d\n", num_entries, fname));
956     return 0;
957   }
958
959   if(num_entries)
960   {
961     *old_shares = share_array = (min_share_mode_entry *)
962                  malloc(num_entries * sizeof(min_share_mode_entry));
963     if(*old_shares == 0)
964     {
965       DEBUG(0,("get_share_modes: malloc fail !\n"));
966       return 0;
967     }
968   } 
969   else
970   {
971     /* No entries - just delete the file. */
972     DEBUG(0,("get_share_modes: share file %s has no share mode entries - deleting.\n",
973               fname));
974     if(buf)
975       free(buf);
976     delete_share_file(cnum, fname);
977     return 0;
978   }
979
980   num_entries_copied = 0;
981   base = buf + SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET);
982
983   for( i = 0; i < num_entries; i++)
984   {
985     int pid;
986     char *p = base + (i*SMF_ENTRY_LENGTH);
987
988     pid = IVAL(p,SME_PID_OFFSET);
989
990     if(!process_exists(pid))
991     {
992       DEBUG(0,("get_share_modes: process %d no longer exists and \
993 it left a share mode entry with mode 0x%X in share file %s\n",
994             pid, IVAL(p,SME_SHAREMODE_OFFSET), fname));
995       continue;
996     }
997     share_array[num_entries_copied].time.tv_sec = IVAL(p,SME_SEC_OFFSET);
998     share_array[num_entries_copied].time.tv_usec = IVAL(p,SME_USEC_OFFSET);
999     share_array[num_entries_copied].share_mode = IVAL(p,SME_SHAREMODE_OFFSET);
1000     share_array[num_entries_copied].pid = pid;
1001     share_array[num_entries_copied].op_port = SVAL(p,SME_PORT_OFFSET);
1002     share_array[num_entries_copied].op_type = SVAL(p,SME_OPLOCK_TYPE_OFFSET);
1003
1004     num_entries_copied++;
1005   }
1006
1007   if(num_entries_copied == 0)
1008   {
1009     /* Delete the whole file. */
1010     DEBUG(0,("get_share_modes: share file %s had no valid entries - deleting it !\n",
1011              fname));
1012     if(*old_shares)
1013       free((char *)*old_shares);
1014     *old_shares = 0;
1015     if(buf)
1016       free(buf);
1017     delete_share_file(cnum, fname);
1018     return 0;
1019   }
1020
1021   /* If we deleted some entries we need to re-write the whole number of
1022      share mode entries back into the file. */
1023
1024   if(num_entries_copied != num_entries)
1025   {
1026     if(lseek(fd, 0, SEEK_SET) != 0)
1027     {
1028       DEBUG(0,("ERROR: get_share_modes: lseek failed to reset to \
1029 position 0 for share mode file %s (%s)\n", fname, strerror(errno)));
1030       if(*old_shares)
1031         free((char *)*old_shares);
1032       *old_shares = 0;
1033       if(buf)
1034         free(buf);
1035       return 0;
1036     }
1037
1038     SIVAL(buf, SMF_NUM_ENTRIES_OFFSET, num_entries_copied);
1039     for( i = 0; i < num_entries_copied; i++)
1040     {
1041       char *p = base + (i*SMF_ENTRY_LENGTH);
1042
1043       SIVAL(p,SME_PID_OFFSET,share_array[i].pid);
1044       SIVAL(p,SME_SHAREMODE_OFFSET,share_array[i].share_mode);
1045       SIVAL(p,SME_SEC_OFFSET,share_array[i].time.tv_sec);
1046       SIVAL(p,SME_USEC_OFFSET,share_array[i].time.tv_usec);
1047       SSVAL(p,SME_PORT_OFFSET,share_array[i].op_port);
1048       SSVAL(p,SME_OPLOCK_TYPE_OFFSET,share_array[i].op_type);
1049     }
1050
1051     newsize = (base - buf) + (SMF_ENTRY_LENGTH*num_entries_copied);
1052     if(write(fd, buf, newsize) != newsize)
1053     {
1054       DEBUG(0,("ERROR: get_share_modes: failed to re-write share \
1055 mode file %s (%s)\n", fname, strerror(errno)));
1056       if(*old_shares)
1057         free((char *)*old_shares);
1058       *old_shares = 0;
1059       if(buf)
1060         free(buf);
1061       return 0;
1062     }
1063     /* Now truncate the file at this point. */
1064     if(ftruncate(fd, newsize)!= 0)
1065     {
1066       DEBUG(0,("ERROR: get_share_modes: failed to ftruncate share \
1067 mode file %s to size %d (%s)\n", fname, newsize, strerror(errno)));
1068       if(*old_shares)
1069         free((char *)*old_shares);
1070       *old_shares = 0;
1071       if(buf)
1072         free(buf);
1073       return 0;
1074     }
1075   }
1076
1077   if(buf)
1078     free(buf);
1079
1080   DEBUG(5,("get_share_modes: Read share file %s returning %d entries\n",fname,
1081             num_entries_copied));
1082
1083   return num_entries_copied;
1084 }
1085
1086 /*******************************************************************
1087 del a share mode from a share mode file.
1088 ********************************************************************/
1089 void del_share_mode(share_lock_token token, int fnum)
1090 {
1091   pstring fname;
1092   int fd = (int)token;
1093   char *buf = 0;
1094   char *base = 0;
1095   int num_entries;
1096   int newsize;
1097   int i;
1098   files_struct *fs_p = &Files[fnum];
1099   int pid;
1100   BOOL deleted = False;
1101   BOOL new_file;
1102
1103   share_name(fs_p->cnum, fs_p->fd_ptr->dev, 
1104                        fs_p->fd_ptr->inode, fname);
1105
1106   if(read_share_file( fs_p->cnum, fd, fname, &buf, &new_file) != 0)
1107   {
1108     DEBUG(0,("ERROR: del_share_mode: Failed to read share file %s\n",
1109                   fname));
1110     return;
1111   }
1112
1113   if(new_file == True)
1114   {
1115     DEBUG(0,("ERROR:del_share_mode: share file %s is new (size zero), deleting it.\n",
1116               fname));
1117     delete_share_file(fs_p->cnum, fname);
1118     return;
1119   }
1120
1121   num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET);
1122
1123   DEBUG(5,("del_share_mode: share file %s has %d share mode entries.\n",
1124             fname, num_entries));
1125
1126   /* PARANOIA TEST */
1127   if(num_entries < 0)
1128   {
1129     DEBUG(0,("PANIC ERROR:del_share_mode: num_share_mode_entries < 0 (%d) \
1130 for share file %d\n", num_entries, fname));
1131     return;
1132   }
1133
1134   if(num_entries == 0)
1135   {
1136     /* No entries - just delete the file. */
1137     DEBUG(0,("del_share_mode: share file %s has no share mode entries - deleting.\n",
1138               fname));
1139     if(buf)
1140       free(buf);
1141     delete_share_file(fs_p->cnum, fname);
1142     return;
1143   }
1144
1145   pid = getpid();
1146
1147   /* Go through the entries looking for the particular one
1148      we have set - delete it.
1149   */
1150
1151   base = buf + SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET);
1152
1153   for(i = 0; i < num_entries; i++)
1154   {
1155     char *p = base + (i*SMF_ENTRY_LENGTH);
1156
1157     if((IVAL(p,SME_SEC_OFFSET) != fs_p->open_time.tv_sec) || 
1158        (IVAL(p,SME_USEC_OFFSET) != fs_p->open_time.tv_usec) ||
1159        (IVAL(p,SME_SHAREMODE_OFFSET) != fs_p->share_mode) || 
1160        (IVAL(p,SME_PID_OFFSET) != pid))
1161       continue;
1162
1163     DEBUG(5,("del_share_mode: deleting entry number %d (of %d) from the share file %s\n",
1164              i, num_entries, fname));
1165
1166     /* Remove this entry. */
1167     if(i != num_entries - 1)
1168       memcpy(p, p + SMF_ENTRY_LENGTH, (num_entries - i - 1)*SMF_ENTRY_LENGTH);
1169
1170     deleted = True;
1171     break;
1172   }
1173
1174   if(!deleted)
1175   {
1176     DEBUG(0,("del_share_mode: entry not found in share file %s\n", fname));
1177     if(buf)
1178       free(buf);
1179     return;
1180   }
1181
1182   num_entries--;
1183   SIVAL(buf,SMF_NUM_ENTRIES_OFFSET, num_entries);
1184
1185   if(num_entries == 0)
1186   {
1187     /* Deleted the last entry - remove the file. */
1188     DEBUG(5,("del_share_mode: removed last entry in share file - deleting share file %s\n",
1189              fname));
1190     if(buf)
1191       free(buf);
1192     delete_share_file(fs_p->cnum,fname);
1193     return;
1194   }
1195
1196   /* Re-write the file - and truncate it at the correct point. */
1197   if(lseek(fd, 0, SEEK_SET) != 0)
1198   {
1199     DEBUG(0,("ERROR: del_share_mode: lseek failed to reset to \
1200 position 0 for share mode file %s (%s)\n", fname, strerror(errno)));
1201     if(buf)
1202       free(buf);
1203     return;
1204   }
1205
1206   newsize = (base - buf) + (SMF_ENTRY_LENGTH*num_entries);
1207   if(write(fd, buf, newsize) != newsize)
1208   {
1209     DEBUG(0,("ERROR: del_share_mode: failed to re-write share \
1210 mode file %s (%s)\n", fname, strerror(errno)));
1211     if(buf)
1212       free(buf);
1213     return;
1214   }
1215   /* Now truncate the file at this point. */
1216   if(ftruncate(fd, newsize) != 0)
1217   {
1218     DEBUG(0,("ERROR: del_share_mode: failed to ftruncate share \
1219 mode file %s to size %d (%s)\n", fname, newsize, strerror(errno)));
1220     if(buf)
1221       free(buf);
1222     return;
1223   }
1224 }
1225   
1226 /*******************************************************************
1227 set the share mode of a file
1228 ********************************************************************/
1229 BOOL set_share_mode(share_lock_token token,int fnum, uint16 port, uint16 op_type)
1230 {
1231   files_struct *fs_p = &Files[fnum];
1232   pstring fname;
1233   int fd = (int)token;
1234   int pid = (int)getpid();
1235   struct stat sb;
1236   char *buf;
1237   int num_entries;
1238   int header_size;
1239   char *p;
1240
1241   share_name(fs_p->cnum, fs_p->fd_ptr->dev,
1242                        fs_p->fd_ptr->inode, fname);
1243
1244   if(fstat(fd, &sb) != 0)
1245   {
1246     DEBUG(0,("ERROR: set_share_mode: Failed to do stat on share file %s\n",
1247                   fname));
1248     return False;
1249   }
1250
1251   /* Sanity check for file contents (if it's not a new share file). */
1252   if(sb.st_size != 0)
1253   {
1254     int size = sb.st_size;
1255
1256     /* Allocate space for the file plus one extra entry */
1257     if((buf = (char *)malloc(sb.st_size + SMF_ENTRY_LENGTH)) == NULL)
1258     {
1259       DEBUG(0,("set_share_mode: malloc for file size %d fail !\n", 
1260                   sb.st_size + SMF_ENTRY_LENGTH));
1261       return False;
1262     }
1263  
1264     if(lseek(fd, 0, SEEK_SET) != 0)
1265     {
1266       DEBUG(0,("ERROR: set_share_mode: Failed to reset position \
1267 to 0 for share file %s (%s)\n", fname, strerror(errno)));
1268       if(buf)
1269         free(buf);
1270       return False;
1271     }
1272
1273     if (read(fd,buf,sb.st_size) != sb.st_size)
1274     {
1275       DEBUG(0,("ERROR: set_share_mode: Failed to read share file %s (%s)\n",
1276                   fname, strerror(errno)));
1277       if(buf)
1278         free(buf);
1279       return False;
1280     }   
1281   
1282     if (IVAL(buf,SMF_VERSION_OFFSET) != LOCKING_VERSION) 
1283     {
1284       DEBUG(0,("ERROR: set_share_mode: share file %s has incorrect \
1285 locking version (was %d, should be %d).\n",fname, IVAL(buf,SMF_VERSION_OFFSET), 
1286                     LOCKING_VERSION));
1287       if(buf)
1288         free(buf);
1289       delete_share_file(fs_p->cnum, fname);
1290       return False;
1291     }   
1292
1293     size -= (SMF_HEADER_LENGTH + SVAL(buf, SMF_FILENAME_LEN_OFFSET)); /* Remove the header */
1294
1295     /* The remaining size must be a multiple of SMF_ENTRY_LENGTH - error if not. */
1296     if((size % SMF_ENTRY_LENGTH) != 0)
1297     {
1298       DEBUG(0,("ERROR: set_share_mode: share file %s is an incorrect length - \
1299 deleting it.\n", fname));
1300       if(buf)
1301         free(buf);
1302       delete_share_file(fs_p->cnum, fname);
1303       return False;
1304     }
1305
1306   }
1307   else
1308   {
1309     /* New file - just use a single_entry. */
1310     if((buf = (char *)malloc(SMF_HEADER_LENGTH + 
1311                   strlen(fs_p->name) + 1 + SMF_ENTRY_LENGTH)) == NULL)
1312     {
1313       DEBUG(0,("ERROR: set_share_mode: malloc failed for single entry.\n"));
1314       return False;
1315     }
1316     SIVAL(buf,SMF_VERSION_OFFSET,LOCKING_VERSION);
1317     SIVAL(buf,SMF_NUM_ENTRIES_OFFSET,0);
1318     SSVAL(buf,SMF_FILENAME_LEN_OFFSET,strlen(fs_p->name) + 1);
1319     strcpy(buf + SMF_HEADER_LENGTH, fs_p->name);
1320   }
1321
1322   num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET);
1323   header_size = SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET);
1324   p = buf + header_size + (num_entries * SMF_ENTRY_LENGTH);
1325   SIVAL(p,SME_SEC_OFFSET,fs_p->open_time.tv_sec);
1326   SIVAL(p,SME_USEC_OFFSET,fs_p->open_time.tv_usec);
1327   SIVAL(p,SME_SHAREMODE_OFFSET,fs_p->share_mode);
1328   SIVAL(p,SME_PID_OFFSET,pid);
1329   SSVAL(p,SME_PORT_OFFSET,port);
1330   SSVAL(p,SME_OPLOCK_TYPE_OFFSET,op_type);
1331
1332   num_entries++;
1333
1334   SIVAL(buf,SMF_NUM_ENTRIES_OFFSET,num_entries);
1335
1336   if(lseek(fd, 0, SEEK_SET) != 0)
1337   {
1338     DEBUG(0,("ERROR: set_share_mode: (1) Failed to reset position to \
1339 0 for share file %s (%s)\n", fname, strerror(errno)));
1340     if(buf)
1341       free(buf);
1342     return False;
1343   }
1344
1345   if (write(fd,buf,header_size + (num_entries*SMF_ENTRY_LENGTH)) != 
1346                        (header_size + (num_entries*SMF_ENTRY_LENGTH))) 
1347   {
1348     DEBUG(2,("ERROR: set_share_mode: Failed to write share file %s - \
1349 deleting it (%s).\n",fname, strerror(errno)));
1350     delete_share_file(fs_p->cnum, fname);
1351     if(buf)
1352       free(buf);
1353     return False;
1354   }
1355
1356   /* Now truncate the file at this point - just for safety. */
1357   if(ftruncate(fd, header_size + (SMF_ENTRY_LENGTH*num_entries))!= 0)
1358   {
1359     DEBUG(0,("ERROR: set_share_mode: failed to ftruncate share \
1360 mode file %s to size %d (%s)\n", fname, header_size + (SMF_ENTRY_LENGTH*num_entries), 
1361                 strerror(errno)));
1362     if(buf)
1363       free(buf);
1364     return False;
1365   }
1366
1367   if(buf)
1368     free(buf);
1369
1370   DEBUG(3,("set_share_mode: Created share file %s with \
1371 mode 0x%X pid=%d\n",fname,fs_p->share_mode,pid));
1372
1373   return True;
1374 }
1375
1376 /*******************************************************************
1377 Remove an oplock port and mode entry from a share mode.
1378 ********************************************************************/
1379 BOOL remove_share_oplock(int fnum, share_lock_token token)
1380 {
1381   pstring fname;
1382   int fd = (int)token;
1383   char *buf = 0;
1384   char *base = 0;
1385   int num_entries;
1386   int fsize;
1387   int i;
1388   files_struct *fs_p = &Files[fnum];
1389   int pid;
1390   BOOL found = False;
1391   BOOL new_file;
1392
1393   share_name(fs_p->cnum, fs_p->fd_ptr->dev, 
1394                        fs_p->fd_ptr->inode, fname);
1395
1396   if(read_share_file( fs_p->cnum, fd, fname, &buf, &new_file) != 0)
1397   {
1398     DEBUG(0,("ERROR: remove_share_oplock: Failed to read share file %s\n",
1399                   fname));
1400     return False;
1401   }
1402
1403   if(new_file == True)
1404   {
1405     DEBUG(0,("ERROR: remove_share_oplock: share file %s is new (size zero), \
1406 deleting it.\n", fname));
1407     delete_share_file(fs_p->cnum, fname);
1408     return False;
1409   }
1410
1411   num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET);
1412
1413   DEBUG(5,("remove_share_oplock: share file %s has %d share mode entries.\n",
1414             fname, num_entries));
1415
1416   /* PARANOIA TEST */
1417   if(num_entries < 0)
1418   {
1419     DEBUG(0,("PANIC ERROR:remove_share_oplock: num_share_mode_entries < 0 (%d) \
1420 for share file %d\n", num_entries, fname));
1421     return False;
1422   }
1423
1424   if(num_entries == 0)
1425   {
1426     /* No entries - just delete the file. */
1427     DEBUG(0,("remove_share_oplock: share file %s has no share mode entries - deleting.\n",
1428               fname));
1429     if(buf)
1430       free(buf);
1431     delete_share_file(fs_p->cnum, fname);
1432     return False;
1433   }
1434
1435   pid = getpid();
1436
1437   /* Go through the entries looking for the particular one
1438      we have set - remove the oplock settings on it.
1439   */
1440
1441   base = buf + SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET);
1442
1443   for(i = 0; i < num_entries; i++)
1444   {
1445     char *p = base + (i*SMF_ENTRY_LENGTH);
1446
1447     if((IVAL(p,SME_SEC_OFFSET) != fs_p->open_time.tv_sec) || 
1448        (IVAL(p,SME_USEC_OFFSET) != fs_p->open_time.tv_usec) ||
1449        (IVAL(p,SME_SHAREMODE_OFFSET) != fs_p->share_mode) || 
1450        (IVAL(p,SME_PID_OFFSET) != pid))
1451       continue;
1452
1453     DEBUG(5,("remove_share_oplock: clearing oplock on entry number %d (of %d) \
1454 from the share file %s\n", i, num_entries, fname));
1455
1456     SSVAL(p,SME_PORT_OFFSET,0);
1457     SSVAL(p,SME_OPLOCK_TYPE_OFFSET,0);
1458     found = True;
1459     break;
1460   }
1461
1462   if(!found)
1463   {
1464     DEBUG(0,("remove_share_oplock: entry not found in share file %s\n", fname));
1465     if(buf)
1466       free(buf);
1467     return False;
1468   }
1469
1470   /* Re-write the file - and truncate it at the correct point. */
1471   if(lseek(fd, 0, SEEK_SET) != 0)
1472   {
1473     DEBUG(0,("ERROR: remove_share_oplock: lseek failed to reset to \
1474 position 0 for share mode file %s (%s)\n", fname, strerror(errno)));
1475     if(buf)
1476       free(buf);
1477     return False;
1478   }
1479
1480   fsize = (base - buf) + (SMF_ENTRY_LENGTH*num_entries);
1481   if(write(fd, buf, fsize) != fsize)
1482   {
1483     DEBUG(0,("ERROR: remove_share_oplock: failed to re-write share \
1484 mode file %s (%s)\n", fname, strerror(errno)));
1485     if(buf)
1486       free(buf);
1487     return False;
1488   }
1489
1490   return True;
1491
1492 }
1493 #endif /* FAST_SHARE_MODES */