4f2c9ab34589be599719cf58f6bb4c6b719ec725
[samba.git] / source3 / locking / locking.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    Locking functions
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 */
33
34 #include "includes.h"
35 extern int DEBUGLEVEL;
36
37 static struct share_ops *share_ops;
38
39 /****************************************************************************
40  Utility function to map a lock type correctly depending on the real open
41  mode of a file.
42 ****************************************************************************/
43
44 static int map_lock_type( files_struct *fsp, int lock_type)
45 {
46   if((lock_type == F_WRLCK) && (fsp->fd_ptr->real_open_flags == O_RDONLY)) {
47     /*
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.
51      */
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)) {
55     /*
56      * Ditto for read locks on write only files.
57      */
58     DEBUG(10,("map_lock_type: Changing read lock to write due to write-only file.\n"));
59     return F_WRLCK;
60   }
61
62   /*
63    * This return should be the most normal, as we attempt
64    * to always open files read/write.
65    */
66
67   return lock_type;
68 }
69
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                uint32 count,uint32 offset, int lock_type)
75 {
76         int snum = SNUM(conn);
77
78         if (count == 0)
79                 return(False);
80
81         if (!lp_locking(snum) || !lp_strict_locking(snum))
82                 return(False);
83
84         /*
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.
88          */
89         
90         return(fcntl_lock(fsp->fd_ptr->fd,F_GETLK,offset,count,lock_type));
91 }
92
93
94 /****************************************************************************
95  Utility function called by locking requests.
96 ****************************************************************************/
97 BOOL do_lock(files_struct *fsp,connection_struct *conn,
98              uint32 count,uint32 offset,int lock_type,
99              int *eclass,uint32 *ecode)
100 {
101   BOOL ok = False;
102
103   if (!lp_locking(SNUM(conn)))
104     return(True);
105
106   if (count == 0) {
107     *eclass = ERRDOS;
108     *ecode = ERRnoaccess;
109     return False;
110   }
111
112   DEBUG(10,("do_lock: lock type %d start=%d len=%d requested for file %s\n",
113         lock_type, (int)offset, (int)count, fsp->fsp_name ));
114
115   if (OPEN_FSP(fsp) && fsp->can_lock && (fsp->conn == conn))
116     ok = fcntl_lock(fsp->fd_ptr->fd,F_SETLK,offset,count,
117                     map_lock_type(fsp,lock_type));
118
119   if (!ok) {
120     *eclass = ERRDOS;
121     *ecode = ERRlock;
122     return False;
123   }
124   return True; /* Got lock */
125 }
126
127
128 /****************************************************************************
129  Utility function called by unlocking requests.
130 ****************************************************************************/
131 BOOL do_unlock(files_struct *fsp,connection_struct *conn,
132                uint32 count,uint32 offset,int *eclass,uint32 *ecode)
133 {
134   BOOL ok = False;
135
136   if (!lp_locking(SNUM(conn)))
137     return(True);
138
139   DEBUG(10,("do_unlock: unlock start=%d len=%d requested for file %s\n",
140         (int)offset, (int)count, fsp->fsp_name ));
141
142   if (OPEN_FSP(fsp) && fsp->can_lock && (fsp->conn == conn))
143     ok = fcntl_lock(fsp->fd_ptr->fd,F_SETLK,offset,count,F_UNLCK);
144    
145   if (!ok) {
146     *eclass = ERRDOS;
147     *ecode = ERRlock;
148     return False;
149   }
150   return True; /* Did unlock */
151 }
152
153
154
155 /****************************************************************************
156  Initialise the locking functions.
157 ****************************************************************************/
158
159 BOOL locking_init(int read_only)
160 {
161         if (share_ops) return True;
162
163 #ifdef FAST_SHARE_MODES
164         share_ops = locking_shm_init(read_only);
165 #else
166         share_ops = locking_slow_init(read_only);
167 #endif
168
169         if (!share_ops) {
170                 DEBUG(0,("ERROR: Failed to initialise share modes!\n"));
171                 return False;
172         }
173         
174         return True;
175 }
176
177 /*******************************************************************
178  Deinitialize the share_mode management.
179 ******************************************************************/
180
181 BOOL locking_end(void)
182 {
183         if (share_ops)
184                 return share_ops->stop_mgmt();
185         return True;
186 }
187
188
189 /*******************************************************************
190  Lock a hash bucket entry.
191 ******************************************************************/
192 BOOL lock_share_entry(connection_struct *conn,
193                       uint32 dev, uint32 inode, int *ptok)
194 {
195         return share_ops->lock_entry(conn, dev, inode, ptok);
196 }
197
198 /*******************************************************************
199  Unlock a hash bucket entry.
200 ******************************************************************/
201 BOOL unlock_share_entry(connection_struct *conn,
202                         uint32 dev, uint32 inode, int token)
203 {
204         return share_ops->unlock_entry(conn, dev, inode, token);
205 }
206
207 /*******************************************************************
208  Get all share mode entries for a dev/inode pair.
209 ********************************************************************/
210 int get_share_modes(connection_struct *conn, 
211                     int token, uint32 dev, uint32 inode, 
212                     share_mode_entry **shares)
213 {
214         return share_ops->get_entries(conn, token, dev, inode, shares);
215 }
216
217 /*******************************************************************
218  Del the share mode of a file.
219 ********************************************************************/
220 void del_share_mode(int token, files_struct *fsp)
221 {
222         share_ops->del_entry(token, fsp);
223 }
224
225 /*******************************************************************
226  Set the share mode of a file. Return False on fail, True on success.
227 ********************************************************************/
228 BOOL set_share_mode(int token, files_struct *fsp, uint16 port, uint16 op_type)
229 {
230         return share_ops->set_entry(token, fsp, port, op_type);
231 }
232
233 /*******************************************************************
234  Remove an oplock port and mode entry from a share mode.
235 ********************************************************************/
236 BOOL remove_share_oplock(files_struct *fsp, int token)
237 {
238         return share_ops->remove_oplock(fsp, token);
239 }
240
241 /*******************************************************************
242  Call the specified function on each entry under management by the
243  share mode system.
244 ********************************************************************/
245
246 int share_mode_forall(void (*fn)(share_mode_entry *, char *))
247 {
248         return share_ops->forall(fn);
249 }
250
251 /*******************************************************************
252  Dump the state of the system.
253 ********************************************************************/
254
255 void share_status(FILE *f)
256 {
257         share_ops->status(f);
258 }