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