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