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