damn. We need root privilages to do semaphore operations even if we
[kai/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-1997
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 extern connection_struct Connections[];
37 extern files_struct Files[];
38
39 static struct share_ops *share_ops;
40
41 /****************************************************************************
42   utility function called to see if a file region is locked
43 ****************************************************************************/
44 BOOL is_locked(int fnum,int cnum,uint32 count,uint32 offset)
45 {
46   int snum = SNUM(cnum);
47
48   if (count == 0)
49     return(False);
50
51   if (!lp_locking(snum) || !lp_strict_locking(snum))
52     return(False);
53
54   return(fcntl_lock(Files[fnum].fd_ptr->fd,F_GETLK,offset,count,
55                    (Files[fnum].can_write?F_WRLCK:F_RDLCK)));
56 }
57
58
59 /****************************************************************************
60   utility function called by locking requests
61 ****************************************************************************/
62 BOOL do_lock(int fnum,int cnum,uint32 count,uint32 offset,int *eclass,uint32 *ecode)
63 {
64   BOOL ok = False;
65
66   if (!lp_locking(SNUM(cnum)))
67     return(True);
68
69   if (count == 0) {
70     *eclass = ERRDOS;
71     *ecode = ERRnoaccess;
72     return False;
73   }
74
75   if (Files[fnum].can_lock && OPEN_FNUM(fnum) && (Files[fnum].cnum == cnum))
76     ok = fcntl_lock(Files[fnum].fd_ptr->fd,F_SETLK,offset,count,
77                     (Files[fnum].can_write?F_WRLCK:F_RDLCK));
78
79   if (!ok) {
80     *eclass = ERRDOS;
81     *ecode = ERRlock;
82     return False;
83   }
84   return True; /* Got lock */
85 }
86
87
88 /****************************************************************************
89   utility function called by unlocking requests
90 ****************************************************************************/
91 BOOL do_unlock(int fnum,int cnum,uint32 count,uint32 offset,int *eclass,uint32 *ecode)
92 {
93   BOOL ok = False;
94
95   if (!lp_locking(SNUM(cnum)))
96     return(True);
97
98   if (Files[fnum].can_lock && OPEN_FNUM(fnum) && (Files[fnum].cnum == cnum))
99     ok = fcntl_lock(Files[fnum].fd_ptr->fd,F_SETLK,offset,count,F_UNLCK);
100    
101   if (!ok) {
102     *eclass = ERRDOS;
103     *ecode = ERRlock;
104     return False;
105   }
106   return True; /* Did unlock */
107 }
108
109
110
111 /****************************************************************************
112   initialise the locking functions
113 ****************************************************************************/
114 BOOL locking_init(int read_only)
115 {
116         if (share_ops) return True;
117
118 #ifdef FAST_SHARE_MODES
119         share_ops = locking_shm_init(read_only);
120         if (!share_ops) {
121                 DEBUG(0,("ERROR: Failed to initialise fast share modes - trying slow code\n"));
122         }
123         if (share_ops) return True;
124 #endif  
125
126         share_ops = locking_slow_init(read_only);
127         if (!share_ops) {
128                 DEBUG(0,("ERROR: Failed to initialise share modes!\n"));
129                 return False;
130         }
131         
132         return True;
133 }
134
135 /*******************************************************************
136   deinitialize the share_mode management 
137   ******************************************************************/
138 BOOL locking_end(void)
139 {
140         if (share_ops)
141                 return share_ops->stop_mgmt();
142         return True;
143 }
144
145
146 /*******************************************************************
147   lock a hash bucket entry 
148   ******************************************************************/
149 BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, int *ptok)
150 {
151         return share_ops->lock_entry(cnum, dev, inode, ptok);
152 }
153
154 /*******************************************************************
155   unlock a hash bucket entry
156   ******************************************************************/
157 BOOL unlock_share_entry(int cnum, uint32 dev, uint32 inode, int token)
158 {
159         return share_ops->unlock_entry(cnum, dev, inode, token);
160 }
161
162 /*******************************************************************
163 get all share mode entries for a dev/inode pair.
164 ********************************************************************/
165 int get_share_modes(int cnum, int token, uint32 dev, uint32 inode, 
166                     share_mode_entry **shares)
167 {
168         return share_ops->get_entries(cnum, token, dev, inode, shares);
169 }
170
171 /*******************************************************************
172 del the share mode of a file.
173 ********************************************************************/
174 void del_share_mode(int token, int fnum)
175 {
176         share_ops->del_entry(token, fnum);
177 }
178
179 /*******************************************************************
180 set the share mode of a file. Return False on fail, True on success.
181 ********************************************************************/
182 BOOL set_share_mode(int token, int fnum, uint16 port, uint16 op_type)
183 {
184         return share_ops->set_entry(token, fnum, port, op_type);
185 }
186
187 /*******************************************************************
188 Remove an oplock port and mode entry from a share mode.
189 ********************************************************************/
190 BOOL remove_share_oplock(int fnum, int token)
191 {
192         return share_ops->remove_oplock(fnum, token);
193 }
194
195
196 /*******************************************************************
197 call the specified function on each entry under management by the
198 share mode system
199 ********************************************************************/
200 int share_mode_forall(void (*fn)(share_mode_entry *, char *))
201 {
202         return share_ops->forall(fn);
203 }
204
205 /*******************************************************************
206 dump the state of the system
207 ********************************************************************/
208 void share_status(FILE *f)
209 {
210         share_ops->status(f);
211 }