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