Makefile.in: Moved blocking lock code into smbd/blocking.c for link purposes.
[jra/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   if (OPEN_FSP(fsp) && fsp->can_lock && (fsp->conn == conn))
113     ok = fcntl_lock(fsp->fd_ptr->fd,F_SETLK,offset,count,
114                     map_lock_type(fsp,lock_type));
115
116   if (!ok) {
117     *eclass = ERRDOS;
118     *ecode = ERRlock;
119     return False;
120   }
121   return True; /* Got lock */
122 }
123
124
125 /****************************************************************************
126  Utility function called by unlocking requests.
127 ****************************************************************************/
128 BOOL do_unlock(files_struct *fsp,connection_struct *conn,
129                uint32 count,uint32 offset,int *eclass,uint32 *ecode)
130 {
131   BOOL ok = False;
132
133   if (!lp_locking(SNUM(conn)))
134     return(True);
135
136   if (OPEN_FSP(fsp) && fsp->can_lock && (fsp->conn == conn))
137     ok = fcntl_lock(fsp->fd_ptr->fd,F_SETLK,offset,count,F_UNLCK);
138    
139   if (!ok) {
140     *eclass = ERRDOS;
141     *ecode = ERRlock;
142     return False;
143   }
144   return True; /* Did unlock */
145 }
146
147
148
149 /****************************************************************************
150  Initialise the locking functions.
151 ****************************************************************************/
152
153 BOOL locking_init(int read_only)
154 {
155         if (share_ops) return True;
156
157 #ifdef FAST_SHARE_MODES
158         share_ops = locking_shm_init(read_only);
159 #else
160         share_ops = locking_slow_init(read_only);
161 #endif
162
163         if (!share_ops) {
164                 DEBUG(0,("ERROR: Failed to initialise share modes!\n"));
165                 return False;
166         }
167         
168         return True;
169 }
170
171 /*******************************************************************
172  Deinitialize the share_mode management.
173 ******************************************************************/
174
175 BOOL locking_end(void)
176 {
177         if (share_ops)
178                 return share_ops->stop_mgmt();
179         return True;
180 }
181
182
183 /*******************************************************************
184  Lock a hash bucket entry.
185 ******************************************************************/
186 BOOL lock_share_entry(connection_struct *conn,
187                       uint32 dev, uint32 inode, int *ptok)
188 {
189         return share_ops->lock_entry(conn, dev, inode, ptok);
190 }
191
192 /*******************************************************************
193  Unlock a hash bucket entry.
194 ******************************************************************/
195 BOOL unlock_share_entry(connection_struct *conn,
196                         uint32 dev, uint32 inode, int token)
197 {
198         return share_ops->unlock_entry(conn, dev, inode, token);
199 }
200
201 /*******************************************************************
202  Get all share mode entries for a dev/inode pair.
203 ********************************************************************/
204 int get_share_modes(connection_struct *conn, 
205                     int token, uint32 dev, uint32 inode, 
206                     share_mode_entry **shares)
207 {
208         return share_ops->get_entries(conn, token, dev, inode, shares);
209 }
210
211 /*******************************************************************
212  Del the share mode of a file.
213 ********************************************************************/
214 void del_share_mode(int token, files_struct *fsp)
215 {
216         share_ops->del_entry(token, fsp);
217 }
218
219 /*******************************************************************
220  Set the share mode of a file. Return False on fail, True on success.
221 ********************************************************************/
222 BOOL set_share_mode(int token, files_struct *fsp, uint16 port, uint16 op_type)
223 {
224         return share_ops->set_entry(token, fsp, port, op_type);
225 }
226
227 /*******************************************************************
228  Remove an oplock port and mode entry from a share mode.
229 ********************************************************************/
230 BOOL remove_share_oplock(files_struct *fsp, int token)
231 {
232         return share_ops->remove_oplock(fsp, token);
233 }
234
235 /*******************************************************************
236  Call the specified function on each entry under management by the
237  share mode system.
238 ********************************************************************/
239
240 int share_mode_forall(void (*fn)(share_mode_entry *, char *))
241 {
242         return share_ops->forall(fn);
243 }
244
245 /*******************************************************************
246  Dump the state of the system.
247 ********************************************************************/
248
249 void share_status(FILE *f)
250 {
251         share_ops->status(f);
252 }