2 Unix SMB/Netbios implementation.
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.
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
32 October 1997 - split into separate file (tridge)
37 #ifndef FAST_SHARE_MODES
39 extern int DEBUGLEVEL
;
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
66 #define SHARE_FILE_MODE 0644
71 /*******************************************************************
72 deinitialize share_mode management
73 ******************************************************************/
74 static BOOL
slow_stop_share_mode_mgmt(void)
80 /*******************************************************************
82 ******************************************************************/
83 static BOOL
share_name(connection_struct
*conn
,
84 SMB_DEV_T dev
, SMB_INO_T inode
, char *name
)
87 pstrcpy(name
,lp_lockdir());
88 trim_string(name
,"","/");
89 if (!*name
) return(False
);
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 */
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 */
111 if(unlink(fname
) != 0)
113 DEBUG(0,("delete_share_file: Can't delete share file %s (%s)\n",
114 fname
, strerror(errno
)));
118 DEBUG(5,("delete_share_file: Deleted share file %s\n", fname
));
121 /* return to our previous privilege level */
122 unbecome_root(False
);
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
)
139 if(!share_name(conn
, dev
, inode
, fname
))
142 if (read_only
) return True
;
144 /* we need to do this as root */
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
);
172 DEBUG(0,("ERROR lock_share_entry: failed to open share file %s. Error was %s\n",
173 fname
, strerror(errno
)));
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
)));
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
)));
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
213 /* return to our previous privilege level */
214 unbecome_root(False
);
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
)
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
)));
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 */
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",
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
)
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
)));
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",
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
)));
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
)));
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
));
325 delete_share_file(conn
, fname
);
329 /* Sanity check for file contents */
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
));
343 delete_share_file(conn
, fname
);
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
)
362 int num_entries_copied
;
364 share_mode_entry
*share_array
;
371 /* Read the share file header - this is of the form:
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 :
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",
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
));
406 DEBUG(0,("PANIC ERROR:get_share_mode: num_share_mode_entries < 0 (%d) \
407 for share file %s\n", num_entries
, fname
));
413 *old_shares
= share_array
= (share_mode_entry
*)
414 malloc(num_entries
* sizeof(share_mode_entry
));
417 DEBUG(0,("get_share_modes: malloc fail !\n"));
423 /* No entries - just delete the file. */
424 DEBUG(0,("get_share_modes: share file %s has no share mode entries - deleting.\n",
428 delete_share_file(conn
, fname
);
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
++)
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
));
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",
465 free((char *)*old_shares
);
469 delete_share_file(conn
, fname
);
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
)));
483 free((char *)*old_shares
);
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
)));
509 free((char *)*old_shares
);
515 /* Now truncate the file at this point. */
516 #ifdef FTRUNCATE_NEEDS_ROOT
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
);
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
)));
531 free((char *)*old_shares
);
539 #ifdef FTRUNCATE_NEEDS_ROOT
540 unbecome_root(False
);
541 #endif /* FTRUNCATE_NEEDS_ROOT */
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
)
565 BOOL deleted
= False
;
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",
580 DEBUG(0,("ERROR:del_share_mode: share file %s is new (size zero), deleting it.\n",
582 delete_share_file(fsp
->conn
, fname
);
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
));
594 DEBUG(0,("PANIC ERROR:del_share_mode: num_share_mode_entries < 0 (%d) \
595 for share file %s\n", num_entries
, fname
));
601 /* No entries - just delete the file. */
602 DEBUG(0,("del_share_mode: share file %s has no share mode entries - deleting.\n",
606 delete_share_file(fsp
->conn
, fname
);
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
))
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
);
641 DEBUG(0,("del_share_mode: entry not found in share file %s\n", fname
));
648 SIVAL(buf
,SMF_NUM_ENTRIES_OFFSET
, num_entries
);
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",
657 delete_share_file(fsp
->conn
,fname
);
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
)));
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
)));
681 /* Now truncate the file at this point. */
682 #ifdef FTRUNCATE_NEEDS_ROOT
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
);
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
)));
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
)
715 pid_t pid
= getpid();
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",
732 /* Sanity check for file contents (if it's not a new share file). */
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
)));
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
)));
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
)));
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
),
770 delete_share_file(fsp
->conn
, fname
);
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
));
783 delete_share_file(fsp
->conn
, fname
);
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"));
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
);
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
)));
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
);
839 /* Now truncate the file at this point - just for safety. */
841 #ifdef FTRUNCATE_NEEDS_ROOT
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
);
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
),
862 #ifdef FTRUNCATE_NEEDS_ROOT
863 unbecome_root(False
);
864 #endif /* FTRUNCATE_NEEDS_ROOT */
869 DEBUG(3,("set_share_mode: Created share file %s with \
870 mode 0x%X pid=%d\n",fname
,fsp
->share_mode
,(int)pid
));
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 *),
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",
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
);
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
));
921 DEBUG(0,("PANIC ERROR:slow_mod_share_entry: num_share_mode_entries < 0 (%d) \
922 for share file %s\n", num_entries
, fname
));
928 /* No entries - just delete the file. */
929 DEBUG(0,("slow_mod_share_entry: share file %s has no share mode entries - deleting.\n",
933 delete_share_file(fsp
->conn
, fname
);
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
))
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
);
985 DEBUG(0,("slow_mod_share_entry: entry not found in share file %s\n", fname
));
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
)));
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
)));
1016 /*******************************************************************
1017 call the specified function on each entry under management by the
1019 ********************************************************************/
1020 static int slow_share_forall(void (*fn
)(share_mode_entry
*, char *))
1027 dir
= opendir(lp_lockdir());
1032 while ((s
=readdirname(dir
))) {
1042 #ifdef LARGE_SMB_INO_T
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
,"/");
1057 fd
= sys_open(lname
,read_only
?O_RDONLY
:O_RDWR
,0);
1062 /* Lock the share mode file while we read it. */
1064 fcntl_lock(fd
, SMB_F_SETLKW
, 0, 1, F_WRLCK
) == False
) {
1069 if(read_share_file( 0, fd
, lname
, &buf
, &new_file
)) {
1074 if(new_file
== True
) {
1079 pstrcpy( fname
, &buf
[10]);
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
)) {
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
,
1130 /*******************************************************************
1131 initialize the slow share_mode management
1132 ******************************************************************/
1133 struct share_ops
*locking_slow_init(int ronly
)
1138 if (!directory_exist(lp_lockdir(),NULL
)) {
1140 mkdir(lp_lockdir(),0755);
1141 if (!directory_exist(lp_lockdir(),NULL
))
1148 int locking_slow_dummy_procedure(void);
1149 int locking_slow_dummy_procedure(void) {return 0;}
1150 #endif /* !FAST_SHARE_MODES */