Correct PPTP server firewall rules chain.
[tomato/davidwu.git] / release / src / router / samba / source / locking / locking_slow.c
blob14acccf458cb54db342a4b56f282ec866ae2593b
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 slow (lockfile) locking implementation
5 Copyright (C) Andrew Tridgell 1992-1998
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.
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.
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.
21 Revision History:
23 12 aug 96: Erik.Devriendt@te6.siemens.be
24 added support for shared memory implementation of share mode locking
26 May 1997. Jeremy Allison (jallison@whistle.com). Modified share mode
27 locking to deal with multiple share modes per open file.
29 September 1997. Jeremy Allison (jallison@whistle.com). Added oplock
30 support.
32 October 1997 - split into separate file (tridge)
35 #include "includes.h"
37 #ifndef FAST_SHARE_MODES
39 extern int DEBUGLEVEL;
41 /*
42 * Locking file header lengths & offsets.
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
49 #define SMF_ENTRY_LENGTH 20
52 * Share mode record offsets.
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
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
69 static int read_only;
71 /*******************************************************************
72 deinitialize share_mode management
73 ******************************************************************/
74 static BOOL slow_stop_share_mode_mgmt(void)
76 return True;
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)
86 int len;
87 pstrcpy(name,lp_lockdir());
88 trim_string(name,"","/");
89 if (!*name) return(False);
90 len = strlen(name);
91 name += len;
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);
101 /*******************************************************************
102 Force a share file to be deleted.
103 ********************************************************************/
104 static int delete_share_file(connection_struct *conn, char *fname )
106 if (read_only) return -1;
108 /* the share file could be owned by anyone, so do this as root */
109 become_root(False);
111 if(unlink(fname) != 0)
113 DEBUG(0,("delete_share_file: Can't delete share file %s (%s)\n",
114 fname, strerror(errno)));
116 else
118 DEBUG(5,("delete_share_file: Deleted share file %s\n", fname));
121 /* return to our previous privilege level */
122 unbecome_root(False);
124 return 0;
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)
133 pstring fname;
134 int fd;
135 int ret = True;
137 *ptok = (int)-1;
139 if(!share_name(conn, dev, inode, fname))
140 return False;
142 if (read_only) return True;
144 /* we need to do this as root */
145 become_root(False);
148 BOOL gotlock = False;
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).
166 SMB_STRUCT_STAT dummy_stat;
168 fd = sys_open(fname,read_only?O_RDONLY:(O_RDWR|O_CREAT), SHARE_FILE_MODE);
170 if(fd < 0)
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;
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)
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;
190 * If we cannot stat the filename, the file was deleted between
191 * the open and the lock call. Back out and try again.
194 if(sys_stat(fname, &dummy_stat)!=0)
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);
200 else
201 gotlock = True;
202 } while(!gotlock);
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 !
211 *ptok = (int)fd;
213 /* return to our previous privilege level */
214 unbecome_root(False);
216 return ret;
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)
225 int fd = token;
226 int ret = True;
227 SMB_STRUCT_STAT sb;
228 pstring fname;
230 if (read_only) return True;
232 /* Fix for zero length share files from
233 Gerald Werner <wernerg@mfldclin.edu> */
235 share_name(conn, dev, inode, fname);
237 /* get the share mode file size */
238 if(sys_fstat((int)token, &sb) != 0)
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;
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.
251 /* remove the share file if zero length */
252 if(sb.st_size == 0)
253 delete_share_file(conn, fname);
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)
259 DEBUG(0,("ERROR unlock_share_entry: fcntl_lock failed with %s\n",
260 strerror(errno)));
261 ret = False;
264 close(fd);
265 return ret;
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)
273 SMB_STRUCT_STAT sb;
274 char *buf;
275 SMB_OFF_T size;
277 *out = 0;
278 *p_new_file = False;
280 if(sys_fstat(fd, &sb) != 0)
282 DEBUG(0,("ERROR: read_share_file: Failed to do stat on share file %s (%s)\n",
283 fname, strerror(errno)));
284 return -1;
287 if(sb.st_size == 0)
289 *p_new_file = True;
290 return 0;
293 /* Allocate space for the file */
294 if((buf = (char *)malloc((size_t)sb.st_size)) == NULL)
296 DEBUG(0,("read_share_file: malloc for file size %d fail !\n",
297 (int)sb.st_size));
298 return -1;
301 if(sys_lseek(fd, (SMB_OFF_T)0, SEEK_SET) != 0)
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;
310 if (read(fd,buf,(size_t)sb.st_size) != (size_t)sb.st_size)
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;
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;
329 /* Sanity check for file contents */
330 size = sb.st_size;
331 size -= SMF_HEADER_LENGTH; /* Remove the header */
333 /* Remove the filename component. */
334 size -= SVAL(buf, SMF_FILENAME_LEN_OFFSET);
336 /* The remaining size must be a multiple of SMF_ENTRY_LENGTH - error if not. */
337 if((size % SMF_ENTRY_LENGTH) != 0)
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;
347 *out = buf;
348 return 0;
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)
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;
369 *old_shares = 0;
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).
377 Followed by <n> share mode entries of the form :
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.
386 share_name(conn, dev, inode, fname);
388 if(read_share_file( conn, fd, fname, &buf, &new_file) != 0)
390 DEBUG(0,("ERROR: get_share_modes: Failed to read share file %s\n",
391 fname));
392 return 0;
395 if(new_file == True)
396 return 0;
398 num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET);
400 DEBUG(5,("get_share_modes: share file %s has %d share mode entries.\n",
401 fname, num_entries));
403 /* PARANOIA TEST */
404 if(num_entries < 0)
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;
411 if(num_entries)
413 *old_shares = share_array = (share_mode_entry *)
414 malloc(num_entries * sizeof(share_mode_entry));
415 if(*old_shares == 0)
417 DEBUG(0,("get_share_modes: malloc fail !\n"));
418 return 0;
421 else
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;
432 num_entries_copied = 0;
433 base = buf + SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET);
435 for( i = 0; i < num_entries; i++)
437 pid_t pid;
438 char *p = base + (i*SMF_ENTRY_LENGTH);
440 pid = (pid_t)IVAL(p,SME_PID_OFFSET);
442 if(!process_exists(pid))
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;
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);
456 num_entries_copied++;
459 if(num_entries_copied == 0)
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;
473 /* If we deleted some entries we need to re-write the whole number of
474 share mode entries back into the file. */
476 if(num_entries_copied != num_entries)
478 if(sys_lseek(fd, (SMB_OFF_T)0, SEEK_SET) != 0)
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;
490 SIVAL(buf, SMF_NUM_ENTRIES_OFFSET, num_entries_copied);
491 for( i = 0; i < num_entries_copied; i++)
493 char *p = base + (i*SMF_ENTRY_LENGTH);
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);
503 newsize = (base - buf) + (SMF_ENTRY_LENGTH*num_entries_copied);
504 if(write(fd, buf, newsize) != newsize)
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;
515 /* Now truncate the file at this point. */
516 #ifdef FTRUNCATE_NEEDS_ROOT
517 become_root(False);
518 #endif /* FTRUNCATE_NEEDS_ROOT */
520 if(sys_ftruncate(fd, (SMB_OFF_T)newsize)!= 0)
522 #ifdef FTRUNCATE_NEEDS_ROOT
523 int saved_errno = errno;
524 unbecome_root(False);
525 errno = saved_errno;
526 #endif /* FTRUNCATE_NEEDS_ROOT */
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;
539 #ifdef FTRUNCATE_NEEDS_ROOT
540 unbecome_root(False);
541 #endif /* FTRUNCATE_NEEDS_ROOT */
543 if(buf)
544 free(buf);
546 DEBUG(5,("get_share_modes: Read share file %s returning %d entries\n",fname,
547 num_entries_copied));
549 return num_entries_copied;
552 /*******************************************************************
553 del a share mode from a share mode file.
554 ********************************************************************/
555 static void slow_del_share_mode(int token, files_struct *fsp)
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;
568 share_name(fsp->conn, fsp->fd_ptr->dev,
569 fsp->fd_ptr->inode, fname);
571 if(read_share_file( fsp->conn, fd, fname, &buf, &new_file) != 0)
573 DEBUG(0,("ERROR: del_share_mode: Failed to read share file %s\n",
574 fname));
575 return;
578 if(new_file == True)
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;
586 num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET);
588 DEBUG(5,("del_share_mode: share file %s has %d share mode entries.\n",
589 fname, num_entries));
591 /* PARANOIA TEST */
592 if(num_entries < 0)
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;
599 if(num_entries == 0)
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;
610 pid = getpid();
612 /* Go through the entries looking for the particular one
613 we have set - delete it.
616 base = buf + SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET);
618 for(i = 0; i < num_entries; i++)
620 char *p = base + (i*SMF_ENTRY_LENGTH);
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;
628 DEBUG(5,("del_share_mode: deleting entry number %d (of %d) from the share file %s\n",
629 i, num_entries, fname));
631 /* Remove this entry. */
632 if(i != num_entries - 1)
633 memcpy(p, p + SMF_ENTRY_LENGTH, (num_entries - i - 1)*SMF_ENTRY_LENGTH);
635 deleted = True;
636 break;
639 if(!deleted)
641 DEBUG(0,("del_share_mode: entry not found in share file %s\n", fname));
642 if(buf)
643 free(buf);
644 return;
647 num_entries--;
648 SIVAL(buf,SMF_NUM_ENTRIES_OFFSET, num_entries);
650 if(num_entries == 0)
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;
661 /* Re-write the file - and truncate it at the correct point. */
662 if(sys_lseek(fd, (SMB_OFF_T)0, SEEK_SET) != 0)
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;
671 newsize = (base - buf) + (SMF_ENTRY_LENGTH*num_entries);
672 if(write(fd, buf, newsize) != newsize)
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;
681 /* Now truncate the file at this point. */
682 #ifdef FTRUNCATE_NEEDS_ROOT
683 become_root(False);
684 #endif /* FTRUNCATE_NEEDS_ROOT */
686 if(sys_ftruncate(fd, (SMB_OFF_T)newsize) != 0)
688 #ifdef FTRUNCATE_NEEDS_ROOT
689 int saved_errno = errno;
690 unbecome_root(False);
691 errno = saved_errno;
692 #endif /* FTRUNCATE_NEEDS_ROOT */
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;
702 #ifdef FTRUNCATE_NEEDS_ROOT
703 unbecome_root(False);
704 #endif /* FTRUNCATE_NEEDS_ROOT */
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)
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;
722 share_name(fsp->conn, fsp->fd_ptr->dev,
723 fsp->fd_ptr->inode, fname);
725 if(sys_fstat(fd, &sb) != 0)
727 DEBUG(0,("ERROR: set_share_mode: Failed to do stat on share file %s\n",
728 fname));
729 return False;
732 /* Sanity check for file contents (if it's not a new share file). */
733 if(sb.st_size != 0)
735 SMB_OFF_T size = sb.st_size;
737 /* Allocate space for the file plus one extra entry */
738 if((buf = (char *)malloc((size_t)(sb.st_size + SMF_ENTRY_LENGTH))) == NULL)
740 DEBUG(0,("set_share_mode: malloc for file size %d fail !\n",
741 (int)(sb.st_size + SMF_ENTRY_LENGTH)));
742 return False;
745 if(sys_lseek(fd, (SMB_OFF_T)0, SEEK_SET) != 0)
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;
754 if (read(fd,buf,(size_t)sb.st_size) != (size_t)sb.st_size)
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;
763 if (IVAL(buf,SMF_VERSION_OFFSET) != LOCKING_VERSION)
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;
774 size -= (SMF_HEADER_LENGTH + SVAL(buf, SMF_FILENAME_LEN_OFFSET)); /* Remove the header */
776 /* The remaining size must be a multiple of SMF_ENTRY_LENGTH - error if not. */
777 if((size % SMF_ENTRY_LENGTH) != 0)
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;
788 else
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)
794 DEBUG(0,("ERROR: set_share_mode: malloc failed for single entry.\n"));
795 return False;
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);
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);
815 num_entries++;
817 SIVAL(buf,SMF_NUM_ENTRIES_OFFSET,num_entries);
819 if(sys_lseek(fd, (SMB_OFF_T)0, SEEK_SET) != 0)
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;
828 if (write(fd,buf,header_size + (num_entries*SMF_ENTRY_LENGTH)) !=
829 (header_size + (num_entries*SMF_ENTRY_LENGTH)))
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;
839 /* Now truncate the file at this point - just for safety. */
841 #ifdef FTRUNCATE_NEEDS_ROOT
842 become_root(False);
843 #endif /* FTRUNCATE_NEEDS_ROOT */
845 if(sys_ftruncate(fd, (SMB_OFF_T)(header_size + (SMF_ENTRY_LENGTH*num_entries)))!= 0)
848 #ifdef FTRUNCATE_NEEDS_ROOT
849 int saved_errno = errno;
850 unbecome_root(False);
851 errno = saved_errno;
852 #endif /* FTRUNCATE_NEEDS_ROOT */
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;
862 #ifdef FTRUNCATE_NEEDS_ROOT
863 unbecome_root(False);
864 #endif /* FTRUNCATE_NEEDS_ROOT */
866 if(buf)
867 free(buf);
869 DEBUG(3,("set_share_mode: Created share file %s with \
870 mode 0x%X pid=%d\n",fname,fsp->share_mode,(int)pid));
872 return True;
875 /*******************************************************************
876 Call a generic modify function for a share mode entry.
877 ********************************************************************/
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)
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;
895 share_name(fsp->conn, fsp->fd_ptr->dev,
896 fsp->fd_ptr->inode, fname);
898 if(read_share_file( fsp->conn, fd, fname, &buf, &new_file) != 0)
900 DEBUG(0,("ERROR: slow_mod_share_entry: Failed to read share file %s\n",
901 fname));
902 return False;
905 if(new_file == True)
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;
913 num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET);
915 DEBUG(5,("slow_mod_share_entry: share file %s has %d share mode entries.\n",
916 fname, num_entries));
918 /* PARANOIA TEST */
919 if(num_entries < 0)
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;
926 if(num_entries == 0)
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;
937 pid = getpid();
939 base = buf + SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET);
941 for(i = 0; i < num_entries; i++)
943 char *p = base + (i*SMF_ENTRY_LENGTH);
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;
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));
955 * Copy into the share_mode_entry structure and then call
956 * the generic function with the given parameter.
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);
966 (*mod_fn)( &entry, fsp->fd_ptr->dev, fsp->fd_ptr->inode, param);
969 * Now copy any changes the function made back into the buffer.
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);
979 found = True;
980 break;
983 if(!found)
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;
991 /* Re-write the file - and truncate it at the correct point. */
992 if(sys_lseek(fd, (SMB_OFF_T)0, SEEK_SET) != 0)
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;
1001 fsize = (base - buf) + (SMF_ENTRY_LENGTH*num_entries);
1002 if(write(fd, buf, fsize) != fsize)
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;
1011 return True;
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 *))
1022 int i, count=0;
1023 DIR *dir;
1024 char *s;
1025 share_mode_entry e;
1027 dir = opendir(lp_lockdir());
1028 if (!dir) {
1029 return(0);
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;
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 */
1052 pstrcpy(lname,lp_lockdir());
1053 trim_string(lname,NULL,"/");
1054 pstrcat(lname,"/");
1055 pstrcat(lname,s);
1057 fd = sys_open(lname,read_only?O_RDONLY:O_RDWR,0);
1058 if (fd < 0) {
1059 continue;
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;
1069 if(read_share_file( 0, fd, lname, &buf, &new_file)) {
1070 close(fd);
1071 continue;
1074 if(new_file == True) {
1075 close(fd);
1076 continue;
1079 pstrcpy( fname, &buf[10]);
1080 close(fd);
1082 base = buf + SMF_HEADER_LENGTH +
1083 SVAL(buf,SMF_FILENAME_LEN_OFFSET);
1084 for( i = 0; i < IVAL(buf, SMF_NUM_ENTRIES_OFFSET); i++) {
1085 char *p = base + (i*SMF_ENTRY_LENGTH);
1086 e.pid = (pid_t)IVAL(p,SME_PID_OFFSET);
1087 e.share_mode = IVAL(p,SME_SHAREMODE_OFFSET);
1088 e.time.tv_sec = IVAL(p,SME_SEC_OFFSET);
1089 e.time.tv_usec = IVAL(p,SME_USEC_OFFSET);
1090 e.op_port = SVAL(p,SME_PORT_OFFSET);
1091 e.op_type = SVAL(p,SME_OPLOCK_TYPE_OFFSET);
1093 if (process_exists(e.pid)) {
1094 fn(&e, fname);
1095 count++;
1097 } /* end for i */
1099 if(buf)
1100 free(buf);
1101 base = 0;
1102 } /* end while */
1103 closedir(dir);
1105 return count;
1109 /*******************************************************************
1110 dump the state of the system
1111 ********************************************************************/
1112 static void slow_share_status(FILE *f)
1118 static struct share_ops share_ops = {
1119 slow_stop_share_mode_mgmt,
1120 slow_lock_share_entry,
1121 slow_unlock_share_entry,
1122 slow_get_share_modes,
1123 slow_del_share_mode,
1124 slow_set_share_mode,
1125 slow_mod_share_entry,
1126 slow_share_forall,
1127 slow_share_status,
1130 /*******************************************************************
1131 initialize the slow share_mode management
1132 ******************************************************************/
1133 struct share_ops *locking_slow_init(int ronly)
1136 read_only = ronly;
1138 if (!directory_exist(lp_lockdir(),NULL)) {
1139 if (!read_only)
1140 mkdir(lp_lockdir(),0755);
1141 if (!directory_exist(lp_lockdir(),NULL))
1142 return NULL;
1145 return &share_ops;
1147 #else
1148 int locking_slow_dummy_procedure(void);
1149 int locking_slow_dummy_procedure(void) {return 0;}
1150 #endif /* !FAST_SHARE_MODES */