Correct PPTP server firewall rules chain.
[tomato/davidwu.git] / release / src / router / samba / source / locking / locking.c
blob012d954e501533402bc5b53c350bb8a2d7d29590
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 Locking functions
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.
34 #include "includes.h"
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
41 mode of a file.
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"));
53 return F_RDLCK;
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"));
59 return F_WRLCK;
63 * This return should be the most normal, as we attempt
64 * to always open files read/write.
67 return lock_type;
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);
78 if (count == 0)
79 return(False);
81 if (!lp_locking(snum) || !lp_strict_locking(snum))
82 return(False);
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)
101 BOOL ok = False;
103 if (!lp_locking(SNUM(conn)))
104 return(True);
106 if (count == 0) {
107 *eclass = ERRDOS;
108 *ecode = ERRnoaccess;
109 return False;
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));
119 if (!ok) {
120 *eclass = ERRDOS;
121 *ecode = ERRlock;
122 return False;
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)
134 BOOL ok = False;
136 if (!lp_locking(SNUM(conn)))
137 return(True);
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);
145 if (!ok) {
146 *eclass = ERRDOS;
147 *ecode = ERRlock;
148 return False;
150 return True; /* Did unlock */
153 /****************************************************************************
154 Initialise the locking functions.
155 ****************************************************************************/
157 BOOL locking_init(int read_only)
159 if (share_ops)
160 return True;
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);
169 #else
170 share_ops = locking_slow_init(read_only);
171 #endif
173 if (!share_ops) {
174 DEBUG(0,("ERROR: Failed to initialise share modes\n"));
175 return False;
178 return True;
181 /*******************************************************************
182 Deinitialize the share_mode management.
183 ******************************************************************/
185 BOOL locking_end(void)
187 if (share_ops)
188 return share_ops->stop_mgmt();
189 return True;
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
239 below.
240 ********************************************************************/
242 static void remove_share_oplock_fn(share_mode_entry *entry, SMB_DEV_T dev, SMB_INO_T inode,
243 void *param)
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. */
248 entry->op_port = 0;
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
263 below.
264 ********************************************************************/
266 static void downgrade_share_oplock_fn(share_mode_entry *entry, SMB_DEV_T dev, SMB_INO_T inode,
267 void *param)
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
285 below.
286 ********************************************************************/
288 struct mod_val {
289 int new_share_mode;
290 uint16 new_oplock;
293 static void modify_share_mode_fn(share_mode_entry *entry, SMB_DEV_T dev, SMB_INO_T inode,
294 void *param)
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)
314 struct mod_val mv;
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
324 share mode system.
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);