merge from the autoconf2 branch to the main branch
[kai/samba.git] / source3 / locking / locking_slow.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    slow (lockfile) locking implementation
5    Copyright (C) Andrew Tridgell 1992-1998
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    October 1997 - split into separate file (tridge)
33 */
34
35 #include "includes.h"
36
37 #ifndef FAST_SHARE_MODES
38
39 extern int DEBUGLEVEL;
40 extern connection_struct Connections[];
41 extern files_struct Files[];
42
43 /* 
44  * Locking file header lengths & offsets. 
45  */
46 #define SMF_VERSION_OFFSET 0
47 #define SMF_NUM_ENTRIES_OFFSET 4
48 #define SMF_FILENAME_LEN_OFFSET 8
49 #define SMF_HEADER_LENGTH 10
50
51 #define SMF_ENTRY_LENGTH 20
52
53 /*
54  * Share mode record offsets.
55  */
56
57 #define SME_SEC_OFFSET 0
58 #define SME_USEC_OFFSET 4
59 #define SME_SHAREMODE_OFFSET 8
60 #define SME_PID_OFFSET 12
61 #define SME_PORT_OFFSET 16
62 #define SME_OPLOCK_TYPE_OFFSET 18
63
64 /* we need world read for smbstatus to function correctly */
65 #ifdef SECURE_SHARE_MODES
66 #define SHARE_FILE_MODE 0600
67 #else
68 #define SHARE_FILE_MODE 0644
69 #endif
70
71 static int read_only;
72
73 /*******************************************************************
74   deinitialize share_mode management 
75   ******************************************************************/
76 static BOOL slow_stop_share_mode_mgmt(void)
77 {
78    return True;
79 }
80
81
82 /*******************************************************************
83   name a share file
84   ******************************************************************/
85 static BOOL share_name(int cnum, uint32 dev, uint32 inode, char *name)
86 {
87   int len;
88   pstrcpy(name,lp_lockdir());
89   trim_string(name,"","/");
90   if (!*name) return(False);
91   len = strlen(name);
92   name += len;
93   
94   slprintf(name, sizeof(pstring) - len - 1, "/share.%u.%u",dev,inode);
95   return(True);
96 }
97
98 /*******************************************************************
99 Force a share file to be deleted.
100 ********************************************************************/
101 static int delete_share_file( int cnum, char *fname )
102 {
103   if (read_only) return -1;
104
105   /* the share file could be owned by anyone, so do this as root */
106   become_root(False);
107
108   if(unlink(fname) != 0)
109   {
110     DEBUG(0,("delete_share_file: Can't delete share file %s (%s)\n",
111             fname, strerror(errno)));
112   } 
113   else 
114   {
115     DEBUG(5,("delete_share_file: Deleted share file %s\n", fname));
116   }
117
118   /* return to our previous privilage level */
119   unbecome_root(False);
120
121   return 0;
122 }
123
124 /*******************************************************************
125   lock a share mode file.
126   ******************************************************************/
127 static BOOL slow_lock_share_entry(int cnum, uint32 dev, uint32 inode, int *ptok)
128 {
129   pstring fname;
130   int fd;
131   int ret = True;
132
133   *ptok = (int)-1;
134
135   if(!share_name(cnum, dev, inode, fname))
136     return False;
137
138   if (read_only) return True;
139
140   /* we need to do this as root */
141   become_root(False);
142
143   {
144     BOOL gotlock = False;
145     /*
146      * There was a race condition in the original slow share mode code.
147      * A smbd could open a share mode file, and before getting
148      * the lock, another smbd could delete the last entry for
149      * the share mode file and delete the file entry from the
150      * directory. Thus this smbd would be left with a locked
151      * share mode fd attached to a file that no longer had a
152      * directory entry. Thus another smbd would think that
153      * there were no outstanding opens on the file. To fix
154      * this we now check we can do a stat() call on the filename
155      * before allowing the lock to proceed, and back out completely
156      * and try the open again if we cannot.
157      * Jeremy Allison (jallison@whistle.com).
158      */
159
160     do
161     {
162       struct stat dummy_stat;
163
164       fd = (int)open(fname,read_only?O_RDONLY:(O_RDWR|O_CREAT),
165                      SHARE_FILE_MODE);
166
167       if(fd < 0)
168       {
169         DEBUG(0,("ERROR lock_share_entry: failed to open share file %s. Error was %s\n",
170                   fname, strerror(errno)));
171         ret = False;
172         break;
173       }
174
175        /* At this point we have an open fd to the share mode file. 
176          Lock the first byte exclusively to signify a lock. */
177       if(fcntl_lock(fd, F_SETLKW, 0, 1, F_WRLCK) == False)
178       {
179         DEBUG(0,("ERROR lock_share_entry: fcntl_lock on file %s failed with %s\n",
180                   fname, strerror(errno)));   
181         close(fd);
182         ret = False;
183         break;
184       }
185
186       /* 
187        * If we cannot stat the filename, the file was deleted between
188        * the open and the lock call. Back out and try again.
189        */
190
191       if(stat(fname, &dummy_stat)!=0)
192       {
193         DEBUG(2,("lock_share_entry: Re-issuing open on %s to fix race. Error was %s\n",
194                 fname, strerror(errno)));
195         close(fd);
196       }
197       else
198         gotlock = True;
199     } while(!gotlock);
200
201     /*
202      * We have to come here if any of the above calls fail
203      * as we don't want to return and leave ourselves running
204      * as root !
205      */
206   }
207
208   *ptok = (int)fd;
209
210   /* return to our previous privilage level */
211   unbecome_root(False);
212
213   return ret;
214 }
215
216 /*******************************************************************
217   unlock a share mode file.
218   ******************************************************************/
219 static BOOL slow_unlock_share_entry(int cnum, uint32 dev, uint32 inode, int token)
220 {
221   int fd = (int)token;
222   int ret = True;
223   struct stat sb;
224   pstring fname;
225
226   if (read_only) return True;
227
228   /* Fix for zero length share files from
229      Gerald Werner <wernerg@mfldclin.edu> */
230     
231   share_name(cnum, dev, inode, fname);
232
233   /* get the share mode file size */
234   if(fstat((int)token, &sb) != 0)
235   {
236     DEBUG(0,("ERROR: unlock_share_entry: Failed to do stat on share file %s (%s)\n",
237               fname, strerror(errno)));
238     sb.st_size = 1;
239     ret = False;
240   }
241
242   /* If the file was zero length, we must delete before
243      doing the unlock to avoid a race condition (see
244      the code in lock_share_mode_entry for details.
245    */
246
247   /* remove the share file if zero length */    
248   if(sb.st_size == 0)  
249     delete_share_file(cnum, fname);
250
251   /* token is the fd of the open share mode file. */
252   /* Unlock the first byte. */
253   if(fcntl_lock(fd, F_SETLKW, 0, 1, F_UNLCK) == False)
254    { 
255       DEBUG(0,("ERROR unlock_share_entry: fcntl_lock failed with %s\n",
256                       strerror(errno)));   
257       ret = False;
258    }
259  
260   close(fd);
261   return ret;
262 }
263
264 /*******************************************************************
265 Read a share file into a buffer.
266 ********************************************************************/
267 static int read_share_file(int cnum, int fd, char *fname, char **out, BOOL *p_new_file)
268 {
269   struct stat sb;
270   char *buf;
271   int size;
272
273   *out = 0;
274   *p_new_file = False;
275
276   if(fstat(fd, &sb) != 0)
277   {
278     DEBUG(0,("ERROR: read_share_file: Failed to do stat on share file %s (%s)\n",
279                   fname, strerror(errno)));
280     return -1;
281   }
282
283   if(sb.st_size == 0)
284   {
285      *p_new_file = True;
286      return 0;
287   }
288
289   /* Allocate space for the file */
290   if((buf = (char *)malloc(sb.st_size)) == NULL)
291   {
292     DEBUG(0,("read_share_file: malloc for file size %d fail !\n", sb.st_size));
293     return -1;
294   }
295   
296   if(lseek(fd, 0, SEEK_SET) != 0)
297   {
298     DEBUG(0,("ERROR: read_share_file: Failed to reset position to 0 \
299 for share file %s (%s)\n", fname, strerror(errno)));
300     if(buf)
301       free(buf);
302     return -1;
303   }
304   
305   if (read(fd,buf,sb.st_size) != sb.st_size)
306   {
307     DEBUG(0,("ERROR: read_share_file: Failed to read share file %s (%s)\n",
308                fname, strerror(errno)));
309     if(buf)
310       free(buf);
311     return -1;
312   }
313   
314   if (IVAL(buf,SMF_VERSION_OFFSET) != LOCKING_VERSION) {
315     DEBUG(0,("ERROR: read_share_file: share file %s has incorrect \
316 locking version (was %d, should be %d).\n",fname, 
317                     IVAL(buf,SMF_VERSION_OFFSET), LOCKING_VERSION));
318    if(buf)
319       free(buf);
320     delete_share_file(cnum, fname);
321     return -1;
322   }
323
324   /* Sanity check for file contents */
325   size = sb.st_size;
326   size -= SMF_HEADER_LENGTH; /* Remove the header */
327
328   /* Remove the filename component. */
329   size -= SVAL(buf, SMF_FILENAME_LEN_OFFSET);
330
331   /* The remaining size must be a multiple of SMF_ENTRY_LENGTH - error if not. */
332   if((size % SMF_ENTRY_LENGTH) != 0)
333   {
334     DEBUG(0,("ERROR: read_share_file: share file %s is an incorrect length - \
335 deleting it.\n", fname));
336     if(buf)
337       free(buf);
338     delete_share_file(cnum, fname);
339     return -1;
340   }
341
342   *out = buf;
343   return 0;
344 }
345
346 /*******************************************************************
347 get all share mode entries in a share file for a dev/inode pair.
348 ********************************************************************/
349 static int slow_get_share_modes(int cnum, int token, uint32 dev, uint32 inode, 
350                                 share_mode_entry **old_shares)
351 {
352   int fd = (int)token;
353   pstring fname;
354   int i;
355   int num_entries;
356   int num_entries_copied;
357   int newsize;
358   share_mode_entry *share_array;
359   char *buf = 0;
360   char *base = 0;
361   BOOL new_file;
362
363   *old_shares = 0;
364
365   /* Read the share file header - this is of the form:
366      0   -  locking version.
367      4   -  number of share mode entries.
368      8   -  2 byte name length
369      [n bytes] file name (zero terminated).
370
371    Followed by <n> share mode entries of the form :
372
373      0   -  tv_sec
374      4   -  tv_usec
375      8   -  share_mode
376     12   -  pid
377     16   -  oplock port (if oplocks in use) - 2 bytes.
378   */
379
380   share_name(cnum, dev, inode, fname);
381
382   if(read_share_file( cnum, fd, fname, &buf, &new_file) != 0)
383   {
384     DEBUG(0,("ERROR: get_share_modes: Failed to read share file %s\n",
385                   fname));
386     return 0;
387   }
388
389   if(new_file == True)
390     return 0;
391
392   num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET);
393
394   DEBUG(5,("get_share_modes: share file %s has %d share mode entries.\n",
395             fname, num_entries));
396
397   /* PARANOIA TEST */
398   if(num_entries < 0)
399   {
400     DEBUG(0,("PANIC ERROR:get_share_mode: num_share_mode_entries < 0 (%d) \
401 for share file %d\n", num_entries, fname));
402     return 0;
403   }
404
405   if(num_entries)
406   {
407     *old_shares = share_array = (share_mode_entry *)
408                  malloc(num_entries * sizeof(share_mode_entry));
409     if(*old_shares == 0)
410     {
411       DEBUG(0,("get_share_modes: malloc fail !\n"));
412       return 0;
413     }
414   } 
415   else
416   {
417     /* No entries - just delete the file. */
418     DEBUG(0,("get_share_modes: share file %s has no share mode entries - deleting.\n",
419               fname));
420     if(buf)
421       free(buf);
422     delete_share_file(cnum, fname);
423     return 0;
424   }
425
426   num_entries_copied = 0;
427   base = buf + SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET);
428
429   for( i = 0; i < num_entries; i++)
430   {
431     int pid;
432     char *p = base + (i*SMF_ENTRY_LENGTH);
433
434     pid = IVAL(p,SME_PID_OFFSET);
435
436     if(!process_exists(pid))
437     {
438       DEBUG(0,("get_share_modes: process %d no longer exists and \
439 it left a share mode entry with mode 0x%X in share file %s\n",
440             pid, IVAL(p,SME_SHAREMODE_OFFSET), fname));
441       continue;
442     }
443     share_array[num_entries_copied].time.tv_sec = IVAL(p,SME_SEC_OFFSET);
444     share_array[num_entries_copied].time.tv_usec = IVAL(p,SME_USEC_OFFSET);
445     share_array[num_entries_copied].share_mode = IVAL(p,SME_SHAREMODE_OFFSET);
446     share_array[num_entries_copied].pid = pid;
447     share_array[num_entries_copied].op_port = SVAL(p,SME_PORT_OFFSET);
448     share_array[num_entries_copied].op_type = SVAL(p,SME_OPLOCK_TYPE_OFFSET);
449
450     num_entries_copied++;
451   }
452
453   if(num_entries_copied == 0)
454   {
455     /* Delete the whole file. */
456     DEBUG(0,("get_share_modes: share file %s had no valid entries - deleting it !\n",
457              fname));
458     if(*old_shares)
459       free((char *)*old_shares);
460     *old_shares = 0;
461     if(buf)
462       free(buf);
463     delete_share_file(cnum, fname);
464     return 0;
465   }
466
467   /* If we deleted some entries we need to re-write the whole number of
468      share mode entries back into the file. */
469
470   if(num_entries_copied != num_entries)
471   {
472     if(lseek(fd, 0, SEEK_SET) != 0)
473     {
474       DEBUG(0,("ERROR: get_share_modes: lseek failed to reset to \
475 position 0 for share mode file %s (%s)\n", fname, strerror(errno)));
476       if(*old_shares)
477         free((char *)*old_shares);
478       *old_shares = 0;
479       if(buf)
480         free(buf);
481       return 0;
482     }
483
484     SIVAL(buf, SMF_NUM_ENTRIES_OFFSET, num_entries_copied);
485     for( i = 0; i < num_entries_copied; i++)
486     {
487       char *p = base + (i*SMF_ENTRY_LENGTH);
488
489       SIVAL(p,SME_PID_OFFSET,share_array[i].pid);
490       SIVAL(p,SME_SHAREMODE_OFFSET,share_array[i].share_mode);
491       SIVAL(p,SME_SEC_OFFSET,share_array[i].time.tv_sec);
492       SIVAL(p,SME_USEC_OFFSET,share_array[i].time.tv_usec);
493       SSVAL(p,SME_PORT_OFFSET,share_array[i].op_port);
494       SSVAL(p,SME_OPLOCK_TYPE_OFFSET,share_array[i].op_type);
495     }
496
497     newsize = (base - buf) + (SMF_ENTRY_LENGTH*num_entries_copied);
498     if(write(fd, buf, newsize) != newsize)
499     {
500       DEBUG(0,("ERROR: get_share_modes: failed to re-write share \
501 mode file %s (%s)\n", fname, strerror(errno)));
502       if(*old_shares)
503         free((char *)*old_shares);
504       *old_shares = 0;
505       if(buf)
506         free(buf);
507       return 0;
508     }
509     /* Now truncate the file at this point. */
510     if(ftruncate(fd, newsize)!= 0)
511     {
512       DEBUG(0,("ERROR: get_share_modes: failed to ftruncate share \
513 mode file %s to size %d (%s)\n", fname, newsize, strerror(errno)));
514       if(*old_shares)
515         free((char *)*old_shares);
516       *old_shares = 0;
517       if(buf)
518         free(buf);
519       return 0;
520     }
521   }
522
523   if(buf)
524     free(buf);
525
526   DEBUG(5,("get_share_modes: Read share file %s returning %d entries\n",fname,
527             num_entries_copied));
528
529   return num_entries_copied;
530 }
531
532 /*******************************************************************
533 del a share mode from a share mode file.
534 ********************************************************************/
535 static void slow_del_share_mode(int token, int fnum)
536 {
537   pstring fname;
538   int fd = (int)token;
539   char *buf = 0;
540   char *base = 0;
541   int num_entries;
542   int newsize;
543   int i;
544   files_struct *fs_p = &Files[fnum];
545   int pid;
546   BOOL deleted = False;
547   BOOL new_file;
548
549   share_name(fs_p->cnum, fs_p->fd_ptr->dev, 
550                        fs_p->fd_ptr->inode, fname);
551
552   if(read_share_file( fs_p->cnum, fd, fname, &buf, &new_file) != 0)
553   {
554     DEBUG(0,("ERROR: del_share_mode: Failed to read share file %s\n",
555                   fname));
556     return;
557   }
558
559   if(new_file == True)
560   {
561     DEBUG(0,("ERROR:del_share_mode: share file %s is new (size zero), deleting it.\n",
562               fname));
563     delete_share_file(fs_p->cnum, fname);
564     return;
565   }
566
567   num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET);
568
569   DEBUG(5,("del_share_mode: share file %s has %d share mode entries.\n",
570             fname, num_entries));
571
572   /* PARANOIA TEST */
573   if(num_entries < 0)
574   {
575     DEBUG(0,("PANIC ERROR:del_share_mode: num_share_mode_entries < 0 (%d) \
576 for share file %d\n", num_entries, fname));
577     return;
578   }
579
580   if(num_entries == 0)
581   {
582     /* No entries - just delete the file. */
583     DEBUG(0,("del_share_mode: share file %s has no share mode entries - deleting.\n",
584               fname));
585     if(buf)
586       free(buf);
587     delete_share_file(fs_p->cnum, fname);
588     return;
589   }
590
591   pid = getpid();
592
593   /* Go through the entries looking for the particular one
594      we have set - delete it.
595   */
596
597   base = buf + SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET);
598
599   for(i = 0; i < num_entries; i++)
600   {
601     char *p = base + (i*SMF_ENTRY_LENGTH);
602
603     if((IVAL(p,SME_SEC_OFFSET) != fs_p->open_time.tv_sec) || 
604        (IVAL(p,SME_USEC_OFFSET) != fs_p->open_time.tv_usec) ||
605        (IVAL(p,SME_SHAREMODE_OFFSET) != fs_p->share_mode) || 
606        (IVAL(p,SME_PID_OFFSET) != pid))
607       continue;
608
609     DEBUG(5,("del_share_mode: deleting entry number %d (of %d) from the share file %s\n",
610              i, num_entries, fname));
611
612     /* Remove this entry. */
613     if(i != num_entries - 1)
614       memcpy(p, p + SMF_ENTRY_LENGTH, (num_entries - i - 1)*SMF_ENTRY_LENGTH);
615
616     deleted = True;
617     break;
618   }
619
620   if(!deleted)
621   {
622     DEBUG(0,("del_share_mode: entry not found in share file %s\n", fname));
623     if(buf)
624       free(buf);
625     return;
626   }
627
628   num_entries--;
629   SIVAL(buf,SMF_NUM_ENTRIES_OFFSET, num_entries);
630
631   if(num_entries == 0)
632   {
633     /* Deleted the last entry - remove the file. */
634     DEBUG(5,("del_share_mode: removed last entry in share file - deleting share file %s\n",
635              fname));
636     if(buf)
637       free(buf);
638     delete_share_file(fs_p->cnum,fname);
639     return;
640   }
641
642   /* Re-write the file - and truncate it at the correct point. */
643   if(lseek(fd, 0, SEEK_SET) != 0)
644   {
645     DEBUG(0,("ERROR: del_share_mode: lseek failed to reset to \
646 position 0 for share mode file %s (%s)\n", fname, strerror(errno)));
647     if(buf)
648       free(buf);
649     return;
650   }
651
652   newsize = (base - buf) + (SMF_ENTRY_LENGTH*num_entries);
653   if(write(fd, buf, newsize) != newsize)
654   {
655     DEBUG(0,("ERROR: del_share_mode: failed to re-write share \
656 mode file %s (%s)\n", fname, strerror(errno)));
657     if(buf)
658       free(buf);
659     return;
660   }
661
662   /* Now truncate the file at this point. */
663   if(ftruncate(fd, newsize) != 0)
664   {
665     DEBUG(0,("ERROR: del_share_mode: failed to ftruncate share \
666 mode file %s to size %d (%s)\n", fname, newsize, strerror(errno)));
667     if(buf)
668       free(buf);
669     return;
670   }
671 }
672   
673 /*******************************************************************
674 set the share mode of a file
675 ********************************************************************/
676 static BOOL slow_set_share_mode(int token,int fnum, uint16 port, uint16 op_type)
677 {
678   files_struct *fs_p = &Files[fnum];
679   pstring fname;
680   int fd = (int)token;
681   int pid = (int)getpid();
682   struct stat sb;
683   char *buf;
684   int num_entries;
685   int header_size;
686   char *p;
687
688   share_name(fs_p->cnum, fs_p->fd_ptr->dev,
689                        fs_p->fd_ptr->inode, fname);
690
691   if(fstat(fd, &sb) != 0)
692   {
693     DEBUG(0,("ERROR: set_share_mode: Failed to do stat on share file %s\n",
694                   fname));
695     return False;
696   }
697
698   /* Sanity check for file contents (if it's not a new share file). */
699   if(sb.st_size != 0)
700   {
701     int size = sb.st_size;
702
703     /* Allocate space for the file plus one extra entry */
704     if((buf = (char *)malloc(sb.st_size + SMF_ENTRY_LENGTH)) == NULL)
705     {
706       DEBUG(0,("set_share_mode: malloc for file size %d fail !\n", 
707                   sb.st_size + SMF_ENTRY_LENGTH));
708       return False;
709     }
710  
711     if(lseek(fd, 0, SEEK_SET) != 0)
712     {
713       DEBUG(0,("ERROR: set_share_mode: Failed to reset position \
714 to 0 for share file %s (%s)\n", fname, strerror(errno)));
715       if(buf)
716         free(buf);
717       return False;
718     }
719
720     if (read(fd,buf,sb.st_size) != sb.st_size)
721     {
722       DEBUG(0,("ERROR: set_share_mode: Failed to read share file %s (%s)\n",
723                   fname, strerror(errno)));
724       if(buf)
725         free(buf);
726       return False;
727     }   
728   
729     if (IVAL(buf,SMF_VERSION_OFFSET) != LOCKING_VERSION) 
730     {
731       DEBUG(0,("ERROR: set_share_mode: share file %s has incorrect \
732 locking version (was %d, should be %d).\n",fname, IVAL(buf,SMF_VERSION_OFFSET), 
733                     LOCKING_VERSION));
734       if(buf)
735         free(buf);
736       delete_share_file(fs_p->cnum, fname);
737       return False;
738     }   
739
740     size -= (SMF_HEADER_LENGTH + SVAL(buf, SMF_FILENAME_LEN_OFFSET)); /* Remove the header */
741
742     /* The remaining size must be a multiple of SMF_ENTRY_LENGTH - error if not. */
743     if((size % SMF_ENTRY_LENGTH) != 0)
744     {
745       DEBUG(0,("ERROR: set_share_mode: share file %s is an incorrect length - \
746 deleting it.\n", fname));
747       if(buf)
748         free(buf);
749       delete_share_file(fs_p->cnum, fname);
750       return False;
751     }
752
753   }
754   else
755   {
756     /* New file - just use a single_entry. */
757     if((buf = (char *)malloc(SMF_HEADER_LENGTH + 
758                   strlen(fs_p->name) + 1 + SMF_ENTRY_LENGTH)) == NULL)
759     {
760       DEBUG(0,("ERROR: set_share_mode: malloc failed for single entry.\n"));
761       return False;
762     }
763     SIVAL(buf,SMF_VERSION_OFFSET,LOCKING_VERSION);
764     SIVAL(buf,SMF_NUM_ENTRIES_OFFSET,0);
765     SSVAL(buf,SMF_FILENAME_LEN_OFFSET,strlen(fs_p->name) + 1);
766     pstrcpy(buf + SMF_HEADER_LENGTH, fs_p->name);
767   }
768
769   num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET);
770   header_size = SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET);
771   p = buf + header_size + (num_entries * SMF_ENTRY_LENGTH);
772   SIVAL(p,SME_SEC_OFFSET,fs_p->open_time.tv_sec);
773   SIVAL(p,SME_USEC_OFFSET,fs_p->open_time.tv_usec);
774   SIVAL(p,SME_SHAREMODE_OFFSET,fs_p->share_mode);
775   SIVAL(p,SME_PID_OFFSET,pid);
776   SSVAL(p,SME_PORT_OFFSET,port);
777   SSVAL(p,SME_OPLOCK_TYPE_OFFSET,op_type);
778
779   num_entries++;
780
781   SIVAL(buf,SMF_NUM_ENTRIES_OFFSET,num_entries);
782
783   if(lseek(fd, 0, SEEK_SET) != 0)
784   {
785     DEBUG(0,("ERROR: set_share_mode: (1) Failed to reset position to \
786 0 for share file %s (%s)\n", fname, strerror(errno)));
787     if(buf)
788       free(buf);
789     return False;
790   }
791
792   if (write(fd,buf,header_size + (num_entries*SMF_ENTRY_LENGTH)) != 
793                        (header_size + (num_entries*SMF_ENTRY_LENGTH))) 
794   {
795     DEBUG(2,("ERROR: set_share_mode: Failed to write share file %s - \
796 deleting it (%s).\n",fname, strerror(errno)));
797     delete_share_file(fs_p->cnum, fname);
798     if(buf)
799       free(buf);
800     return False;
801   }
802
803   /* Now truncate the file at this point - just for safety. */
804
805   if(ftruncate(fd, header_size + (SMF_ENTRY_LENGTH*num_entries))!= 0)
806   {
807     DEBUG(0,("ERROR: set_share_mode: failed to ftruncate share \
808 mode file %s to size %d (%s)\n", fname, header_size + (SMF_ENTRY_LENGTH*num_entries), 
809                 strerror(errno)));
810     if(buf)
811       free(buf);
812     return False;
813   }
814
815   if(buf)
816     free(buf);
817
818   DEBUG(3,("set_share_mode: Created share file %s with \
819 mode 0x%X pid=%d\n",fname,fs_p->share_mode,pid));
820
821   return True;
822 }
823
824 /*******************************************************************
825 Remove an oplock port and mode entry from a share mode.
826 ********************************************************************/
827 static BOOL slow_remove_share_oplock(int fnum, int token)
828 {
829   pstring fname;
830   int fd = (int)token;
831   char *buf = 0;
832   char *base = 0;
833   int num_entries;
834   int fsize;
835   int i;
836   files_struct *fs_p = &Files[fnum];
837   int pid;
838   BOOL found = False;
839   BOOL new_file;
840
841   share_name(fs_p->cnum, fs_p->fd_ptr->dev, 
842                        fs_p->fd_ptr->inode, fname);
843
844   if(read_share_file( fs_p->cnum, fd, fname, &buf, &new_file) != 0)
845   {
846     DEBUG(0,("ERROR: remove_share_oplock: Failed to read share file %s\n",
847                   fname));
848     return False;
849   }
850
851   if(new_file == True)
852   {
853     DEBUG(0,("ERROR: remove_share_oplock: share file %s is new (size zero), \
854 deleting it.\n", fname));
855     delete_share_file(fs_p->cnum, fname);
856     return False;
857   }
858
859   num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET);
860
861   DEBUG(5,("remove_share_oplock: share file %s has %d share mode entries.\n",
862             fname, num_entries));
863
864   /* PARANOIA TEST */
865   if(num_entries < 0)
866   {
867     DEBUG(0,("PANIC ERROR:remove_share_oplock: num_share_mode_entries < 0 (%d) \
868 for share file %d\n", num_entries, fname));
869     return False;
870   }
871
872   if(num_entries == 0)
873   {
874     /* No entries - just delete the file. */
875     DEBUG(0,("remove_share_oplock: share file %s has no share mode entries - deleting.\n",
876               fname));
877     if(buf)
878       free(buf);
879     delete_share_file(fs_p->cnum, fname);
880     return False;
881   }
882
883   pid = getpid();
884
885   /* Go through the entries looking for the particular one
886      we have set - remove the oplock settings on it.
887   */
888
889   base = buf + SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET);
890
891   for(i = 0; i < num_entries; i++)
892   {
893     char *p = base + (i*SMF_ENTRY_LENGTH);
894
895     if((IVAL(p,SME_SEC_OFFSET) != fs_p->open_time.tv_sec) || 
896        (IVAL(p,SME_USEC_OFFSET) != fs_p->open_time.tv_usec) ||
897        (IVAL(p,SME_SHAREMODE_OFFSET) != fs_p->share_mode) || 
898        (IVAL(p,SME_PID_OFFSET) != pid))
899       continue;
900
901     DEBUG(5,("remove_share_oplock: clearing oplock on entry number %d (of %d) \
902 from the share file %s\n", i, num_entries, fname));
903
904     SSVAL(p,SME_PORT_OFFSET,0);
905     SSVAL(p,SME_OPLOCK_TYPE_OFFSET,0);
906     found = True;
907     break;
908   }
909
910   if(!found)
911   {
912     DEBUG(0,("remove_share_oplock: entry not found in share file %s\n", fname));
913     if(buf)
914       free(buf);
915     return False;
916   }
917
918   /* Re-write the file - and truncate it at the correct point. */
919   if(lseek(fd, 0, SEEK_SET) != 0)
920   {
921     DEBUG(0,("ERROR: remove_share_oplock: lseek failed to reset to \
922 position 0 for share mode file %s (%s)\n", fname, strerror(errno)));
923     if(buf)
924       free(buf);
925     return False;
926   }
927
928   fsize = (base - buf) + (SMF_ENTRY_LENGTH*num_entries);
929   if(write(fd, buf, fsize) != fsize)
930   {
931     DEBUG(0,("ERROR: remove_share_oplock: failed to re-write share \
932 mode file %s (%s)\n", fname, strerror(errno)));
933     if(buf)
934       free(buf);
935     return False;
936   }
937
938   return True;
939 }
940
941
942
943 /*******************************************************************
944 call the specified function on each entry under management by the
945 share ode system
946 ********************************************************************/
947 static int slow_share_forall(void (*fn)(share_mode_entry *, char *))
948 {
949         int i, count=0;
950         void *dir;
951         char *s;
952         share_mode_entry e;
953
954         dir = opendir(lp_lockdir());
955         if (!dir) {
956                 return(0);
957         }
958
959         while ((s=readdirname(dir))) {
960                 char *buf;
961                 char *base;
962                 int fd;
963                 pstring lname;
964                 uint32 dev,inode;
965                 BOOL new_file;
966                 pstring fname;
967
968                 if (sscanf(s,"share.%u.%u",&dev,&inode)!=2) continue;
969        
970                 pstrcpy(lname,lp_lockdir());
971                 trim_string(lname,NULL,"/");
972                 pstrcat(lname,"/");
973                 pstrcat(lname,s);
974        
975                 fd = open(lname,read_only?O_RDONLY:O_RDWR,0);
976                 if (fd < 0) {
977                         continue;
978                 }
979
980                 /* Lock the share mode file while we read it. */
981                 if(!read_only &&
982                    fcntl_lock(fd, F_SETLKW, 0, 1, F_WRLCK) == False) {
983                         close(fd);
984                         continue;
985                 }
986
987                 if(read_share_file( 0, fd, lname, &buf, &new_file)) {
988                         close(fd);
989                         continue;
990                 } 
991                 pstrcpy( fname, &buf[10]);
992                 close(fd);
993       
994                 base = buf + SMF_HEADER_LENGTH + 
995                         SVAL(buf,SMF_FILENAME_LEN_OFFSET); 
996                 for( i = 0; i < IVAL(buf, SMF_NUM_ENTRIES_OFFSET); i++) {
997                         char *p = base + (i*SMF_ENTRY_LENGTH);
998                         e.pid = IVAL(p,SME_PID_OFFSET);
999                         e.share_mode = IVAL(p,SME_SHAREMODE_OFFSET);
1000                         e.time.tv_sec = IVAL(p,SME_SEC_OFFSET);
1001                         e.time.tv_usec = IVAL(p,SME_USEC_OFFSET);
1002                         e.op_port = SVAL(p,SME_PORT_OFFSET);
1003                         e.pid = SVAL(p,SME_PID_OFFSET);
1004                         e.op_type = SVAL(p,SME_OPLOCK_TYPE_OFFSET);
1005
1006                         if (process_exists(e.pid)) {
1007                                 fn(&e, fname);
1008                                 count++;
1009                         }
1010                 } /* end for i */
1011
1012                 if(buf)
1013                         free(buf);
1014                 base = 0;
1015         } /* end while */
1016         closedir(dir);
1017
1018         return count;
1019 }
1020
1021
1022 /*******************************************************************
1023 dump the state of the system
1024 ********************************************************************/
1025 static void slow_share_status(FILE *f)
1026 {
1027         
1028 }
1029
1030
1031 static struct share_ops share_ops = {
1032         slow_stop_share_mode_mgmt,
1033         slow_lock_share_entry,
1034         slow_unlock_share_entry,
1035         slow_get_share_modes,
1036         slow_del_share_mode,
1037         slow_set_share_mode,
1038         slow_remove_share_oplock,
1039         slow_share_forall,
1040         slow_share_status,
1041 };
1042
1043 /*******************************************************************
1044   initialize the slow share_mode management 
1045   ******************************************************************/
1046 struct share_ops *locking_slow_init(int ronly)
1047 {
1048
1049         read_only = ronly;
1050
1051         if (!directory_exist(lp_lockdir(),NULL)) {
1052                 if (!read_only)
1053                         mkdir(lp_lockdir(),0755);
1054                 if (!directory_exist(lp_lockdir(),NULL))
1055                         return NULL;
1056         }
1057
1058         return &share_ops;
1059 }
1060 #else
1061  int locking_slow_dummy_procedure(void)
1062 {return 0;}
1063 #endif /* !FAST_SHARE_MODES */