2 Unix SMB/Netbios 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
35 extern int DEBUGLEVEL
;
37 static struct share_ops
*share_ops
;
39 /****************************************************************************
40 Utility function to map a lock type correctly depending on the real open
42 ****************************************************************************/
44 static int map_lock_type( files_struct
*fsp
, int lock_type
)
46 if((lock_type
== F_WRLCK
) && (fsp
->fd_ptr
->real_open_flags
== O_RDONLY
)) {
48 * Many UNIX's cannot get a write lock on a file opened read-only.
49 * Win32 locking semantics allow this.
50 * Do the best we can and attempt a read-only lock.
52 DEBUG(10,("map_lock_type: Downgrading write lock to read due to read-only file.\n"));
54 } else if( (lock_type
== F_RDLCK
) && (fsp
->fd_ptr
->real_open_flags
== O_WRONLY
)) {
56 * Ditto for read locks on write only files.
58 DEBUG(10,("map_lock_type: Changing read lock to write due to write-only file.\n"));
63 * This return should be the most normal, as we attempt
64 * to always open files read/write.
70 /****************************************************************************
71 Utility function called to see if a file region is locked.
72 ****************************************************************************/
73 BOOL
is_locked(files_struct
*fsp
,connection_struct
*conn
,
74 SMB_OFF_T count
,SMB_OFF_T offset
, int lock_type
)
76 int snum
= SNUM(conn
);
81 if (!lp_locking(snum
) || !lp_strict_locking(snum
))
85 * Note that most UNIX's can *test* for a write lock on
86 * a read-only fd, just not *set* a write lock on a read-only
87 * fd. So we don't need to use map_lock_type here.
90 return(fcntl_lock(fsp
->fd_ptr
->fd
,SMB_F_GETLK
,offset
,count
,lock_type
));
94 /****************************************************************************
95 Utility function called by locking requests.
96 ****************************************************************************/
97 BOOL
do_lock(files_struct
*fsp
,connection_struct
*conn
,
98 SMB_OFF_T count
,SMB_OFF_T offset
,int lock_type
,
99 int *eclass
,uint32
*ecode
)
103 if (!lp_locking(SNUM(conn
)))
108 *ecode
= ERRnoaccess
;
112 DEBUG(10,("do_lock: lock type %d start=%.0f len=%.0f requested for file %s\n",
113 lock_type
, (double)offset
, (double)count
, fsp
->fsp_name
));
115 if (OPEN_FSP(fsp
) && fsp
->can_lock
&& (fsp
->conn
== conn
))
116 ok
= fcntl_lock(fsp
->fd_ptr
->fd
,SMB_F_SETLK
,offset
,count
,
117 map_lock_type(fsp
,lock_type
));
124 return True
; /* Got lock */
128 /****************************************************************************
129 Utility function called by unlocking requests.
130 ****************************************************************************/
131 BOOL
do_unlock(files_struct
*fsp
,connection_struct
*conn
,
132 SMB_OFF_T count
,SMB_OFF_T offset
,int *eclass
,uint32
*ecode
)
136 if (!lp_locking(SNUM(conn
)))
139 DEBUG(10,("do_unlock: unlock start=%.0f len=%.0f requested for file %s\n",
140 (double)offset
, (double)count
, fsp
->fsp_name
));
142 if (OPEN_FSP(fsp
) && fsp
->can_lock
&& (fsp
->conn
== conn
))
143 ok
= fcntl_lock(fsp
->fd_ptr
->fd
,SMB_F_SETLK
,offset
,count
,F_UNLCK
);
150 return True
; /* Did unlock */
153 /****************************************************************************
154 Initialise the locking functions.
155 ****************************************************************************/
157 BOOL
locking_init(int read_only
)
162 #ifdef FAST_SHARE_MODES
163 share_ops
= locking_shm_init(read_only
);
164 if (!share_ops
&& read_only
&& (getuid() == 0)) {
165 /* this may be the first time the share modes code has
166 been run. Initialise it now by running it read-write */
167 share_ops
= locking_shm_init(0);
170 share_ops
= locking_slow_init(read_only
);
174 DEBUG(0,("ERROR: Failed to initialise share modes\n"));
181 /*******************************************************************
182 Deinitialize the share_mode management.
183 ******************************************************************/
185 BOOL
locking_end(void)
188 return share_ops
->stop_mgmt();
193 /*******************************************************************
194 Lock a hash bucket entry.
195 ******************************************************************/
196 BOOL
lock_share_entry(connection_struct
*conn
,
197 SMB_DEV_T dev
, SMB_INO_T inode
, int *ptok
)
199 return share_ops
->lock_entry(conn
, dev
, inode
, ptok
);
202 /*******************************************************************
203 Unlock a hash bucket entry.
204 ******************************************************************/
205 BOOL
unlock_share_entry(connection_struct
*conn
,
206 SMB_DEV_T dev
, SMB_INO_T inode
, int token
)
208 return share_ops
->unlock_entry(conn
, dev
, inode
, token
);
211 /*******************************************************************
212 Get all share mode entries for a dev/inode pair.
213 ********************************************************************/
214 int get_share_modes(connection_struct
*conn
,
215 int token
, SMB_DEV_T dev
, SMB_INO_T inode
,
216 share_mode_entry
**shares
)
218 return share_ops
->get_entries(conn
, token
, dev
, inode
, shares
);
221 /*******************************************************************
222 Del the share mode of a file.
223 ********************************************************************/
224 void del_share_mode(int token
, files_struct
*fsp
)
226 share_ops
->del_entry(token
, fsp
);
229 /*******************************************************************
230 Set the share mode of a file. Return False on fail, True on success.
231 ********************************************************************/
232 BOOL
set_share_mode(int token
, files_struct
*fsp
, uint16 port
, uint16 op_type
)
234 return share_ops
->set_entry(token
, fsp
, port
, op_type
);
237 /*******************************************************************
238 Static function that actually does the work for the generic function
240 ********************************************************************/
242 static void remove_share_oplock_fn(share_mode_entry
*entry
, SMB_DEV_T dev
, SMB_INO_T inode
,
245 DEBUG(10,("remove_share_oplock_fn: removing oplock info for entry dev=%x ino=%.0f\n",
246 (unsigned int)dev
, (double)inode
));
247 /* Delete the oplock info. */
249 entry
->op_type
= NO_OPLOCK
;
252 /*******************************************************************
253 Remove an oplock port and mode entry from a share mode.
254 ********************************************************************/
256 BOOL
remove_share_oplock(int token
, files_struct
*fsp
)
258 return share_ops
->mod_entry(token
, fsp
, remove_share_oplock_fn
, NULL
);
261 /*******************************************************************
262 Static function that actually does the work for the generic function
264 ********************************************************************/
266 static void downgrade_share_oplock_fn(share_mode_entry
*entry
, SMB_DEV_T dev
, SMB_INO_T inode
,
269 DEBUG(10,("downgrade_share_oplock_fn: downgrading oplock info for entry dev=%x ino=%.0f\n",
270 (unsigned int)dev
, (double)inode
));
271 entry
->op_type
= LEVEL_II_OPLOCK
;
274 /*******************************************************************
275 Downgrade a oplock type from exclusive to level II.
276 ********************************************************************/
278 BOOL
downgrade_share_oplock(int token
, files_struct
*fsp
)
280 return share_ops
->mod_entry(token
, fsp
, downgrade_share_oplock_fn
, NULL
);
283 /*******************************************************************
284 Static function that actually does the work for the generic function
286 ********************************************************************/
293 static void modify_share_mode_fn(share_mode_entry
*entry
, SMB_DEV_T dev
, SMB_INO_T inode
,
296 struct mod_val
*mvp
= (struct mod_val
*)param
;
298 DEBUG(10,("modify_share_mode_fn: changing share mode info from %x to %x for entry dev=%x ino=%.0f\n",
299 entry
->share_mode
, mvp
->new_share_mode
, (unsigned int)dev
, (double)inode
));
300 DEBUG(10,("modify_share_mode_fn: changing oplock state from %x to %x for entry dev=%x ino=%.0f\n",
301 entry
->op_type
, (int)mvp
->new_oplock
, (unsigned int)dev
, (double)inode
));
302 /* Change the share mode info. */
303 entry
->share_mode
= mvp
->new_share_mode
;
304 entry
->op_type
= mvp
->new_oplock
;
307 /*******************************************************************
308 Modify a share mode on a file. Used by the delete open file code.
309 Return False on fail, True on success.
310 ********************************************************************/
312 BOOL
modify_share_mode(int token
, files_struct
*fsp
, int new_mode
, uint16 new_oplock
)
316 mv
.new_share_mode
= new_mode
;
317 mv
.new_oplock
= new_oplock
;
319 return share_ops
->mod_entry(token
, fsp
, modify_share_mode_fn
, (void *)&mv
);
322 /*******************************************************************
323 Call the specified function on each entry under management by the
325 ********************************************************************/
327 int share_mode_forall(void (*fn
)(share_mode_entry
*, char *))
329 if (!share_ops
) return 0;
330 return share_ops
->forall(fn
);
333 /*******************************************************************
334 Dump the state of the system.
335 ********************************************************************/
337 void share_status(FILE *f
)
339 share_ops
->status(f
);