abda5d39d472356519195a0a0f90522766f80211
[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 #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->share_mode == Files[fnum].share_mode) &&
672         (memcmp(&entry_scanner_p->time, 
673                 &Files[fnum].open_time,sizeof(struct timeval)) == 0) )
674     {
675       /* Delete the oplock info. */
676       entry_scanner_p->op_port = 0;
677       entry_scanner_p->op_type = 0;
678       found = True;
679       break;
680     }
681     else
682     {
683       entry_prev_p = entry_scanner_p;
684       entry_scanner_p = (share_mode_entry *)
685                           smb_shm_offset2addr(entry_scanner_p->next_share_mode_entry);
686     }
687   } 
688
689   if(!found)
690   {
691     DEBUG(0,("ERROR: remove_share_oplock (FAST_SHARE_MODES): No oplock granted share \
692 mode record found dev = %d, inode = %d in hash bucket %d\n", dev, inode, hash_entry));
693     return False;
694   }
695
696   return True;
697 #else /* USE_OPLOCKS */
698   return False;
699 #endif /* USE_OPLOCKS */
700 }
701
702 #else /* FAST_SHARE_MODES */
703
704 /* SHARE MODE LOCKS USING SLOW DESCRIPTION FILES */
705
706 /*******************************************************************
707   name a share file
708   ******************************************************************/
709 static BOOL share_name(int cnum, uint32 dev, uint32 inode, char *name)
710 {
711   strcpy(name,lp_lockdir());
712   standard_sub(cnum,name);
713   trim_string(name,"","/");
714   if (!*name) return(False);
715   name += strlen(name);
716   
717   sprintf(name,"/share.%u.%u",dev,inode);
718   return(True);
719 }
720
721 /*******************************************************************
722   lock a share mode file.
723   ******************************************************************/
724 BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok)
725 {
726   pstring fname;
727   int fd;
728
729   *ptok = (share_lock_token)-1;
730
731   if(!share_name(cnum, dev, inode, fname))
732     return False;
733
734   {
735     int old_umask;
736     unbecome_user();
737     old_umask = umask(0);
738 #ifdef SECURE_SHARE_MODES
739     fd = (share_lock_token)open(fname,O_RDWR|O_CREAT,0600);
740 #else /* SECURE_SHARE_MODES */
741     fd = (share_lock_token)open(fname,O_RDWR|O_CREAT,0666);
742 #endif /* SECURE_SHARE_MODES */
743     umask(old_umask);
744     if(!become_user(cnum,Connections[cnum].vuid))
745     {
746       DEBUG(0,("lock_share_entry: Can't become connected user!\n"));
747       close(fd);
748       return False;
749     }
750     /* We need to change directory back to the connection root. */
751     if (ChDir(Connections[cnum].connectpath) != 0)
752     {
753       DEBUG(0,("lock_share_entry: Can't change directory to %s (%s)\n",
754               Connections[cnum].connectpath, strerror(errno)));
755       close(fd);
756       return False;  
757     }
758   }
759
760   /* At this point we have an open fd to the share mode file. 
761      Lock the first byte exclusively to signify a lock. */
762   if(fcntl_lock(fd, F_SETLKW, 0, 1, F_WRLCK) == False)
763    {
764       DEBUG(0,("ERROR lock_share_entry: fcntl_lock failed with %s\n",
765                   strerror(errno)));   
766       close(fd);
767       return False;
768    }
769
770    *ptok = (share_lock_token)fd;
771    return True;
772 }
773
774 /*******************************************************************
775   unlock a share mode file.
776   ******************************************************************/
777 BOOL unlock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token token)
778 {
779   int fd = (int)token;
780   int ret = True;
781
782   /* token is the fd of the open share mode file. */
783   /* Unlock the first byte. */
784   if(fcntl_lock(fd, F_SETLKW, 0, 1, F_UNLCK) == False)
785    { 
786       DEBUG(0,("ERROR unlock_share_entry: fcntl_lock failed with %s\n",
787                       strerror(errno)));   
788       ret = False;
789    }
790  
791   close((int)token);
792   return ret;
793 }
794
795 /*******************************************************************
796 Force a share file to be deleted.
797 ********************************************************************/
798
799 static int delete_share_file( int cnum, char *fname )
800 {
801   unbecome_user();
802   if(unlink(fname) != 0)
803   {
804     DEBUG(0,("delete_share_file: Can't delete share file %s (%s)\n",
805             fname, strerror(errno)));
806   }
807
808   DEBUG(5,("delete_share_file: Deleted share file %s\n", fname));
809
810   if(!become_user(cnum,Connections[cnum].vuid))
811   {
812     DEBUG(0,("delete_share_file: Can't become connected user!\n"));
813     return -1;
814   }
815   /* We need to change directory back to the connection root. */
816   if (ChDir(Connections[cnum].connectpath) != 0)
817   {
818     DEBUG(0,("delete_share_file: Can't change directory to %s (%s)\n",
819             Connections[cnum].connectpath, strerror(errno)));
820     return -1;  
821   }
822   return 0;
823 }
824
825 /*******************************************************************
826 Read a share file into a buffer.
827 ********************************************************************/
828
829 static int read_share_file(int cnum, int fd, char *fname, char **out, BOOL *p_new_file)
830 {
831   struct stat sb;
832   char *buf;
833   int size;
834
835   *out = 0;
836   *p_new_file = False;
837
838   if(fstat(fd, &sb) != 0)
839   {
840     DEBUG(0,("ERROR: read_share_file: Failed to do stat on share file %s (%s)\n",
841                   fname, strerror(errno)));
842     return -1;
843   }
844
845   if(sb.st_size == 0)
846   {
847      *p_new_file = True;
848      return 0;
849   }
850
851   /* Allocate space for the file */
852   if((buf = (char *)malloc(sb.st_size)) == NULL)
853   {
854     DEBUG(0,("read_share_file: malloc for file size %d fail !\n", sb.st_size));
855     return -1;
856   }
857   
858   if(lseek(fd, 0, SEEK_SET) != 0)
859   {
860     DEBUG(0,("ERROR: read_share_file: Failed to reset position to 0 \
861 for share file %s (%s)\n", fname, strerror(errno)));
862     if(buf)
863       free(buf);
864     return -1;
865   }
866   
867   if (read(fd,buf,sb.st_size) != sb.st_size)
868   {
869     DEBUG(0,("ERROR: read_share_file: Failed to read share file %s (%s)\n",
870                fname, strerror(errno)));
871     if(buf)
872       free(buf);
873     return -1;
874   }
875   
876   if (IVAL(buf,SMF_VERSION_OFFSET) != LOCKING_VERSION) {
877     DEBUG(0,("ERROR: read_share_file: share file %s has incorrect \
878 locking version (was %d, should be %d).\n",fname, 
879                     IVAL(buf,SMF_VERSION_OFFSET), LOCKING_VERSION));
880    if(buf)
881       free(buf);
882     delete_share_file(cnum, fname);
883     return -1;
884   }
885
886   /* Sanity check for file contents */
887   size = sb.st_size;
888   size -= SMF_HEADER_LENGTH; /* Remove the header */
889
890   /* Remove the filename component. */
891   size -= SVAL(buf, SMF_FILENAME_LEN_OFFSET);
892
893   /* The remaining size must be a multiple of SMF_ENTRY_LENGTH - error if not. */
894   if((size % SMF_ENTRY_LENGTH) != 0)
895   {
896     DEBUG(0,("ERROR: read_share_file: share file %s is an incorrect length - \
897 deleting it.\n", fname));
898     if(buf)
899       free(buf);
900     delete_share_file(cnum, fname);
901     return -1;
902   }
903
904   *out = buf;
905   return 0;
906 }
907
908 /*******************************************************************
909 get all share mode entries in a share file for a dev/inode pair.
910 ********************************************************************/
911 int get_share_modes(int cnum, share_lock_token token, uint32 dev, uint32 inode, 
912                     min_share_mode_entry **old_shares)
913 {
914   int fd = (int)token;
915   pstring fname;
916   int i;
917   int num_entries;
918   int num_entries_copied;
919   int newsize;
920   min_share_mode_entry *share_array;
921   char *buf = 0;
922   char *base = 0;
923   BOOL new_file;
924
925   *old_shares = 0;
926
927   /* Read the share file header - this is of the form:
928      0   -  locking version.
929      4   -  number of share mode entries.
930      8   -  2 byte name length
931      [n bytes] file name (zero terminated).
932
933    Followed by <n> share mode entries of the form :
934
935      0   -  tv_sec
936      4   -  tv_usec
937      8   -  share_mode
938     12   -  pid
939     16   -  oplock port (if oplocks in use) - 2 bytes.
940   */
941
942   share_name(cnum, dev, inode, fname);
943
944   if(read_share_file( cnum, fd, fname, &buf, &new_file) != 0)
945   {
946     DEBUG(0,("ERROR: get_share_modes: Failed to read share file %s\n",
947                   fname));
948     return 0;
949   }
950
951   if(new_file == True)
952     return 0;
953
954   num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET);
955
956   DEBUG(5,("get_share_modes: share file %s has %d share mode entries.\n",
957             fname, num_entries));
958
959   /* PARANOIA TEST */
960   if(num_entries < 0)
961   {
962     DEBUG(0,("PANIC ERROR:get_share_mode: num_share_mode_entries < 0 (%d) \
963 for share file %d\n", num_entries, fname));
964     return 0;
965   }
966
967   if(num_entries)
968   {
969     *old_shares = share_array = (min_share_mode_entry *)
970                  malloc(num_entries * sizeof(min_share_mode_entry));
971     if(*old_shares == 0)
972     {
973       DEBUG(0,("get_share_modes: malloc fail !\n"));
974       return 0;
975     }
976   } 
977   else
978   {
979     /* No entries - just delete the file. */
980     DEBUG(0,("get_share_modes: share file %s has no share mode entries - deleting.\n",
981               fname));
982     if(buf)
983       free(buf);
984     delete_share_file(cnum, fname);
985     return 0;
986   }
987
988   num_entries_copied = 0;
989   base = buf + SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET);
990
991   for( i = 0; i < num_entries; i++)
992   {
993     int pid;
994     char *p = base + (i*SMF_ENTRY_LENGTH);
995
996     pid = IVAL(p,SME_PID_OFFSET);
997
998     if(!process_exists(pid))
999     {
1000       DEBUG(0,("get_share_modes: process %d no longer exists and \
1001 it left a share mode entry with mode 0x%X in share file %s\n",
1002             pid, IVAL(p,SME_SHAREMODE_OFFSET), fname));
1003       continue;
1004     }
1005     share_array[num_entries_copied].time.tv_sec = IVAL(p,SME_SEC_OFFSET);
1006     share_array[num_entries_copied].time.tv_usec = IVAL(p,SME_USEC_OFFSET);
1007     share_array[num_entries_copied].share_mode = IVAL(p,SME_SHAREMODE_OFFSET);
1008     share_array[num_entries_copied].pid = pid;
1009 #ifdef USE_OPLOCKS
1010     share_array[num_entries_copied].op_port = SVAL(p,SME_PORT_OFFSET);
1011     share_array[num_entries_copied].op_type = SVAL(p,SME_OPLOCK_TYPE_OFFSET);
1012 #endif /* USE_OPLOCKS */
1013
1014     num_entries_copied++;
1015   }
1016
1017   if(num_entries_copied == 0)
1018   {
1019     /* Delete the whole file. */
1020     DEBUG(0,("get_share_modes: share file %s had no valid entries - deleting it !\n",
1021              fname));
1022     if(*old_shares)
1023       free((char *)*old_shares);
1024     *old_shares = 0;
1025     if(buf)
1026       free(buf);
1027     delete_share_file(cnum, fname);
1028     return 0;
1029   }
1030
1031   /* If we deleted some entries we need to re-write the whole number of
1032      share mode entries back into the file. */
1033
1034   if(num_entries_copied != num_entries)
1035   {
1036     if(lseek(fd, 0, SEEK_SET) != 0)
1037     {
1038       DEBUG(0,("ERROR: get_share_modes: lseek failed to reset to \
1039 position 0 for share mode file %s (%s)\n", fname, strerror(errno)));
1040       if(*old_shares)
1041         free((char *)*old_shares);
1042       *old_shares = 0;
1043       if(buf)
1044         free(buf);
1045       return 0;
1046     }
1047
1048     SIVAL(buf, SMF_NUM_ENTRIES_OFFSET, num_entries_copied);
1049     for( i = 0; i < num_entries_copied; i++)
1050     {
1051       char *p = base + (i*SMF_ENTRY_LENGTH);
1052
1053       SIVAL(p,SME_PID_OFFSET,share_array[i].pid);
1054       SIVAL(p,SME_SHAREMODE_OFFSET,share_array[i].share_mode);
1055       SIVAL(p,SME_SEC_OFFSET,share_array[i].time.tv_sec);
1056       SIVAL(p,SME_USEC_OFFSET,share_array[i].time.tv_usec);
1057 #ifdef USE_OPLOCKS
1058       SSVAL(p,SME_PORT_OFFSET,share_array[i].op_port);
1059       SSVAL(p,SME_OPLOCK_TYPE_OFFSET,share_array[i].op_type);
1060 #endif /* USE_OPLOCKS */
1061     }
1062
1063     newsize = (base - buf) + (SMF_ENTRY_LENGTH*num_entries_copied);
1064     if(write(fd, buf, newsize) != newsize)
1065     {
1066       DEBUG(0,("ERROR: get_share_modes: failed to re-write share \
1067 mode file %s (%s)\n", fname, 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     /* Now truncate the file at this point. */
1076     if(ftruncate(fd, newsize)!= 0)
1077     {
1078       DEBUG(0,("ERROR: get_share_modes: failed to ftruncate share \
1079 mode file %s to size %d (%s)\n", fname, newsize, strerror(errno)));
1080       if(*old_shares)
1081         free((char *)*old_shares);
1082       *old_shares = 0;
1083       if(buf)
1084         free(buf);
1085       return 0;
1086     }
1087   }
1088
1089   if(buf)
1090     free(buf);
1091
1092   DEBUG(5,("get_share_modes: Read share file %s returning %d entries\n",fname,
1093             num_entries_copied));
1094
1095   return num_entries_copied;
1096 }
1097
1098 /*******************************************************************
1099 del a share mode from a share mode file.
1100 ********************************************************************/
1101 void del_share_mode(share_lock_token token, int fnum)
1102 {
1103   pstring fname;
1104   int fd = (int)token;
1105   char *buf = 0;
1106   char *base = 0;
1107   int num_entries;
1108   int newsize;
1109   int i;
1110   files_struct *fs_p = &Files[fnum];
1111   int pid;
1112   BOOL deleted = False;
1113   BOOL new_file;
1114
1115   share_name(fs_p->cnum, fs_p->fd_ptr->dev, 
1116                        fs_p->fd_ptr->inode, fname);
1117
1118   if(read_share_file( fs_p->cnum, fd, fname, &buf, &new_file) != 0)
1119   {
1120     DEBUG(0,("ERROR: del_share_mode: Failed to read share file %s\n",
1121                   fname));
1122     return;
1123   }
1124
1125   if(new_file == True)
1126   {
1127     DEBUG(0,("ERROR:del_share_mode: share file %s is new (size zero), deleting it.\n",
1128               fname));
1129     delete_share_file(fs_p->cnum, fname);
1130     return;
1131   }
1132
1133   num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET);
1134
1135   DEBUG(5,("del_share_mode: share file %s has %d share mode entries.\n",
1136             fname, num_entries));
1137
1138   /* PARANOIA TEST */
1139   if(num_entries < 0)
1140   {
1141     DEBUG(0,("PANIC ERROR:del_share_mode: num_share_mode_entries < 0 (%d) \
1142 for share file %d\n", num_entries, fname));
1143     return;
1144   }
1145
1146   if(num_entries == 0)
1147   {
1148     /* No entries - just delete the file. */
1149     DEBUG(0,("del_share_mode: share file %s has no share mode entries - deleting.\n",
1150               fname));
1151     if(buf)
1152       free(buf);
1153     delete_share_file(fs_p->cnum, fname);
1154     return;
1155   }
1156
1157   pid = getpid();
1158
1159   /* Go through the entries looking for the particular one
1160      we have set - delete it.
1161   */
1162
1163   base = buf + SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET);
1164
1165   for(i = 0; i < num_entries; i++)
1166   {
1167     char *p = base + (i*SMF_ENTRY_LENGTH);
1168
1169     if((IVAL(p,SME_SEC_OFFSET) != fs_p->open_time.tv_sec) || 
1170        (IVAL(p,SME_USEC_OFFSET) != fs_p->open_time.tv_usec) ||
1171        (IVAL(p,SME_SHAREMODE_OFFSET) != fs_p->share_mode) || 
1172        (IVAL(p,SME_PID_OFFSET) != pid))
1173       continue;
1174
1175     DEBUG(5,("del_share_mode: deleting entry number %d (of %d) from the share file %s\n",
1176              i, num_entries, fname));
1177
1178     /* Remove this entry. */
1179     if(i != num_entries - 1)
1180       memcpy(p, p + SMF_ENTRY_LENGTH, (num_entries - i - 1)*SMF_ENTRY_LENGTH);
1181
1182     deleted = True;
1183     break;
1184   }
1185
1186   if(!deleted)
1187   {
1188     DEBUG(0,("del_share_mode: entry not found in share file %s\n", fname));
1189     if(buf)
1190       free(buf);
1191     return;
1192   }
1193
1194   num_entries--;
1195   SIVAL(buf,SMF_NUM_ENTRIES_OFFSET, num_entries);
1196
1197   if(num_entries == 0)
1198   {
1199     /* Deleted the last entry - remove the file. */
1200     DEBUG(5,("del_share_mode: removed last entry in share file - deleting share file %s\n",
1201              fname));
1202     if(buf)
1203       free(buf);
1204     delete_share_file(fs_p->cnum,fname);
1205     return;
1206   }
1207
1208   /* Re-write the file - and truncate it at the correct point. */
1209   if(lseek(fd, 0, SEEK_SET) != 0)
1210   {
1211     DEBUG(0,("ERROR: del_share_mode: lseek failed to reset to \
1212 position 0 for share mode file %s (%s)\n", fname, strerror(errno)));
1213     if(buf)
1214       free(buf);
1215     return;
1216   }
1217
1218   newsize = (base - buf) + (SMF_ENTRY_LENGTH*num_entries);
1219   if(write(fd, buf, newsize) != newsize)
1220   {
1221     DEBUG(0,("ERROR: del_share_mode: failed to re-write share \
1222 mode file %s (%s)\n", fname, strerror(errno)));
1223     if(buf)
1224       free(buf);
1225     return;
1226   }
1227   /* Now truncate the file at this point. */
1228   if(ftruncate(fd, newsize) != 0)
1229   {
1230     DEBUG(0,("ERROR: del_share_mode: failed to ftruncate share \
1231 mode file %s to size %d (%s)\n", fname, newsize, strerror(errno)));
1232     if(buf)
1233       free(buf);
1234     return;
1235   }
1236 }
1237   
1238 /*******************************************************************
1239 set the share mode of a file
1240 ********************************************************************/
1241 BOOL set_share_mode(share_lock_token token,int fnum, uint16 port, uint16 op_type)
1242 {
1243   files_struct *fs_p = &Files[fnum];
1244   pstring fname;
1245   int fd = (int)token;
1246   int pid = (int)getpid();
1247   struct stat sb;
1248   char *buf;
1249   int num_entries;
1250   int header_size;
1251   char *p;
1252
1253   share_name(fs_p->cnum, fs_p->fd_ptr->dev,
1254                        fs_p->fd_ptr->inode, fname);
1255
1256   if(fstat(fd, &sb) != 0)
1257   {
1258     DEBUG(0,("ERROR: set_share_mode: Failed to do stat on share file %s\n",
1259                   fname));
1260     return False;
1261   }
1262
1263   /* Sanity check for file contents (if it's not a new share file). */
1264   if(sb.st_size != 0)
1265   {
1266     int size = sb.st_size;
1267
1268     /* Allocate space for the file plus one extra entry */
1269     if((buf = (char *)malloc(sb.st_size + SMF_ENTRY_LENGTH)) == NULL)
1270     {
1271       DEBUG(0,("set_share_mode: malloc for file size %d fail !\n", 
1272                   sb.st_size + SMF_ENTRY_LENGTH));
1273       return False;
1274     }
1275  
1276     if(lseek(fd, 0, SEEK_SET) != 0)
1277     {
1278       DEBUG(0,("ERROR: set_share_mode: Failed to reset position \
1279 to 0 for share file %s (%s)\n", fname, strerror(errno)));
1280       if(buf)
1281         free(buf);
1282       return False;
1283     }
1284
1285     if (read(fd,buf,sb.st_size) != sb.st_size)
1286     {
1287       DEBUG(0,("ERROR: set_share_mode: Failed to read share file %s (%s)\n",
1288                   fname, strerror(errno)));
1289       if(buf)
1290         free(buf);
1291       return False;
1292     }   
1293   
1294     if (IVAL(buf,SMF_VERSION_OFFSET) != LOCKING_VERSION) 
1295     {
1296       DEBUG(0,("ERROR: set_share_mode: share file %s has incorrect \
1297 locking version (was %d, should be %d).\n",fname, IVAL(buf,SMF_VERSION_OFFSET), 
1298                     LOCKING_VERSION));
1299       if(buf)
1300         free(buf);
1301       delete_share_file(fs_p->cnum, fname);
1302       return False;
1303     }   
1304
1305     size -= (SMF_HEADER_LENGTH + SVAL(buf, SMF_FILENAME_LEN_OFFSET)); /* Remove the header */
1306
1307     /* The remaining size must be a multiple of SMF_ENTRY_LENGTH - error if not. */
1308     if((size % SMF_ENTRY_LENGTH) != 0)
1309     {
1310       DEBUG(0,("ERROR: set_share_mode: share file %s is an incorrect length - \
1311 deleting it.\n", fname));
1312       if(buf)
1313         free(buf);
1314       delete_share_file(fs_p->cnum, fname);
1315       return False;
1316     }
1317
1318   }
1319   else
1320   {
1321     /* New file - just use a single_entry. */
1322     if((buf = (char *)malloc(SMF_HEADER_LENGTH + 
1323                   strlen(fs_p->name) + 1 + SMF_ENTRY_LENGTH)) == NULL)
1324     {
1325       DEBUG(0,("ERROR: set_share_mode: malloc failed for single entry.\n"));
1326       return False;
1327     }
1328     SIVAL(buf,SMF_VERSION_OFFSET,LOCKING_VERSION);
1329     SIVAL(buf,SMF_NUM_ENTRIES_OFFSET,0);
1330     SSVAL(buf,SMF_FILENAME_LEN_OFFSET,strlen(fs_p->name) + 1);
1331     strcpy(buf + SMF_HEADER_LENGTH, fs_p->name);
1332   }
1333
1334   num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET);
1335   header_size = SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET);
1336   p = buf + header_size + (num_entries * SMF_ENTRY_LENGTH);
1337   SIVAL(p,SME_SEC_OFFSET,fs_p->open_time.tv_sec);
1338   SIVAL(p,SME_USEC_OFFSET,fs_p->open_time.tv_usec);
1339   SIVAL(p,SME_SHAREMODE_OFFSET,fs_p->share_mode);
1340   SIVAL(p,SME_PID_OFFSET,pid);
1341 #ifdef USE_OPLOCKS
1342   SSVAL(p,SME_PORT_OFFSET,port);
1343   SSVAL(p,SME_OPLOCK_TYPE_OFFSET,op_type);
1344 #endif /* USE_OPLOCKS */
1345
1346   num_entries++;
1347
1348   SIVAL(buf,SMF_NUM_ENTRIES_OFFSET,num_entries);
1349
1350   if(lseek(fd, 0, SEEK_SET) != 0)
1351   {
1352     DEBUG(0,("ERROR: set_share_mode: (1) Failed to reset position to \
1353 0 for share file %s (%s)\n", fname, strerror(errno)));
1354     if(buf)
1355       free(buf);
1356     return False;
1357   }
1358
1359   if (write(fd,buf,header_size + (num_entries*SMF_ENTRY_LENGTH)) != 
1360                        (header_size + (num_entries*SMF_ENTRY_LENGTH))) 
1361   {
1362     DEBUG(2,("ERROR: set_share_mode: Failed to write share file %s - \
1363 deleting it (%s).\n",fname, strerror(errno)));
1364     delete_share_file(fs_p->cnum, fname);
1365     if(buf)
1366       free(buf);
1367     return False;
1368   }
1369
1370   /* Now truncate the file at this point - just for safety. */
1371   if(ftruncate(fd, header_size + (SMF_ENTRY_LENGTH*num_entries))!= 0)
1372   {
1373     DEBUG(0,("ERROR: set_share_mode: failed to ftruncate share \
1374 mode file %s to size %d (%s)\n", fname, header_size + (SMF_ENTRY_LENGTH*num_entries), 
1375                 strerror(errno)));
1376     if(buf)
1377       free(buf);
1378     return False;
1379   }
1380
1381   if(buf)
1382     free(buf);
1383
1384   DEBUG(3,("set_share_mode: Created share file %s with \
1385 mode 0x%X pid=%d\n",fname,fs_p->share_mode,pid));
1386
1387   return True;
1388 }
1389
1390 /*******************************************************************
1391 Remove an oplock port and mode entry from a share mode.
1392 ********************************************************************/
1393 BOOL remove_share_oplock(int fnum, share_lock_token token)
1394 {
1395 #ifdef USE_OPLOCKS
1396   pstring fname;
1397   int fd = (int)token;
1398   char *buf = 0;
1399   char *base = 0;
1400   int num_entries;
1401   int fsize;
1402   int i;
1403   files_struct *fs_p = &Files[fnum];
1404   int pid;
1405   BOOL found = False;
1406   BOOL new_file;
1407
1408   share_name(fs_p->cnum, fs_p->fd_ptr->dev, 
1409                        fs_p->fd_ptr->inode, fname);
1410
1411   if(read_share_file( fs_p->cnum, fd, fname, &buf, &new_file) != 0)
1412   {
1413     DEBUG(0,("ERROR: remove_share_oplock: Failed to read share file %s\n",
1414                   fname));
1415     return False;
1416   }
1417
1418   if(new_file == True)
1419   {
1420     DEBUG(0,("ERROR: remove_share_oplock: share file %s is new (size zero), \
1421 deleting it.\n", fname));
1422     delete_share_file(fs_p->cnum, fname);
1423     return False;
1424   }
1425
1426   num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET);
1427
1428   DEBUG(5,("remove_share_oplock: share file %s has %d share mode entries.\n",
1429             fname, num_entries));
1430
1431   /* PARANOIA TEST */
1432   if(num_entries < 0)
1433   {
1434     DEBUG(0,("PANIC ERROR:remove_share_oplock: num_share_mode_entries < 0 (%d) \
1435 for share file %d\n", num_entries, fname));
1436     return False;
1437   }
1438
1439   if(num_entries == 0)
1440   {
1441     /* No entries - just delete the file. */
1442     DEBUG(0,("remove_share_oplock: share file %s has no share mode entries - deleting.\n",
1443               fname));
1444     if(buf)
1445       free(buf);
1446     delete_share_file(fs_p->cnum, fname);
1447     return False;
1448   }
1449
1450   pid = getpid();
1451
1452   /* Go through the entries looking for the particular one
1453      we have set - remove the oplock settings on it.
1454   */
1455
1456   base = buf + SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET);
1457
1458   for(i = 0; i < num_entries; i++)
1459   {
1460     char *p = base + (i*SMF_ENTRY_LENGTH);
1461
1462     if((IVAL(p,SME_SEC_OFFSET) != fs_p->open_time.tv_sec) || 
1463        (IVAL(p,SME_USEC_OFFSET) != fs_p->open_time.tv_usec) ||
1464        (IVAL(p,SME_SHAREMODE_OFFSET) != fs_p->share_mode) || 
1465        (IVAL(p,SME_PID_OFFSET) != pid))
1466       continue;
1467
1468     DEBUG(5,("remove_share_oplock: clearing oplock on entry number %d (of %d) \
1469 from the share file %s\n", i, num_entries, fname));
1470
1471     SSVAL(p,SME_PORT_OFFSET,0);
1472     SSVAL(p,SME_OPLOCK_TYPE_OFFSET,0);
1473     found = True;
1474     break;
1475   }
1476
1477   if(!found)
1478   {
1479     DEBUG(0,("remove_share_oplock: entry not found in share file %s\n", fname));
1480     if(buf)
1481       free(buf);
1482     return False;
1483   }
1484
1485   /* Re-write the file - and truncate it at the correct point. */
1486   if(lseek(fd, 0, SEEK_SET) != 0)
1487   {
1488     DEBUG(0,("ERROR: remove_share_oplock: lseek failed to reset to \
1489 position 0 for share mode file %s (%s)\n", fname, strerror(errno)));
1490     if(buf)
1491       free(buf);
1492     return False;
1493   }
1494
1495   fsize = (base - buf) + (SMF_ENTRY_LENGTH*num_entries);
1496   if(write(fd, buf, fsize) != fsize)
1497   {
1498     DEBUG(0,("ERROR: remove_share_oplock: failed to re-write share \
1499 mode file %s (%s)\n", fname, strerror(errno)));
1500     if(buf)
1501       free(buf);
1502     return False;
1503   }
1504
1505   return True;
1506
1507 #else /* USE_OPLOCKS */
1508   return False;
1509 #endif /* USE_OPLOCKS */
1510 }
1511 #endif /* FAST_SHARE_MODES */