4c2ba43cd8e1c9ead95c3f09a7df732f7d565d4b
[ira/wip.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
41 /* 
42  * Locking file header lengths & offsets. 
43  */
44 #define SMF_VERSION_OFFSET 0
45 #define SMF_NUM_ENTRIES_OFFSET 4
46 #define SMF_FILENAME_LEN_OFFSET 8
47 #define SMF_HEADER_LENGTH 10
48
49 #define SMF_ENTRY_LENGTH 20
50
51 /*
52  * Share mode record offsets.
53  */
54
55 #define SME_SEC_OFFSET 0
56 #define SME_USEC_OFFSET 4
57 #define SME_SHAREMODE_OFFSET 8
58 #define SME_PID_OFFSET 12
59 #define SME_PORT_OFFSET 16
60 #define SME_OPLOCK_TYPE_OFFSET 18
61
62 /* we need world read for smbstatus to function correctly */
63 #ifdef SECURE_SHARE_MODES
64 #define SHARE_FILE_MODE 0600
65 #else
66 #define SHARE_FILE_MODE 0644
67 #endif
68
69 static int read_only;
70
71 /*******************************************************************
72   deinitialize share_mode management 
73   ******************************************************************/
74 static BOOL slow_stop_share_mode_mgmt(void)
75 {
76    return True;
77 }
78
79
80 /*******************************************************************
81   name a share file
82   ******************************************************************/
83 static BOOL share_name(connection_struct *conn, 
84                        SMB_DEV_T dev, SMB_INO_T inode, char *name)
85 {
86         int len;
87         pstrcpy(name,lp_lockdir());
88         trim_string(name,"","/");
89         if (!*name) return(False);
90         len = strlen(name);
91         name += len;
92         
93         slprintf(name, sizeof(pstring) - len - 1, "/share.%u.%u",dev,inode);
94         return(True);
95 }
96
97 /*******************************************************************
98 Force a share file to be deleted.
99 ********************************************************************/
100 static int delete_share_file(connection_struct *conn, char *fname )
101 {
102   if (read_only) return -1;
103
104   /* the share file could be owned by anyone, so do this as root */
105   become_root(False);
106
107   if(unlink(fname) != 0)
108   {
109     DEBUG(0,("delete_share_file: Can't delete share file %s (%s)\n",
110             fname, strerror(errno)));
111   } 
112   else 
113   {
114     DEBUG(5,("delete_share_file: Deleted share file %s\n", fname));
115   }
116
117   /* return to our previous privilage level */
118   unbecome_root(False);
119
120   return 0;
121 }
122
123 /*******************************************************************
124   lock a share mode file.
125   ******************************************************************/
126 static BOOL slow_lock_share_entry(connection_struct *conn,
127                                   SMB_DEV_T dev, SMB_INO_T inode, int *ptok)
128 {
129   pstring fname;
130   int fd;
131   int ret = True;
132
133   *ptok = (int)-1;
134
135   if(!share_name(conn, 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       SMB_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(connection_struct *conn, 
220                                     SMB_DEV_T dev, SMB_INO_T inode, int token)
221 {
222   int fd = token;
223   int ret = True;
224   SMB_STRUCT_STAT sb;
225   pstring fname;
226
227   if (read_only) return True;
228
229   /* Fix for zero length share files from
230      Gerald Werner <wernerg@mfldclin.edu> */
231     
232   share_name(conn, dev, inode, fname);
233
234   /* get the share mode file size */
235   if(fstat((int)token, &sb) != 0)
236   {
237     DEBUG(0,("ERROR: unlock_share_entry: Failed to do stat on share file %s (%s)\n",
238               fname, strerror(errno)));
239     sb.st_size = 1;
240     ret = False;
241   }
242
243   /* If the file was zero length, we must delete before
244      doing the unlock to avoid a race condition (see
245      the code in lock_share_mode_entry for details.
246    */
247
248   /* remove the share file if zero length */    
249   if(sb.st_size == 0)  
250     delete_share_file(conn, fname);
251
252   /* token is the fd of the open share mode file. */
253   /* Unlock the first byte. */
254   if(fcntl_lock(fd, F_SETLKW, 0, 1, F_UNLCK) == False)
255    { 
256       DEBUG(0,("ERROR unlock_share_entry: fcntl_lock failed with %s\n",
257                       strerror(errno)));   
258       ret = False;
259    }
260  
261   close(fd);
262   return ret;
263 }
264
265 /*******************************************************************
266 Read a share file into a buffer.
267 ********************************************************************/
268 static int read_share_file(connection_struct *conn, int fd, char *fname, char **out, BOOL *p_new_file)
269 {
270   SMB_STRUCT_STAT sb;
271   char *buf;
272   int size;
273
274   *out = 0;
275   *p_new_file = False;
276
277   if(fstat(fd, &sb) != 0)
278   {
279     DEBUG(0,("ERROR: read_share_file: Failed to do stat on share file %s (%s)\n",
280                   fname, strerror(errno)));
281     return -1;
282   }
283
284   if(sb.st_size == 0)
285   {
286      *p_new_file = True;
287      return 0;
288   }
289
290   /* Allocate space for the file */
291   if((buf = (char *)malloc(sb.st_size)) == NULL)
292   {
293     DEBUG(0,("read_share_file: malloc for file size %d fail !\n", 
294              (int)sb.st_size));
295     return -1;
296   }
297   
298   if(lseek(fd, 0, SEEK_SET) != 0)
299   {
300     DEBUG(0,("ERROR: read_share_file: Failed to reset position to 0 \
301 for share file %s (%s)\n", fname, strerror(errno)));
302     if(buf)
303       free(buf);
304     return -1;
305   }
306   
307   if (read(fd,buf,sb.st_size) != sb.st_size)
308   {
309     DEBUG(0,("ERROR: read_share_file: Failed to read share file %s (%s)\n",
310                fname, strerror(errno)));
311     if(buf)
312       free(buf);
313     return -1;
314   }
315   
316   if (IVAL(buf,SMF_VERSION_OFFSET) != LOCKING_VERSION) {
317     DEBUG(0,("ERROR: read_share_file: share file %s has incorrect \
318 locking version (was %d, should be %d).\n",fname, 
319                     IVAL(buf,SMF_VERSION_OFFSET), LOCKING_VERSION));
320    if(buf)
321       free(buf);
322     delete_share_file(conn, fname);
323     return -1;
324   }
325
326   /* Sanity check for file contents */
327   size = sb.st_size;
328   size -= SMF_HEADER_LENGTH; /* Remove the header */
329
330   /* Remove the filename component. */
331   size -= SVAL(buf, SMF_FILENAME_LEN_OFFSET);
332
333   /* The remaining size must be a multiple of SMF_ENTRY_LENGTH - error if not. */
334   if((size % SMF_ENTRY_LENGTH) != 0)
335   {
336     DEBUG(0,("ERROR: read_share_file: share file %s is an incorrect length - \
337 deleting it.\n", fname));
338     if(buf)
339       free(buf);
340     delete_share_file(conn, fname);
341     return -1;
342   }
343
344   *out = buf;
345   return 0;
346 }
347
348 /*******************************************************************
349 get all share mode entries in a share file for a dev/inode pair.
350 ********************************************************************/
351 static int slow_get_share_modes(connection_struct *conn, int token, 
352                 SMB_DEV_T dev, SMB_INO_T inode, 
353                                 share_mode_entry **old_shares)
354 {
355   int fd = token;
356   pstring fname;
357   int i;
358   int num_entries;
359   int num_entries_copied;
360   int newsize;
361   share_mode_entry *share_array;
362   char *buf = 0;
363   char *base = 0;
364   BOOL new_file;
365
366   *old_shares = 0;
367
368   /* Read the share file header - this is of the form:
369      0   -  locking version.
370      4   -  number of share mode entries.
371      8   -  2 byte name length
372      [n bytes] file name (zero terminated).
373
374    Followed by <n> share mode entries of the form :
375
376      0   -  tv_sec
377      4   -  tv_usec
378      8   -  share_mode
379     12   -  pid
380     16   -  oplock port (if oplocks in use) - 2 bytes.
381   */
382
383   share_name(conn, dev, inode, fname);
384
385   if(read_share_file( conn, fd, fname, &buf, &new_file) != 0)
386   {
387     DEBUG(0,("ERROR: get_share_modes: Failed to read share file %s\n",
388                   fname));
389     return 0;
390   }
391
392   if(new_file == True)
393     return 0;
394
395   num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET);
396
397   DEBUG(5,("get_share_modes: share file %s has %d share mode entries.\n",
398             fname, num_entries));
399
400   /* PARANOIA TEST */
401   if(num_entries < 0)
402   {
403     DEBUG(0,("PANIC ERROR:get_share_mode: num_share_mode_entries < 0 (%d) \
404 for share file %s\n", num_entries, fname));
405     return 0;
406   }
407
408   if(num_entries)
409   {
410     *old_shares = share_array = (share_mode_entry *)
411                  malloc(num_entries * sizeof(share_mode_entry));
412     if(*old_shares == 0)
413     {
414       DEBUG(0,("get_share_modes: malloc fail !\n"));
415       return 0;
416     }
417   } 
418   else
419   {
420     /* No entries - just delete the file. */
421     DEBUG(0,("get_share_modes: share file %s has no share mode entries - deleting.\n",
422               fname));
423     if(buf)
424       free(buf);
425     delete_share_file(conn, fname);
426     return 0;
427   }
428
429   num_entries_copied = 0;
430   base = buf + SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET);
431
432   for( i = 0; i < num_entries; i++)
433   {
434     int pid;
435     char *p = base + (i*SMF_ENTRY_LENGTH);
436
437     pid = IVAL(p,SME_PID_OFFSET);
438
439     if(!process_exists(pid))
440     {
441       DEBUG(0,("get_share_modes: process %d no longer exists and \
442 it left a share mode entry with mode 0x%X in share file %s\n",
443             pid, IVAL(p,SME_SHAREMODE_OFFSET), fname));
444       continue;
445     }
446     share_array[num_entries_copied].time.tv_sec = IVAL(p,SME_SEC_OFFSET);
447     share_array[num_entries_copied].time.tv_usec = IVAL(p,SME_USEC_OFFSET);
448     share_array[num_entries_copied].share_mode = IVAL(p,SME_SHAREMODE_OFFSET);
449     share_array[num_entries_copied].pid = pid;
450     share_array[num_entries_copied].op_port = SVAL(p,SME_PORT_OFFSET);
451     share_array[num_entries_copied].op_type = SVAL(p,SME_OPLOCK_TYPE_OFFSET);
452
453     num_entries_copied++;
454   }
455
456   if(num_entries_copied == 0)
457   {
458     /* Delete the whole file. */
459     DEBUG(0,("get_share_modes: share file %s had no valid entries - deleting it !\n",
460              fname));
461     if(*old_shares)
462       free((char *)*old_shares);
463     *old_shares = 0;
464     if(buf)
465       free(buf);
466     delete_share_file(conn, fname);
467     return 0;
468   }
469
470   /* If we deleted some entries we need to re-write the whole number of
471      share mode entries back into the file. */
472
473   if(num_entries_copied != num_entries)
474   {
475     if(lseek(fd, 0, SEEK_SET) != 0)
476     {
477       DEBUG(0,("ERROR: get_share_modes: lseek failed to reset to \
478 position 0 for share mode file %s (%s)\n", fname, strerror(errno)));
479       if(*old_shares)
480         free((char *)*old_shares);
481       *old_shares = 0;
482       if(buf)
483         free(buf);
484       return 0;
485     }
486
487     SIVAL(buf, SMF_NUM_ENTRIES_OFFSET, num_entries_copied);
488     for( i = 0; i < num_entries_copied; i++)
489     {
490       char *p = base + (i*SMF_ENTRY_LENGTH);
491
492       SIVAL(p,SME_PID_OFFSET,share_array[i].pid);
493       SIVAL(p,SME_SHAREMODE_OFFSET,share_array[i].share_mode);
494       SIVAL(p,SME_SEC_OFFSET,share_array[i].time.tv_sec);
495       SIVAL(p,SME_USEC_OFFSET,share_array[i].time.tv_usec);
496       SSVAL(p,SME_PORT_OFFSET,share_array[i].op_port);
497       SSVAL(p,SME_OPLOCK_TYPE_OFFSET,share_array[i].op_type);
498     }
499
500     newsize = (base - buf) + (SMF_ENTRY_LENGTH*num_entries_copied);
501     if(write(fd, buf, newsize) != newsize)
502     {
503       DEBUG(0,("ERROR: get_share_modes: failed to re-write share \
504 mode file %s (%s)\n", fname, strerror(errno)));
505       if(*old_shares)
506         free((char *)*old_shares);
507       *old_shares = 0;
508       if(buf)
509         free(buf);
510       return 0;
511     }
512     /* Now truncate the file at this point. */
513     if(ftruncate(fd, newsize)!= 0)
514     {
515       DEBUG(0,("ERROR: get_share_modes: failed to ftruncate share \
516 mode file %s to size %d (%s)\n", fname, newsize, strerror(errno)));
517       if(*old_shares)
518         free((char *)*old_shares);
519       *old_shares = 0;
520       if(buf)
521         free(buf);
522       return 0;
523     }
524   }
525
526   if(buf)
527     free(buf);
528
529   DEBUG(5,("get_share_modes: Read share file %s returning %d entries\n",fname,
530             num_entries_copied));
531
532   return num_entries_copied;
533 }
534
535 /*******************************************************************
536 del a share mode from a share mode file.
537 ********************************************************************/
538 static void slow_del_share_mode(int token, files_struct *fsp)
539 {
540   pstring fname;
541   int fd = (int)token;
542   char *buf = 0;
543   char *base = 0;
544   int num_entries;
545   int newsize;
546   int i;
547   int pid;
548   BOOL deleted = False;
549   BOOL new_file;
550
551   share_name(fsp->conn, fsp->fd_ptr->dev, 
552                        fsp->fd_ptr->inode, fname);
553
554   if(read_share_file( fsp->conn, fd, fname, &buf, &new_file) != 0)
555   {
556     DEBUG(0,("ERROR: del_share_mode: Failed to read share file %s\n",
557                   fname));
558     return;
559   }
560
561   if(new_file == True)
562   {
563     DEBUG(0,("ERROR:del_share_mode: share file %s is new (size zero), deleting it.\n",
564               fname));
565     delete_share_file(fsp->conn, fname);
566     return;
567   }
568
569   num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET);
570
571   DEBUG(5,("del_share_mode: share file %s has %d share mode entries.\n",
572             fname, num_entries));
573
574   /* PARANOIA TEST */
575   if(num_entries < 0)
576   {
577     DEBUG(0,("PANIC ERROR:del_share_mode: num_share_mode_entries < 0 (%d) \
578 for share file %s\n", num_entries, fname));
579     return;
580   }
581
582   if(num_entries == 0)
583   {
584     /* No entries - just delete the file. */
585     DEBUG(0,("del_share_mode: share file %s has no share mode entries - deleting.\n",
586               fname));
587     if(buf)
588       free(buf);
589     delete_share_file(fsp->conn, fname);
590     return;
591   }
592
593   pid = getpid();
594
595   /* Go through the entries looking for the particular one
596      we have set - delete it.
597   */
598
599   base = buf + SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET);
600
601   for(i = 0; i < num_entries; i++)
602   {
603     char *p = base + (i*SMF_ENTRY_LENGTH);
604
605     if((IVAL(p,SME_SEC_OFFSET) != fsp->open_time.tv_sec) || 
606        (IVAL(p,SME_USEC_OFFSET) != fsp->open_time.tv_usec) ||
607        (IVAL(p,SME_SHAREMODE_OFFSET) != fsp->share_mode) || 
608        (IVAL(p,SME_PID_OFFSET) != pid))
609       continue;
610
611     DEBUG(5,("del_share_mode: deleting entry number %d (of %d) from the share file %s\n",
612              i, num_entries, fname));
613
614     /* Remove this entry. */
615     if(i != num_entries - 1)
616       memcpy(p, p + SMF_ENTRY_LENGTH, (num_entries - i - 1)*SMF_ENTRY_LENGTH);
617
618     deleted = True;
619     break;
620   }
621
622   if(!deleted)
623   {
624     DEBUG(0,("del_share_mode: entry not found in share file %s\n", fname));
625     if(buf)
626       free(buf);
627     return;
628   }
629
630   num_entries--;
631   SIVAL(buf,SMF_NUM_ENTRIES_OFFSET, num_entries);
632
633   if(num_entries == 0)
634   {
635     /* Deleted the last entry - remove the file. */
636     DEBUG(5,("del_share_mode: removed last entry in share file - deleting share file %s\n",
637              fname));
638     if(buf)
639       free(buf);
640     delete_share_file(fsp->conn,fname);
641     return;
642   }
643
644   /* Re-write the file - and truncate it at the correct point. */
645   if(lseek(fd, 0, SEEK_SET) != 0)
646   {
647     DEBUG(0,("ERROR: del_share_mode: lseek failed to reset to \
648 position 0 for share mode file %s (%s)\n", fname, strerror(errno)));
649     if(buf)
650       free(buf);
651     return;
652   }
653
654   newsize = (base - buf) + (SMF_ENTRY_LENGTH*num_entries);
655   if(write(fd, buf, newsize) != newsize)
656   {
657     DEBUG(0,("ERROR: del_share_mode: failed to re-write share \
658 mode file %s (%s)\n", fname, strerror(errno)));
659     if(buf)
660       free(buf);
661     return;
662   }
663
664   /* Now truncate the file at this point. */
665   if(ftruncate(fd, newsize) != 0)
666   {
667     DEBUG(0,("ERROR: del_share_mode: failed to ftruncate share \
668 mode file %s to size %d (%s)\n", fname, newsize, strerror(errno)));
669     if(buf)
670       free(buf);
671     return;
672   }
673 }
674   
675 /*******************************************************************
676 set the share mode of a file
677 ********************************************************************/
678 static BOOL slow_set_share_mode(int token,files_struct *fsp, uint16 port, uint16 op_type)
679 {
680   pstring fname;
681   int fd = (int)token;
682   int pid = (int)getpid();
683   SMB_STRUCT_STAT sb;
684   char *buf;
685   int num_entries;
686   int header_size;
687   char *p;
688
689   share_name(fsp->conn, fsp->fd_ptr->dev,
690                        fsp->fd_ptr->inode, fname);
691
692   if(fstat(fd, &sb) != 0)
693   {
694     DEBUG(0,("ERROR: set_share_mode: Failed to do stat on share file %s\n",
695                   fname));
696     return False;
697   }
698
699   /* Sanity check for file contents (if it's not a new share file). */
700   if(sb.st_size != 0)
701   {
702     int size = sb.st_size;
703
704     /* Allocate space for the file plus one extra entry */
705     if((buf = (char *)malloc(sb.st_size + SMF_ENTRY_LENGTH)) == NULL)
706     {
707       DEBUG(0,("set_share_mode: malloc for file size %d fail !\n", 
708                (int)(sb.st_size + SMF_ENTRY_LENGTH)));
709       return False;
710     }
711  
712     if(lseek(fd, 0, SEEK_SET) != 0)
713     {
714       DEBUG(0,("ERROR: set_share_mode: Failed to reset position \
715 to 0 for share file %s (%s)\n", fname, strerror(errno)));
716       if(buf)
717         free(buf);
718       return False;
719     }
720
721     if (read(fd,buf,sb.st_size) != sb.st_size)
722     {
723       DEBUG(0,("ERROR: set_share_mode: Failed to read share file %s (%s)\n",
724                   fname, strerror(errno)));
725       if(buf)
726         free(buf);
727       return False;
728     }   
729   
730     if (IVAL(buf,SMF_VERSION_OFFSET) != LOCKING_VERSION) 
731     {
732       DEBUG(0,("ERROR: set_share_mode: share file %s has incorrect \
733 locking version (was %d, should be %d).\n",fname, IVAL(buf,SMF_VERSION_OFFSET), 
734                     LOCKING_VERSION));
735       if(buf)
736         free(buf);
737       delete_share_file(fsp->conn, fname);
738       return False;
739     }   
740
741     size -= (SMF_HEADER_LENGTH + SVAL(buf, SMF_FILENAME_LEN_OFFSET)); /* Remove the header */
742
743     /* The remaining size must be a multiple of SMF_ENTRY_LENGTH - error if not. */
744     if((size % SMF_ENTRY_LENGTH) != 0)
745     {
746       DEBUG(0,("ERROR: set_share_mode: share file %s is an incorrect length - \
747 deleting it.\n", fname));
748       if(buf)
749         free(buf);
750       delete_share_file(fsp->conn, fname);
751       return False;
752     }
753
754   }
755   else
756   {
757     /* New file - just use a single_entry. */
758     if((buf = (char *)malloc(SMF_HEADER_LENGTH + 
759                   strlen(fsp->fsp_name) + 1 + SMF_ENTRY_LENGTH)) == NULL)
760     {
761       DEBUG(0,("ERROR: set_share_mode: malloc failed for single entry.\n"));
762       return False;
763     }
764     SIVAL(buf,SMF_VERSION_OFFSET,LOCKING_VERSION);
765     SIVAL(buf,SMF_NUM_ENTRIES_OFFSET,0);
766     SSVAL(buf,SMF_FILENAME_LEN_OFFSET,strlen(fsp->fsp_name) + 1);
767     pstrcpy(buf + SMF_HEADER_LENGTH, fsp->fsp_name);
768   }
769
770   num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET);
771   header_size = SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET);
772   p = buf + header_size + (num_entries * SMF_ENTRY_LENGTH);
773   SIVAL(p,SME_SEC_OFFSET,fsp->open_time.tv_sec);
774   SIVAL(p,SME_USEC_OFFSET,fsp->open_time.tv_usec);
775   SIVAL(p,SME_SHAREMODE_OFFSET,fsp->share_mode);
776   SIVAL(p,SME_PID_OFFSET,pid);
777   SSVAL(p,SME_PORT_OFFSET,port);
778   SSVAL(p,SME_OPLOCK_TYPE_OFFSET,op_type);
779
780   num_entries++;
781
782   SIVAL(buf,SMF_NUM_ENTRIES_OFFSET,num_entries);
783
784   if(lseek(fd, 0, SEEK_SET) != 0)
785   {
786     DEBUG(0,("ERROR: set_share_mode: (1) Failed to reset position to \
787 0 for share file %s (%s)\n", fname, strerror(errno)));
788     if(buf)
789       free(buf);
790     return False;
791   }
792
793   if (write(fd,buf,header_size + (num_entries*SMF_ENTRY_LENGTH)) != 
794                        (header_size + (num_entries*SMF_ENTRY_LENGTH))) 
795   {
796     DEBUG(2,("ERROR: set_share_mode: Failed to write share file %s - \
797 deleting it (%s).\n",fname, strerror(errno)));
798     delete_share_file(fsp->conn, fname);
799     if(buf)
800       free(buf);
801     return False;
802   }
803
804   /* Now truncate the file at this point - just for safety. */
805
806   if(ftruncate(fd, header_size + (SMF_ENTRY_LENGTH*num_entries))!= 0)
807   {
808     DEBUG(0,("ERROR: set_share_mode: failed to ftruncate share \
809 mode file %s to size %d (%s)\n", fname, header_size + (SMF_ENTRY_LENGTH*num_entries), 
810                 strerror(errno)));
811     if(buf)
812       free(buf);
813     return False;
814   }
815
816   if(buf)
817     free(buf);
818
819   DEBUG(3,("set_share_mode: Created share file %s with \
820 mode 0x%X pid=%d\n",fname,fsp->share_mode,pid));
821
822   return True;
823 }
824
825 /*******************************************************************
826 Remove an oplock port and mode entry from a share mode.
827 ********************************************************************/
828 static BOOL slow_remove_share_oplock(files_struct *fsp, int token)
829 {
830   pstring fname;
831   int fd = (int)token;
832   char *buf = 0;
833   char *base = 0;
834   int num_entries;
835   int fsize;
836   int i;
837   int pid;
838   BOOL found = False;
839   BOOL new_file;
840
841   share_name(fsp->conn, fsp->fd_ptr->dev, 
842                        fsp->fd_ptr->inode, fname);
843
844   if(read_share_file( fsp->conn, 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(fsp->conn, 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 %s\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(fsp->conn, 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) != fsp->open_time.tv_sec) || 
896        (IVAL(p,SME_USEC_OFFSET) != fsp->open_time.tv_usec) ||
897        (IVAL(p,SME_SHAREMODE_OFFSET) != fsp->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                 SMB_DEV_T dev;
965         SMB_INO_T inode;
966                 BOOL new_file;
967                 pstring fname;
968
969                 if (sscanf(s,"share.%u.%u",&dev,&inode)!=2) continue;
970        
971                 pstrcpy(lname,lp_lockdir());
972                 trim_string(lname,NULL,"/");
973                 pstrcat(lname,"/");
974                 pstrcat(lname,s);
975        
976                 fd = open(lname,read_only?O_RDONLY:O_RDWR,0);
977                 if (fd < 0) {
978                         continue;
979                 }
980
981                 /* Lock the share mode file while we read it. */
982                 if(!read_only &&
983                    fcntl_lock(fd, F_SETLKW, 0, 1, F_WRLCK) == False) {
984                         close(fd);
985                         continue;
986                 }
987
988                 if(read_share_file( 0, fd, lname, &buf, &new_file)) {
989                         close(fd);
990                         continue;
991                 } 
992                 pstrcpy( fname, &buf[10]);
993                 close(fd);
994       
995                 base = buf + SMF_HEADER_LENGTH + 
996                         SVAL(buf,SMF_FILENAME_LEN_OFFSET); 
997                 for( i = 0; i < IVAL(buf, SMF_NUM_ENTRIES_OFFSET); i++) {
998                         char *p = base + (i*SMF_ENTRY_LENGTH);
999                         e.pid = IVAL(p,SME_PID_OFFSET);
1000                         e.share_mode = IVAL(p,SME_SHAREMODE_OFFSET);
1001                         e.time.tv_sec = IVAL(p,SME_SEC_OFFSET);
1002                         e.time.tv_usec = IVAL(p,SME_USEC_OFFSET);
1003                         e.op_port = SVAL(p,SME_PORT_OFFSET);
1004                         e.pid = SVAL(p,SME_PID_OFFSET);
1005                         e.op_type = SVAL(p,SME_OPLOCK_TYPE_OFFSET);
1006
1007                         if (process_exists(e.pid)) {
1008                                 fn(&e, fname);
1009                                 count++;
1010                         }
1011                 } /* end for i */
1012
1013                 if(buf)
1014                         free(buf);
1015                 base = 0;
1016         } /* end while */
1017         closedir(dir);
1018
1019         return count;
1020 }
1021
1022
1023 /*******************************************************************
1024 dump the state of the system
1025 ********************************************************************/
1026 static void slow_share_status(FILE *f)
1027 {
1028         
1029 }
1030
1031
1032 static struct share_ops share_ops = {
1033         slow_stop_share_mode_mgmt,
1034         slow_lock_share_entry,
1035         slow_unlock_share_entry,
1036         slow_get_share_modes,
1037         slow_del_share_mode,
1038         slow_set_share_mode,
1039         slow_remove_share_oplock,
1040         slow_share_forall,
1041         slow_share_status,
1042 };
1043
1044 /*******************************************************************
1045   initialize the slow share_mode management 
1046   ******************************************************************/
1047 struct share_ops *locking_slow_init(int ronly)
1048 {
1049
1050         read_only = ronly;
1051
1052         if (!directory_exist(lp_lockdir(),NULL)) {
1053                 if (!read_only)
1054                         mkdir(lp_lockdir(),0755);
1055                 if (!directory_exist(lp_lockdir(),NULL))
1056                         return NULL;
1057         }
1058
1059         return &share_ops;
1060 }
1061 #else
1062  int locking_slow_dummy_procedure(void)
1063 {return 0;}
1064 #endif /* !FAST_SHARE_MODES */