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