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