client.c: New print queue query code from Jeff C. Foster " <jfoste@wgc.woodward...
[jelmer/samba4.git] / source / locking / locking.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    Locking functions
5    Copyright (C) Andrew Tridgell 1992-1997
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20
21    Revision History:
22
23    12 aug 96: Erik.Devriendt@te6.siemens.be
24    added support for shared memory implementation of share mode locking
25
26    May 1997. Jeremy Allison (jallison@whistle.com). Modified share mode
27    locking to deal with multiple share modes per open file.
28 */
29
30 #include "includes.h"
31 extern int DEBUGLEVEL;
32 extern connection_struct Connections[];
33 extern files_struct Files[];
34
35 /****************************************************************************
36   utility function called to see if a file region is locked
37 ****************************************************************************/
38 BOOL is_locked(int fnum,int cnum,uint32 count,uint32 offset)
39 {
40   int snum = SNUM(cnum);
41
42   if (count == 0)
43     return(False);
44
45   if (!lp_locking(snum) || !lp_strict_locking(snum))
46     return(False);
47
48   return(fcntl_lock(Files[fnum].fd_ptr->fd,F_GETLK,offset,count,
49                     (Files[fnum].can_write?F_WRLCK:F_RDLCK)));
50 }
51
52
53 /****************************************************************************
54   utility function called by locking requests
55 ****************************************************************************/
56 BOOL do_lock(int fnum,int cnum,uint32 count,uint32 offset,int *eclass,uint32 *ecode)
57 {
58   BOOL ok = False;
59
60   if (!lp_locking(SNUM(cnum)))
61     return(True);
62
63   if (count == 0) {
64     *eclass = ERRDOS;
65     *ecode = ERRnoaccess;
66     return False;
67   }
68
69   if (Files[fnum].can_lock && OPEN_FNUM(fnum) && (Files[fnum].cnum == cnum))
70     ok = fcntl_lock(Files[fnum].fd_ptr->fd,F_SETLK,offset,count,
71                     (Files[fnum].can_write?F_WRLCK:F_RDLCK));
72
73   if (!ok) {
74     *eclass = ERRDOS;
75     *ecode = ERRlock;
76     return False;
77   }
78   return True; /* Got lock */
79 }
80
81
82 /****************************************************************************
83   utility function called by unlocking requests
84 ****************************************************************************/
85 BOOL do_unlock(int fnum,int cnum,uint32 count,uint32 offset,int *eclass,uint32 *ecode)
86 {
87   BOOL ok = False;
88
89   if (!lp_locking(SNUM(cnum)))
90     return(True);
91
92   if (Files[fnum].can_lock && OPEN_FNUM(fnum) && (Files[fnum].cnum == cnum))
93     ok = fcntl_lock(Files[fnum].fd_ptr->fd,F_SETLK,offset,count,F_UNLCK);
94    
95   if (!ok) {
96     *eclass = ERRDOS;
97     *ecode = ERRlock;
98     return False;
99   }
100   return True; /* Did unlock */
101 }
102
103 #ifdef FAST_SHARE_MODES
104 /*******************************************************************
105   initialize the shared memory for share_mode management 
106   ******************************************************************/
107 BOOL start_share_mode_mgmt(void)
108 {
109    pstring shmem_file_name;
110    
111   strcpy(shmem_file_name,lp_lockdir());
112   if (!directory_exist(shmem_file_name,NULL))
113     mkdir(shmem_file_name,0755);
114   trim_string(shmem_file_name,"","/");
115   if (!*shmem_file_name) return(False);
116   strcat(shmem_file_name, "/SHARE_MEM_FILE");
117   return smb_shm_open(shmem_file_name, lp_shmem_size());
118 }
119
120
121 /*******************************************************************
122   deinitialize the shared memory for share_mode management 
123   ******************************************************************/
124 BOOL stop_share_mode_mgmt(void)
125 {
126    return smb_shm_close();
127 }
128
129 /*******************************************************************
130   lock a hash bucket entry in shared memory for share_mode management 
131   ******************************************************************/
132 BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok)
133 {
134   return smb_shm_lock_hash_entry(HASH_ENTRY(dev, inode));
135 }
136
137 /*******************************************************************
138   unlock a hash bucket entry in shared memory for share_mode management 
139   ******************************************************************/
140 BOOL unlock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token token)
141 {
142   return smb_shm_unlock_hash_entry(HASH_ENTRY(dev, inode));
143 }
144
145 /*******************************************************************
146 get all share mode entries in shared memory for a dev/inode pair.
147 ********************************************************************/
148 int get_share_modes(int cnum, share_lock_token token, uint32 dev, uint32 inode, 
149                     min_share_mode_entry **old_shares)
150 {
151   smb_shm_offset_t *mode_array;
152   unsigned int hash_entry = HASH_ENTRY(dev, inode); 
153   share_mode_record *file_scanner_p;
154   share_mode_record *file_prev_p;
155   share_mode_entry *entry_scanner_p;
156   share_mode_entry *entry_prev_p;
157   int num_entries;
158   int num_entries_copied;
159   BOOL found = False;
160   min_share_mode_entry *share_array = (min_share_mode_entry *)0;
161
162   *old_shares = 0;
163
164   if(hash_entry > lp_shmem_hash_size() )
165   {
166     DEBUG(0, 
167       ("PANIC ERROR : get_share_modes (FAST_SHARE_MODES): hash_entry %d too large \
168 (max = %d)\n",
169       hash_entry, lp_shmem_hash_size() ));
170     return 0;
171   }
172
173   mode_array = (smb_shm_offset_t *)smb_shm_offset2addr(smb_shm_get_userdef_off());
174   
175   if(mode_array[hash_entry] == NULL_OFFSET)
176   {
177     DEBUG(5,("get_share_modes (FAST_SHARE_MODES): hash bucket %d empty\n", hash_entry));
178     return 0;
179   }
180
181   file_scanner_p = (share_mode_record *)smb_shm_offset2addr(mode_array[hash_entry]);
182   file_prev_p = file_scanner_p;
183   while(file_scanner_p)
184   {
185      if( (file_scanner_p->st_dev == dev) && (file_scanner_p->st_ino == inode) )
186      {
187         found = True;
188         break;
189      }
190      else
191      {
192         file_prev_p = file_scanner_p ;
193         file_scanner_p = (share_mode_record *)smb_shm_offset2addr(
194                                                 file_scanner_p->next_offset);
195      }
196   }
197   
198   if(!found)
199   {
200      DEBUG(5,("get_share_modes (FAST_SHARE_MODES): no entry for \
201 file dev = %d, ino = %d in hash_bucket %d\n", dev, inode, hash_entry));
202      return (0);
203   }
204   
205   if(file_scanner_p->locking_version != LOCKING_VERSION)
206   {
207      DEBUG(0,("ERROR:get_share_modes (FAST_SHARE_MODES): Deleting old share mode \
208 record due to old locking version %d for file dev = %d, inode = %d in hash \
209 bucket %d",file_scanner_p->locking_version, dev, inode, hash_entry));
210      if(file_prev_p == file_scanner_p)
211         mode_array[hash_entry] = file_scanner_p->next_offset;
212      else
213         file_prev_p->next_offset = file_scanner_p->next_offset;
214      smb_shm_free(smb_shm_addr2offset(file_scanner_p));
215      return (0);
216   }
217
218   /* Allocate the old_shares array */
219   num_entries = file_scanner_p->num_share_mode_entries;
220   if(num_entries)
221   {
222     *old_shares = share_array = (min_share_mode_entry *)
223                  malloc(num_entries * sizeof(min_share_mode_entry));
224     if(*old_shares == 0)
225     {
226       DEBUG(0,("get_share_modes (FAST_SHARE_MODES): malloc fail !\n"));
227       return 0;
228     }
229   }
230
231   num_entries_copied = 0;
232   
233   entry_scanner_p = (share_mode_entry*)smb_shm_offset2addr(
234                                            file_scanner_p->share_mode_entries);
235   entry_prev_p = entry_scanner_p;
236   while(entry_scanner_p)
237   {
238     int pid = entry_scanner_p->pid;
239
240     if (pid && !process_exists(pid))
241     {
242       /* Delete this share mode entry */
243       share_mode_entry *delete_entry_p = entry_scanner_p;
244
245       if(entry_prev_p == entry_scanner_p)
246       {
247         /* We are at start of list */
248         file_scanner_p->share_mode_entries = entry_scanner_p->next_share_mode_entry;
249         entry_scanner_p = (share_mode_entry*)smb_shm_offset2addr(
250                                            file_scanner_p->share_mode_entries);
251         entry_prev_p = entry_scanner_p;
252       }
253       else
254       {
255         entry_prev_p->next_share_mode_entry = entry_scanner_p->next_share_mode_entry;
256         entry_scanner_p = (share_mode_entry*)
257                            smb_shm_offset2addr(entry_scanner_p->next_share_mode_entry);
258       }
259       /* Decrement the number of share mode entries on this share mode record */
260       file_scanner_p->num_share_mode_entries -= 1;
261
262       /* PARANOIA TEST */
263       if(file_scanner_p->num_share_mode_entries < 0)
264       {
265         DEBUG(0,("PANIC ERROR:get_share_mode (FAST_SHARE_MODES): num_share_mode_entries < 0 (%d) \
266 for dev = %d, ino = %d, hashbucket %d\n", file_scanner_p->num_share_mode_entries,
267              dev, inode, hash_entry));
268         return 0;
269       }
270
271       DEBUG(0,("get_share_modes (FAST_SHARE_MODES): process %d no longer exists and \
272 it left a share mode entry with mode 0x%X for file dev = %d, ino = %d in hash \
273 bucket (number of entries now = %d)\n", 
274             pid, entry_scanner_p->share_mode, dev, inode, hash_entry,
275             file_scanner_p->num_share_mode_entries));
276
277       smb_shm_free(smb_shm_addr2offset(delete_entry_p));
278     } 
279     else
280     {
281        /* This is a valid share mode entry and the process that
282            created it still exists. Copy it into the output array.
283        */
284        share_array[num_entries_copied].pid = entry_scanner_p->pid;
285        share_array[num_entries_copied].share_mode = entry_scanner_p->share_mode;
286        memcpy(&share_array[num_entries_copied].time, &entry_scanner_p->time,
287               sizeof(struct timeval));
288        num_entries_copied++;
289        DEBUG(5,("get_share_modes (FAST_SHARE_MODES): Read share mode \
290 record mode 0x%X pid=%d\n", entry_scanner_p->share_mode, entry_scanner_p->pid));
291        entry_prev_p = entry_scanner_p;
292        entry_scanner_p = (share_mode_entry *)
293                            smb_shm_offset2addr(entry_scanner_p->next_share_mode_entry);
294     }
295   }
296   
297   /* If no valid share mode entries were found then this record shouldn't exist ! */
298   if(num_entries_copied == 0)
299   {
300     DEBUG(0,("get_share_modes (FAST_SHARE_MODES): file with dev %d, inode %d in \
301 hash bucket %d has a share mode record but no entries - deleting\n", 
302                  dev, inode, hash_entry));
303     if(*old_shares)
304       free((char *)old_shares);
305     *old_shares = 0;
306
307     if(file_prev_p == file_scanner_p)
308       mode_array[hash_entry] = file_scanner_p->next_offset;
309     else
310       file_prev_p->next_offset = file_scanner_p->next_offset;
311     smb_shm_free(smb_shm_addr2offset(file_scanner_p));
312   }
313
314   DEBUG(5,("get_share_modes (FAST_SHARE_MODES): file with dev %d, inode %d in \
315 hash bucket %d returning %d entries\n", dev, inode, hash_entry,
316                          num_entries_copied));
317
318   return(num_entries_copied);
319 }  
320
321 /*******************************************************************
322 del the share mode of a file.
323 ********************************************************************/
324 void del_share_mode(share_lock_token token, int fnum)
325 {
326   uint32 dev, inode;
327   smb_shm_offset_t *mode_array;
328   unsigned int hash_entry;
329   share_mode_record *file_scanner_p;
330   share_mode_record *file_prev_p;
331   share_mode_entry *entry_scanner_p;
332   share_mode_entry *entry_prev_p;
333   BOOL found = False;
334   int pid = getpid();
335
336   dev = Files[fnum].fd_ptr->dev;
337   inode = Files[fnum].fd_ptr->inode;
338
339   hash_entry = HASH_ENTRY(dev, inode);
340
341   if(hash_entry > lp_shmem_hash_size() )
342   {
343     DEBUG(0,
344       ("PANIC ERROR:del_share_mode (FAST_SHARE_MODES): hash_entry %d too large \
345 (max = %d)\n",
346       hash_entry, lp_shmem_hash_size() ));
347     return;
348   }
349
350   mode_array = (smb_shm_offset_t *)smb_shm_offset2addr(smb_shm_get_userdef_off());
351  
352   if(mode_array[hash_entry] == NULL_OFFSET)
353   {  
354     DEBUG(0,("PANIC ERROR:del_share_mode (FAST_SHARE_MODES): hash bucket %d empty\n", 
355                   hash_entry));
356     return;
357   }  
358   
359   file_scanner_p = (share_mode_record *)smb_shm_offset2addr(mode_array[hash_entry]);
360   file_prev_p = file_scanner_p;
361
362   while(file_scanner_p)
363   {
364      if( (file_scanner_p->st_dev == dev) && (file_scanner_p->st_ino == inode) )
365      {
366         found = True;
367         break;
368      }
369      else
370      {
371         file_prev_p = file_scanner_p ;
372         file_scanner_p = (share_mode_record *)
373                           smb_shm_offset2addr(file_scanner_p->next_offset);
374      }
375   }
376     
377   if(!found)
378   {
379      DEBUG(0,("ERROR:del_share_mode (FAST_SHARE_MODES): no entry found for dev %d, \
380 inode %d in hash bucket %d\n", dev, inode, hash_entry));
381      return;
382   }
383   
384   if(file_scanner_p->locking_version != LOCKING_VERSION)
385   {
386      DEBUG(0,("ERROR: del_share_modes (FAST_SHARE_MODES): Deleting old share mode \
387 record due to old locking version %d for file dev %d, inode %d hash bucket %d\n",
388        file_scanner_p->locking_version, dev, inode, hash_entry ));
389      if(file_prev_p == file_scanner_p)
390         mode_array[hash_entry] = file_scanner_p->next_offset;
391      else
392         file_prev_p->next_offset = file_scanner_p->next_offset;
393      smb_shm_free(smb_shm_addr2offset(file_scanner_p));
394      return;
395   }
396
397   found = False;
398   entry_scanner_p = (share_mode_entry*)smb_shm_offset2addr(
399                                            file_scanner_p->share_mode_entries);
400   entry_prev_p = entry_scanner_p;
401   while(entry_scanner_p)
402   {
403     if( (pid == entry_scanner_p->pid) && 
404           (memcmp(&entry_scanner_p->time, 
405                  &Files[fnum].open_time,sizeof(struct timeval)) == 0) )
406     {
407       found = True;
408       break;
409     }
410     else
411     {
412       entry_prev_p = entry_scanner_p;
413       entry_scanner_p = (share_mode_entry *)
414                           smb_shm_offset2addr(entry_scanner_p->next_share_mode_entry);
415     }
416   } 
417
418   if (found)
419   {
420     /* Decrement the number of entries in the record. */
421     file_scanner_p->num_share_mode_entries -= 1;
422
423     DEBUG(2,("del_share_modes (FAST_SHARE_MODES): \
424 Deleting share mode entry dev = %d, inode = %d in hash bucket %d (num entries now = %d)\n",
425               dev, inode, hash_entry, file_scanner_p->num_share_mode_entries));
426     if(entry_prev_p == entry_scanner_p)
427       /* We are at start of list */
428       file_scanner_p->share_mode_entries = entry_scanner_p->next_share_mode_entry;
429     else
430       entry_prev_p->next_share_mode_entry = entry_scanner_p->next_share_mode_entry;
431     smb_shm_free(smb_shm_addr2offset(entry_scanner_p));
432
433     /* PARANOIA TEST */
434     if(file_scanner_p->num_share_mode_entries < 0)
435     {
436       DEBUG(0,("PANIC ERROR:del_share_mode (FAST_SHARE_MODES): num_share_mode_entries < 0 (%d) \
437 for dev = %d, ino = %d, hashbucket %d\n", file_scanner_p->num_share_mode_entries,
438            dev, inode, hash_entry));
439       return;
440     }
441
442     /* If we deleted the last share mode entry then remove the share mode record. */
443     if(file_scanner_p->num_share_mode_entries == 0)
444       {
445       DEBUG(2,("del_share_modes (FAST_SHARE_MODES): num entries = 0, deleting share_mode \
446 record dev = %d, inode = %d in hash bucket %d\n", dev, inode, hash_entry));
447       if(file_prev_p == file_scanner_p)
448         mode_array[hash_entry] = file_scanner_p->next_offset;
449       else
450         file_prev_p->next_offset = file_scanner_p->next_offset;
451       smb_shm_free(smb_shm_addr2offset(file_scanner_p));
452       }
453   }
454   else
455   {
456     DEBUG(0,("ERROR: del_share_modes (FAST_SHARE_MODES): No share mode record found \
457 dev = %d, inode = %d in hash bucket %d\n", dev, inode, hash_entry));
458   }
459 }
460
461 /*******************************************************************
462 set the share mode of a file. Return False on fail, True on success.
463 ********************************************************************/
464 BOOL set_share_mode(share_lock_token token, int fnum)
465 {
466   files_struct *fs_p = &Files[fnum];
467   int32 dev, inode;
468   smb_shm_offset_t *mode_array;
469   unsigned int hash_entry;
470   share_mode_record *file_scanner_p;
471   share_mode_record *file_prev_p;
472   share_mode_entry *new_entry_p;
473   smb_shm_offset_t new_entry_offset;
474   BOOL found = False;
475
476   dev = fs_p->fd_ptr->dev;
477   inode = fs_p->fd_ptr->inode;
478
479   hash_entry = HASH_ENTRY(dev, inode);
480   if(hash_entry > lp_shmem_hash_size() )
481   {
482     DEBUG(0,
483       ("PANIC ERROR:set_share_mode (FAST_SHARE_MODES): hash_entry %d too large \
484 (max = %d)\n",
485       hash_entry, lp_shmem_hash_size() ));
486     return False;
487   }
488
489   mode_array = (smb_shm_offset_t *)smb_shm_offset2addr(smb_shm_get_userdef_off());
490
491   file_scanner_p = (share_mode_record *)smb_shm_offset2addr(mode_array[hash_entry]);
492   file_prev_p = file_scanner_p;
493   
494   while(file_scanner_p)
495   {
496      if( (file_scanner_p->st_dev == dev) && (file_scanner_p->st_ino == inode) )
497      {
498         found = True;
499         break;
500      }
501      else
502      {
503         file_prev_p = file_scanner_p ;
504         file_scanner_p = (share_mode_record *)
505                           smb_shm_offset2addr(file_scanner_p->next_offset);
506      }
507   }
508   
509   if(!found)
510   {
511     /* We must create a share_mode_record */
512     share_mode_record *new_mode_p = NULL;
513     smb_shm_offset_t new_offset = smb_shm_alloc( sizeof(share_mode_record) +
514                                         strlen(fs_p->name) + 1);
515     if(new_offset == NULL_OFFSET)
516     {
517       DEBUG(0,("ERROR:set_share_mode (FAST_SHARE_MODES): smb_shm_alloc fail !\n"));
518       return False;
519     }
520     new_mode_p = smb_shm_offset2addr(new_offset);
521     new_mode_p->locking_version = LOCKING_VERSION;
522     new_mode_p->st_dev = dev;
523     new_mode_p->st_ino = inode;
524     new_mode_p->num_share_mode_entries = 0;
525     new_mode_p->share_mode_entries = NULL_OFFSET;
526     strcpy(new_mode_p->file_name, fs_p->name);
527
528     /* Chain onto the start of the hash chain (in the hope we will be used first). */
529     new_mode_p->next_offset = mode_array[hash_entry];
530     mode_array[hash_entry] = new_offset;
531
532     file_scanner_p = new_mode_p;
533
534     DEBUG(3,("set_share_mode (FAST_SHARE_MODES): Created share record for %s (dev %d \
535 inode %d in hash bucket %d\n", fs_p->name, dev, inode, hash_entry));
536   }
537  
538   /* Now create the share mode entry */ 
539   new_entry_offset = smb_shm_alloc( sizeof(share_mode_entry));
540   if(new_entry_offset == NULL_OFFSET)
541   {
542     smb_shm_offset_t delete_offset = mode_array[hash_entry];
543     DEBUG(0,("ERROR:set_share_mode (FAST_SHARE_MODES): smb_shm_alloc fail 1!\n"));
544     /* Unlink the damaged record */
545     mode_array[hash_entry] = file_scanner_p->next_offset;
546     /* And delete it */
547     smb_shm_free( delete_offset );
548     return False;
549   }
550
551   new_entry_p = smb_shm_offset2addr(new_entry_offset);
552
553   new_entry_p->pid = getpid();
554   new_entry_p->share_mode = fs_p->share_mode;
555   memcpy( (char *)&new_entry_p->time, (char *)&fs_p->open_time, sizeof(struct timeval));
556
557   /* Chain onto the share_mode_record */
558   new_entry_p->next_share_mode_entry = file_scanner_p->share_mode_entries;
559   file_scanner_p->share_mode_entries = new_entry_offset;
560
561   /* PARANOIA TEST */
562   if(file_scanner_p->num_share_mode_entries < 0)
563   {
564     DEBUG(0,("PANIC ERROR:set_share_mode (FAST_SHARE_MODES): num_share_mode_entries < 0 (%d) \
565 for dev = %d, ino = %d, hashbucket %d\n", file_scanner_p->num_share_mode_entries,
566          dev, inode, hash_entry));
567     return False;
568   }
569
570   /* Increment the share_mode_entries counter */
571   file_scanner_p->num_share_mode_entries += 1;
572
573   DEBUG(3,("set_share_mode (FAST_SHARE_MODES): Created share entry for %s with mode \
574 0x%X pid=%d (num_entries now = %d)\n",fs_p->name, fs_p->share_mode, new_entry_p->pid,
575                              file_scanner_p->num_share_mode_entries));
576
577   return(True);
578 }
579
580 #else /* FAST_SHARE_MODES */
581
582 /* SHARE MODE LOCKS USING SLOW DESCRIPTION FILES */
583
584 /*******************************************************************
585   name a share file
586   ******************************************************************/
587 static BOOL share_name(int cnum, uint32 dev, uint32 inode, char *name)
588 {
589   strcpy(name,lp_lockdir());
590   standard_sub(cnum,name);
591   trim_string(name,"","/");
592   if (!*name) return(False);
593   name += strlen(name);
594   
595   sprintf(name,"/share.%u.%u",dev,inode);
596   return(True);
597 }
598
599 /*******************************************************************
600   lock a share mode file.
601   ******************************************************************/
602 BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok)
603 {
604   pstring fname;
605   int fd;
606
607   *ptok = (share_lock_token)-1;
608
609   if(!share_name(cnum, dev, inode, fname))
610     return False;
611
612   {
613     int old_umask;
614     unbecome_user();
615     old_umask = umask(0);
616 #ifdef SECURE_SHARE_MODES
617     fd = (share_lock_token)open(fname,O_RDWR|O_CREAT,0600);
618 #else /* SECURE_SHARE_MODES */
619     fd = (share_lock_token)open(fname,O_RDWR|O_CREAT,0644);
620 #endif /* SECURE_SHARE_MODES */
621     umask(old_umask);
622     if(!become_user(cnum,Connections[cnum].vuid))
623     {
624       DEBUG(0,("lock_share_entry: Can't become connected user!\n"));
625       close(fd);
626       return False;
627     }
628     /* We need to change directory back to the connection root. */
629     if (ChDir(Connections[cnum].connectpath) != 0)
630     {
631       DEBUG(0,("lock_share_entry: Can't change directory to %s (%s)\n",
632               Connections[cnum].connectpath, strerror(errno)));
633       close(fd);
634       return False;  
635     }
636   }
637
638   /* At this point we have an open fd to the share mode file. 
639      Lock the first byte exclusively to signify a lock. */
640   if(fcntl_lock(fd, F_SETLKW, 0, 1, F_WRLCK) == False)
641    {
642       DEBUG(0,("ERROR lock_share_entry: fcntl_lock failed with %s\n",
643                   strerror(errno)));   
644       close(fd);
645       return False;
646    }
647
648    *ptok = (share_lock_token)fd;
649    return True;
650 }
651
652 /*******************************************************************
653   unlock a share mode file.
654   ******************************************************************/
655 BOOL unlock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token token)
656 {
657   int fd = (int)token;
658   int ret = True;
659
660   /* token is the fd of the open share mode file. */
661   /* Unlock the first byte. */
662   if(fcntl_lock(fd, F_SETLKW, 0, 1, F_UNLCK) == False)
663    { 
664       DEBUG(0,("ERROR unlock_share_entry: fcntl_lock failed with %s\n",
665                       strerror(errno)));   
666       ret = False;
667    }
668  
669   close((int)token);
670   return ret;
671 }
672
673 /*******************************************************************
674 Force a share file to be deleted.
675 ********************************************************************/
676
677 static int delete_share_file( int cnum, char *fname )
678 {
679   unbecome_user();
680   if(unlink(fname) != 0)
681   {
682     DEBUG(0,("delete_share_file: Can't delete share file %s (%s)\n",
683             fname, strerror(errno)));
684   }
685
686   DEBUG(5,("delete_share_file: Deleted share file %s\n", fname));
687
688   if(!become_user(cnum,Connections[cnum].vuid))
689   {
690     DEBUG(0,("delete_share_file: Can't become connected user!\n"));
691     return -1;
692   }
693   /* We need to change directory back to the connection root. */
694   if (ChDir(Connections[cnum].connectpath) != 0)
695   {
696     DEBUG(0,("delete_share_file: Can't change directory to %s (%s)\n",
697             Connections[cnum].connectpath, strerror(errno)));
698     return -1;  
699   }
700   return 0;
701 }
702
703 /*******************************************************************
704 Read a share file into a buffer.
705 ********************************************************************/
706
707 static int read_share_file(int cnum, int fd, char *fname, char **out, BOOL *p_new_file)
708 {
709   struct stat sb;
710   char *buf;
711   int size;
712
713   *out = 0;
714   *p_new_file = False;
715
716   if(fstat(fd, &sb) != 0)
717   {
718     DEBUG(0,("ERROR: read_share_file: Failed to do stat on share file %s (%s)\n",
719                   fname, strerror(errno)));
720     return -1;
721   }
722
723   if(sb.st_size == 0)
724   {
725      *p_new_file = True;
726      return 0;
727   }
728
729   /* Allocate space for the file */
730   if((buf = (char *)malloc(sb.st_size)) == NULL)
731   {
732     DEBUG(0,("read_share_file: malloc for file size %d fail !\n", sb.st_size));
733     return -1;
734   }
735   
736   if(lseek(fd, 0, SEEK_SET) != 0)
737   {
738     DEBUG(0,("ERROR: read_share_file: Failed to reset position to 0 \
739 for share file %s (%s)\n", fname, strerror(errno)));
740     if(buf)
741       free(buf);
742     return -1;
743   }
744   
745   if (read(fd,buf,sb.st_size) != sb.st_size)
746   {
747     DEBUG(0,("ERROR: read_share_file: Failed to read share file %s (%s)\n",
748                fname, strerror(errno)));
749     if(buf)
750       free(buf);
751     return -1;
752   }
753   
754   if (IVAL(buf,0) != LOCKING_VERSION) {
755     DEBUG(0,("ERROR: read_share_file: share file %s has incorrect \
756 locking version (was %d, should be %d).\n",fname, IVAL(buf,0), LOCKING_VERSION));
757     if(buf)
758       free(buf);
759     delete_share_file(cnum, fname);
760     return -1;
761   }
762
763   /* Sanity check for file contents */
764   size = sb.st_size;
765   size -= 10; /* Remove the header */
766
767   /* Remove the filename component. */
768   size -= SVAL(buf, 8);
769
770   /* The remaining size must be a multiple of 16 - error if not. */
771   if((size % 16) != 0)
772   {
773     DEBUG(0,("ERROR: read_share_file: share file %s is an incorrect length - \
774 deleting it.\n", fname));
775     if(buf)
776       free(buf);
777     delete_share_file(cnum, fname);
778     return -1;
779   }
780
781   *out = buf;
782   return 0;
783 }
784
785 /*******************************************************************
786 get all share mode entries in a share file for a dev/inode pair.
787 ********************************************************************/
788 int get_share_modes(int cnum, share_lock_token token, uint32 dev, uint32 inode, 
789                     min_share_mode_entry **old_shares)
790 {
791   int fd = (int)token;
792   pstring fname;
793   int i;
794   int num_entries;
795   int num_entries_copied;
796   int newsize;
797   min_share_mode_entry *share_array;
798   char *buf = 0;
799   char *base = 0;
800   BOOL new_file;
801
802   *old_shares = 0;
803
804   /* Read the share file header - this is of the form:
805      0   -  locking version.
806      4   -  number of share mode entries.
807      8   -  2 byte name length
808      [n bytes] file name (zero terminated).
809
810    Followed by <n> share mode entries of the form :
811
812      0   -  tv_sec
813      4   -  tv_usec
814      8   -  share_mode
815     12   -  pid
816
817   */
818
819   share_name(cnum, dev, inode, fname);
820
821   if(read_share_file( cnum, fd, fname, &buf, &new_file) != 0)
822   {
823     DEBUG(0,("ERROR: get_share_modes: Failed to read share file %s\n",
824                   fname));
825     return 0;
826   }
827
828   if(new_file == True)
829     return 0;
830
831   num_entries = IVAL(buf,4);
832
833   DEBUG(5,("get_share_modes: share file %s has %d share mode entries.\n",
834             fname, num_entries));
835
836   /* PARANOIA TEST */
837   if(num_entries < 0)
838   {
839     DEBUG(0,("PANIC ERROR:get_share_mode: num_share_mode_entries < 0 (%d) \
840 for share file %d\n", num_entries, fname));
841     return 0;
842   }
843
844   if(num_entries)
845   {
846     *old_shares = share_array = (min_share_mode_entry *)
847                  malloc(num_entries * sizeof(min_share_mode_entry));
848     if(*old_shares == 0)
849     {
850       DEBUG(0,("get_share_modes: malloc fail !\n"));
851       return 0;
852     }
853   } 
854   else
855   {
856     /* No entries - just delete the file. */
857     DEBUG(0,("get_share_modes: share file %s has no share mode entries - deleting.\n",
858               fname));
859     if(buf)
860       free(buf);
861     delete_share_file(cnum, fname);
862     return 0;
863   }
864
865   num_entries_copied = 0;
866   base = buf + 10 + SVAL(buf,8);
867
868   for( i = 0; i < num_entries; i++)
869   {
870     int pid;
871     char *p = base + (i*16);
872
873     pid = IVAL(p,12);
874
875     if(!process_exists(pid))
876     {
877       DEBUG(0,("get_share_modes: process %d no longer exists and \
878 it left a share mode entry with mode 0x%X in share file %s\n",
879             pid, IVAL(p,8), fname));
880       continue;
881     }
882     share_array[num_entries_copied].time.tv_sec = IVAL(p,0);
883     share_array[num_entries_copied].time.tv_usec = IVAL(p,4);
884     share_array[num_entries_copied].share_mode = IVAL(p,8);
885     share_array[num_entries_copied].pid = pid;
886
887     num_entries_copied++;
888   }
889
890   if(num_entries_copied == 0)
891   {
892     /* Delete the whole file. */
893     DEBUG(0,("get_share_modes: share file %s had no valid entries - deleting it !\n",
894              fname));
895     if(*old_shares)
896       free((char *)*old_shares);
897     *old_shares = 0;
898     if(buf)
899       free(buf);
900     delete_share_file(cnum, fname);
901     return 0;
902   }
903
904   /* If we deleted some entries we need to re-write the whole number of
905      share mode entries back into the file. */
906
907   if(num_entries_copied != num_entries)
908   {
909     if(lseek(fd, 0, SEEK_SET) != 0)
910     {
911       DEBUG(0,("ERROR: get_share_modes: lseek failed to reset to \
912 position 0 for share mode file %s (%s)\n", fname, strerror(errno)));
913       if(*old_shares)
914         free((char *)*old_shares);
915       *old_shares = 0;
916       if(buf)
917         free(buf);
918       return 0;
919     }
920
921     SIVAL(buf, 4, num_entries_copied);
922     for( i = 0; i < num_entries_copied; i++)
923     {
924       char *p = base + (i*16);
925
926       SIVAL(p,12,share_array[i].pid);
927       SIVAL(p,8,share_array[i].share_mode);
928       SIVAL(p,0,share_array[i].time.tv_sec);
929       SIVAL(p,4,share_array[i].time.tv_usec);
930     }
931
932     newsize = (base - buf) + (16*num_entries_copied);
933     if(write(fd, buf, newsize) != newsize)
934     {
935       DEBUG(0,("ERROR: get_share_modes: failed to re-write share \
936 mode file %s (%s)\n", fname, strerror(errno)));
937       if(*old_shares)
938         free((char *)*old_shares);
939       *old_shares = 0;
940       if(buf)
941         free(buf);
942       return 0;
943     }
944     /* Now truncate the file at this point. */
945     if(ftruncate(fd, newsize)!= 0)
946     {
947       DEBUG(0,("ERROR: get_share_modes: failed to ftruncate share \
948 mode file %s to size %d (%s)\n", fname, newsize, strerror(errno)));
949       if(*old_shares)
950         free((char *)*old_shares);
951       *old_shares = 0;
952       if(buf)
953         free(buf);
954       return 0;
955     }
956   }
957
958   if(buf)
959     free(buf);
960
961   DEBUG(5,("get_share_modes: Read share file %s returning %d entries\n",fname,
962             num_entries_copied));
963
964   return num_entries_copied;
965 }
966
967 /*******************************************************************
968 del a share mode from a share mode file.
969 ********************************************************************/
970 void del_share_mode(share_lock_token token, int fnum)
971 {
972   pstring fname;
973   int fd = (int)token;
974   char *buf = 0;
975   char *base = 0;
976   int num_entries;
977   int newsize;
978   int i;
979   files_struct *fs_p = &Files[fnum];
980   int pid;
981   BOOL deleted = False;
982   BOOL new_file;
983
984   share_name(fs_p->cnum, fs_p->fd_ptr->dev, 
985                        fs_p->fd_ptr->inode, fname);
986
987   if(read_share_file( fs_p->cnum, fd, fname, &buf, &new_file) != 0)
988   {
989     DEBUG(0,("ERROR: del_share_mode: Failed to read share file %s\n",
990                   fname));
991     return;
992   }
993
994   if(new_file == True)
995   {
996     DEBUG(0,("ERROR:del_share_mode: share file %s is new (size zero), deleting it.\n",
997               fname));
998     delete_share_file(fs_p->cnum, fname);
999     return;
1000   }
1001
1002   num_entries = IVAL(buf,4);
1003
1004   DEBUG(5,("del_share_mode: share file %s has %d share mode entries.\n",
1005             fname, num_entries));
1006
1007   /* PARANOIA TEST */
1008   if(num_entries < 0)
1009   {
1010     DEBUG(0,("PANIC ERROR:del_share_mode: num_share_mode_entries < 0 (%d) \
1011 for share file %d\n", num_entries, fname));
1012     return;
1013   }
1014
1015   if(num_entries == 0)
1016   {
1017     /* No entries - just delete the file. */
1018     DEBUG(0,("del_share_mode: share file %s has no share mode entries - deleting.\n",
1019               fname));
1020     if(buf)
1021       free(buf);
1022     delete_share_file(fs_p->cnum, fname);
1023     return;
1024   }
1025
1026   pid = getpid();
1027
1028   /* Go through the entries looking for the particular one
1029      we have set - delete it.
1030   */
1031
1032   base = buf + 10 + SVAL(buf,8);
1033
1034   for(i = 0; i < num_entries; i++)
1035   {
1036     char *p = base + (i*16);
1037
1038     if((IVAL(p,0) != fs_p->open_time.tv_sec) || (IVAL(p,4) != fs_p->open_time.tv_usec) ||
1039         (IVAL(p,8) != fs_p->share_mode) || (IVAL(p,12) != pid))
1040       continue;
1041
1042     DEBUG(5,("del_share_mode: deleting entry number %d (of %d) from the share file %s\n",
1043              i, num_entries, fname));
1044
1045     /* Remove this entry. */
1046     if(i != num_entries - 1)
1047       memcpy(p, p + 16, (num_entries - i - 1)*16);
1048
1049     deleted = True;
1050     break;
1051   }
1052
1053   if(!deleted)
1054   {
1055     DEBUG(0,("del_share_mode: entry not found in share file %s\n", fname));
1056     if(buf)
1057       free(buf);
1058     return;
1059   }
1060
1061   num_entries--;
1062   SIVAL(buf,4, num_entries);
1063
1064   if(num_entries == 0)
1065   {
1066     /* Deleted the last entry - remove the file. */
1067     DEBUG(5,("del_share_mode: removed last entry in share file - deleting share file %s\n",
1068              fname));
1069     if(buf)
1070       free(buf);
1071     delete_share_file(fs_p->cnum,fname);
1072     return;
1073   }
1074
1075   /* Re-write the file - and truncate it at the correct point. */
1076   if(lseek(fd, 0, SEEK_SET) != 0)
1077     {
1078       DEBUG(0,("ERROR: del_share_mode: lseek failed to reset to \
1079 position 0 for share mode file %s (%s)\n", fname, strerror(errno)));
1080       if(buf)
1081         free(buf);
1082       return;
1083     }
1084
1085   newsize = (base - buf) + (16*num_entries);
1086   if(write(fd, buf, newsize) != newsize)
1087     {
1088       DEBUG(0,("ERROR: del_share_mode: failed to re-write share \
1089 mode file %s (%s)\n", fname, strerror(errno)));
1090       if(buf)
1091         free(buf);
1092       return;
1093     }
1094   /* Now truncate the file at this point. */
1095   if(ftruncate(fd, newsize) != 0)
1096   {
1097     DEBUG(0,("ERROR: del_share_mode: failed to ftruncate share \
1098 mode file %s to size %d (%s)\n", fname, newsize, strerror(errno)));
1099     if(buf)
1100       free(buf);
1101     return;
1102   }
1103 }
1104   
1105 /*******************************************************************
1106 set the share mode of a file
1107 ********************************************************************/
1108 BOOL set_share_mode(share_lock_token token,int fnum)
1109 {
1110   files_struct *fs_p = &Files[fnum];
1111   pstring fname;
1112   int fd = (int)token;
1113   int pid = (int)getpid();
1114   struct stat sb;
1115   char *buf;
1116   int num_entries;
1117   int header_size;
1118   char *p;
1119
1120   share_name(fs_p->cnum, fs_p->fd_ptr->dev,
1121                        fs_p->fd_ptr->inode, fname);
1122
1123   if(fstat(fd, &sb) != 0)
1124   {
1125     DEBUG(0,("ERROR: set_share_mode: Failed to do stat on share file %s\n",
1126                   fname));
1127     return False;
1128   }
1129
1130   /* Sanity check for file contents (if it's not a new share file). */
1131   if(sb.st_size != 0)
1132   {
1133     int size = sb.st_size;
1134
1135     /* Allocate space for the file plus one extra entry */
1136     if((buf = (char *)malloc(sb.st_size + 16)) == NULL)
1137     {
1138       DEBUG(0,("set_share_mode: malloc for file size %d fail !\n", sb.st_size + 16));
1139       return False;
1140     }
1141  
1142     if(lseek(fd, 0, SEEK_SET) != 0)
1143     {
1144       DEBUG(0,("ERROR: set_share_mode: Failed to reset position \
1145 to 0 for share file %s (%s)\n", fname, strerror(errno)));
1146       if(buf)
1147         free(buf);
1148       return False;
1149     }
1150
1151     if (read(fd,buf,sb.st_size) != sb.st_size)
1152     {
1153       DEBUG(0,("ERROR: set_share_mode: Failed to read share file %s (%s)\n",
1154                   fname, strerror(errno)));
1155       if(buf)
1156         free(buf);
1157       return False;
1158     }   
1159   
1160     if (IVAL(buf,0) != LOCKING_VERSION) 
1161     {
1162       DEBUG(0,("ERROR: set_share_mode: share file %s has incorrect \
1163 locking version (was %d, should be %d).\n",fname, IVAL(buf,0), LOCKING_VERSION));
1164       if(buf)
1165         free(buf);
1166       delete_share_file(fs_p->cnum, fname);
1167       return False;
1168     }   
1169
1170     size -= (10 + SVAL(buf, 8)); /* Remove the header */
1171
1172     /* The remaining size must be a multiple of 16 - error if not. */
1173     if((size % 16) != 0)
1174     {
1175       DEBUG(0,("ERROR: set_share_mode: share file %s is an incorrect length - \
1176 deleting it.\n", fname));
1177       if(buf)
1178         free(buf);
1179       delete_share_file(fs_p->cnum, fname);
1180       return False;
1181     }
1182
1183   }
1184   else
1185   {
1186     /* New file - just use a single_entry. */
1187     if((buf = (char *)malloc(10 + strlen(fs_p->name) + 1 + 16)) == NULL)
1188     {
1189       DEBUG(0,("ERROR: set_share_mode: malloc failed for single entry.\n"));
1190       return False;
1191     }
1192     SIVAL(buf,0,LOCKING_VERSION);
1193     SIVAL(buf,4,0);
1194     SSVAL(buf,8,strlen(fs_p->name) + 1);
1195     strcpy(buf + 10, fs_p->name);
1196   }
1197
1198   num_entries = IVAL(buf,4);
1199   header_size = 10 + SVAL(buf,8);
1200   p = buf + header_size + (num_entries * 16);
1201   SIVAL(p,0,fs_p->open_time.tv_sec);
1202   SIVAL(p,4,fs_p->open_time.tv_usec);
1203   SIVAL(p,8,fs_p->share_mode);
1204   SIVAL(p,12,pid);
1205
1206   num_entries++;
1207
1208   SIVAL(buf,4,num_entries);
1209
1210   if(lseek(fd, 0, SEEK_SET) != 0)
1211   {
1212     DEBUG(0,("ERROR: set_share_mode: (1) Failed to reset position to \
1213 0 for share file %s (%s)\n", fname, strerror(errno)));
1214     if(buf)
1215       free(buf);
1216     return False;
1217   }
1218
1219   if (write(fd,buf,header_size + (num_entries*16)) != (header_size + (num_entries*16))) 
1220   {
1221     DEBUG(2,("ERROR: set_share_mode: Failed to write share file %s - \
1222 deleting it (%s).\n",fname, strerror(errno)));
1223     delete_share_file(fs_p->cnum, fname);
1224     if(buf)
1225       free(buf);
1226     return False;
1227   }
1228
1229   /* Now truncate the file at this point - just for safety. */
1230   if(ftruncate(fd, header_size + (16*num_entries))!= 0)
1231   {
1232     DEBUG(0,("ERROR: set_share_mode: failed to ftruncate share \
1233 mode file %s to size %d (%s)\n", fname, header_size + (16*num_entries), strerror(errno)));
1234     if(buf)
1235       free(buf);
1236     return False;
1237   }
1238
1239   if(buf)
1240     free(buf);
1241
1242   DEBUG(3,("set_share_mode: Created share file %s with \
1243 mode 0x%X pid=%d\n",fname,fs_p->share_mode,pid));
1244
1245   return True;
1246 }
1247 #endif /* FAST_SHARE_MODES */