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