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