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;
36 extern files_struct Files[];
39 static struct share_ops *share_ops;
41 #if 0 /* JRATEST - blocking lock code - under development. */
43 /****************************************************************************
44 This is the structure to queue to implement blocking locks.
45 notify. It consists of the requesting SMB and the expiry time.
46 *****************************************************************************/
54 } blocking_lock_record;
56 static ubi_slList blocking_lock_queue = { NULL, (ubi_slNodePtr)&blocking_lock_queue, 0};
58 /****************************************************************************
59 Function to push a blocking lockingX request onto the lock queue.
60 ****************************************************************************/
62 BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout, int lock_num)
64 blocking_lock_record *blr;
65 int fnum = GETFNUM(inbuf,smb_vwv2);
68 * Now queue an entry on the blocking lock queue. We setup
69 * the expiration time here.
72 if((blr = (blocking_lock_record *)malloc(sizeof(blocking_lock_record))) == NULL) {
73 DEBUG(0,("push_blocking_lock_request: Malloc fail !\n" ));
77 if((blr->inbuf = (char *)malloc(length)) == NULL) {
78 DEBUG(0,("push_blocking_lock_request: Malloc fail (2)!\n" ));
83 memcpy(blr->inbuf, inbuf, length);
85 blr->lock_num = lock_num;
86 blr->expire_time = (lock_timeout == -1) ? (time_t)-1 : time(NULL) + (time_t)lock_timeout;
88 ubi_slAddTail(&blocking_lock_queue, blr);
90 DEBUG(3,("push_blocking_lock_request: lock request blocked with expiry time %d \
91 for fnum = %d, name = %s\n", blr->expire_time, fnum, Files[fnum].name ));
96 /****************************************************************************
97 Return a blocking lock success SMB.
98 *****************************************************************************/
100 static void blocking_lock_reply_success(blocking_lock_record *blr)
102 extern int chain_size;
103 extern int chain_fnum;
104 extern char *OutBuffer;
105 char *outbuf = OutBuffer;
106 int bufsize = BUFFER_SIZE;
107 char *inbuf = blr->inbuf;
108 int fnum = GETFNUM(inbuf,smb_vwv2);
111 construct_reply_common(inbuf, outbuf);
112 set_message(outbuf,2,0,True);
115 * As this message is a lockingX call we must handle
116 * any following chained message correctly.
117 * This is normally handled in construct_reply(),
118 * but as that calls switch_message, we can't use
119 * that here and must set up the chain info manually.
125 outsize = chain_reply(inbuf,outbuf,blr->length,bufsize);
127 outsize += chain_size;
130 smb_setlen(outbuf,outsize - 4);
132 send_smb(Client,outbuf);
135 /****************************************************************************
136 Return a lock fail error. Undo all the locks we have obtained first.
137 *****************************************************************************/
139 static void blocking_lock_reply_error(blocking_lock_record *blr, int eclass, int32 ecode)
141 extern char *OutBuffer;
142 char *outbuf = OutBuffer;
143 int bufsize = BUFFER_SIZE;
144 char *inbuf = blr->inbuf;
145 int fnum = GETFNUM(inbuf,smb_vwv2);
146 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
147 uint16 num_locks = SVAL(inbuf,smb_vwv7);
148 uint32 count, offset;
149 int lock_num = blr->lock_num;
153 data = smb_buf(inbuf) + 10*num_ulocks;
156 * Data now points at the beginning of the list
157 * of smb_lkrng structs.
160 for(i = blr->lock_num; i >= 0; i--) {
161 count = IVAL(data,SMB_LKLEN_OFFSET(i));
162 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
163 do_unlock(fnum,conn,count,offset,&dummy1,&dummy2);
166 construct_reply_common(inbuf, outbuf);
168 send_smb(Client,outbuf);
171 /****************************************************************************
172 Attempt to finish off getting all pending blocking locks.
173 Returns True if we want to be removed from the list.
174 *****************************************************************************/
176 static BOOL blocking_lock_record_process(blocking_lock_record *blr)
178 char *inbuf = blr->inbuf;
179 unsigned char locktype = CVAL(inbuf,smb_vwv3);
180 int fnum = GETFNUM(inbuf,smb_vwv2);
181 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
182 uint16 num_locks = SVAL(inbuf,smb_vwv7);
183 uint32 count, offset;
184 int lock_num = blr->lock_num;
189 data = smb_buf(inbuf) + 10*num_ulocks;
192 * Data now points at the beginning of the list
193 * of smb_lkrng structs.
196 for(; blr->lock_num < num_locks; blr->lock_num++) {
197 count = IVAL(data,SMB_LKLEN_OFFSET(blr->lock_num));
198 offset = IVAL(data,SMB_LKOFF_OFFSET(blr->lock_num));
199 if(!do_lock(fnum,conn,count,offset, ((locktype & 1) ? F_RDLCK : F_WRLCK),
204 if(blr->lock_num == num_locks) {
207 * Success - we got all the locks.
210 DEBUG(3,("blocking_lock_record_process fnum=%d type=%d num_locks=%d\n",
211 fnum, (unsigned int)locktype, num_locks) );
213 blocking_lock_reply_success(blr);
216 } else if((errno != EACCES) && (errno != EAGAIN)) {
219 * We have other than a "can't get lock" POSIX
220 * error. Free any locks we had and return an error.
221 * Return True so we get dequeued.
224 blocking_lock_reply_error(blr, eclass, ecode);
229 * Still can't get all the locks - keep waiting.
232 DEBUG(10,("blocking_lock_record_process: only got %d locks of %d needed for fnum = %d. \
233 Waiting..\n", blr->lock_num, num_locks, fnum ));
238 /****************************************************************************
239 Process the blocking lock queue. Note that this is only called as root.
240 *****************************************************************************/
242 void process_blocking_lock_queue(time_t t)
244 blocking_lock_record *blr = (blocking_lock_record *)ubi_slFirst( &blocking_lock_queue );
245 blocking_lock_record *prev = NULL;
251 * Go through the queue and see if we can get any of the locks.
255 int fnum = GETFNUM(blr->inbuf,smb_vwv2);
256 files_struct *fsp = &Files[fnum];
257 uint16 vuid = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID :
258 SVAL(blr->inbuf,smb_uid);
260 DEBUG(5,("process_blocking_lock_queue: examining pending lock fnum = %d for file %s\n",
263 if((blr->expire_time != -1) && (blr->expire_time > t)) {
265 * Lock expired - throw away all previously
266 * obtained locks and return lock error.
268 DEBUG(5,("process_blocking_lock_queue: pending lock fnum = %d for file %s timed out.\n",
271 blocking_lock_reply_error(blr,ERRSRV,ERRaccess);
272 free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev));
273 blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue));
277 if(!become_user(conn,vuid)) {
278 DEBUG(0,("process_blocking_lock_queue: Unable to become user vuid=%d.\n",
281 * Remove the entry and return an error to the client.
283 blocking_lock_reply_error(blr,ERRSRV,ERRaccess);
284 free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev));
285 blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue));
289 if(!become_service(conn,True)) {
290 DEBUG(0,("process_blocking_lock_queue: Unable to become service Error was %s.\n", strerror(errno) ));
292 * Remove the entry and return an error to the client.
294 blocking_lock_reply_error(blr,ERRSRV,ERRaccess);
295 free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev));
296 blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue));
302 * Go through the remaining locks and try and obtain them.
303 * The call returns True if all locks were obtained successfully
304 * and False if we still need to wait.
307 if(blocking_lock_record_process(blr)) {
308 free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev));
309 blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue));
317 * Move to the next in the list.
320 blr = (blocking_lock_record *)ubi_slNext(blr);
325 /****************************************************************************
326 Utility function to map a lock type correctly depending on the real open
328 ****************************************************************************/
330 static int map_lock_type( files_struct *fsp, int lock_type)
332 if((lock_type == F_WRLCK) && (fsp->fd_ptr->real_open_flags == O_RDONLY)) {
334 * Many UNIX's cannot get a write lock on a file opened read-only.
335 * Win32 locking semantics allow this.
336 * Do the best we can and attempt a read-only lock.
338 DEBUG(10,("map_lock_type: Downgrading write lock to read due to read-only file.\n"));
340 } else if( (lock_type == F_RDLCK) && (fsp->fd_ptr->real_open_flags == O_WRONLY)) {
342 * Ditto for read locks on write only files.
344 DEBUG(10,("map_lock_type: Changing read lock to write due to write-only file.\n"));
349 * This return should be the most normal, as we attempt
350 * to always open files read/write.
356 /****************************************************************************
357 Utility function called to see if a file region is locked.
358 ****************************************************************************/
359 BOOL is_locked(int fnum,connection_struct *conn,
360 uint32 count,uint32 offset, int lock_type)
362 int snum = SNUM(conn);
363 files_struct *fsp = &Files[fnum];
368 if (!lp_locking(snum) || !lp_strict_locking(snum))
372 * Note that most UNIX's can *test* for a write lock on
373 * a read-only fd, just not *set* a write lock on a read-only
374 * fd. So we don't need to use map_lock_type here.
377 return(fcntl_lock(fsp->fd_ptr->fd,F_GETLK,offset,count,lock_type));
381 /****************************************************************************
382 Utility function called by locking requests.
383 ****************************************************************************/
384 BOOL do_lock(int fnum,connection_struct *conn,
385 uint32 count,uint32 offset,int lock_type,
386 int *eclass,uint32 *ecode)
389 files_struct *fsp = &Files[fnum];
391 if (!lp_locking(SNUM(conn)))
396 *ecode = ERRnoaccess;
400 if (OPEN_FNUM(fnum) && fsp->can_lock && (fsp->conn == conn))
401 ok = fcntl_lock(fsp->fd_ptr->fd,F_SETLK,offset,count,
402 map_lock_type(fsp,lock_type));
409 return True; /* Got lock */
413 /****************************************************************************
414 Utility function called by unlocking requests.
415 ****************************************************************************/
416 BOOL do_unlock(int fnum,connection_struct *conn,
417 uint32 count,uint32 offset,int *eclass,uint32 *ecode)
420 files_struct *fsp = &Files[fnum];
422 if (!lp_locking(SNUM(conn)))
425 if (OPEN_FNUM(fnum) && fsp->can_lock && (fsp->conn == conn))
426 ok = fcntl_lock(fsp->fd_ptr->fd,F_SETLK,offset,count,F_UNLCK);
433 return True; /* Did unlock */
438 /****************************************************************************
439 Initialise the locking functions.
440 ****************************************************************************/
442 BOOL locking_init(int read_only)
444 if (share_ops) return True;
446 #ifdef FAST_SHARE_MODES
447 share_ops = locking_shm_init(read_only);
449 share_ops = locking_slow_init(read_only);
453 DEBUG(0,("ERROR: Failed to initialise share modes!\n"));
460 /*******************************************************************
461 Deinitialize the share_mode management.
462 ******************************************************************/
464 BOOL locking_end(void)
467 return share_ops->stop_mgmt();
472 /*******************************************************************
473 Lock a hash bucket entry.
474 ******************************************************************/
475 BOOL lock_share_entry(connection_struct *conn,
476 uint32 dev, uint32 inode, int *ptok)
478 return share_ops->lock_entry(conn, dev, inode, ptok);
481 /*******************************************************************
482 Unlock a hash bucket entry.
483 ******************************************************************/
484 BOOL unlock_share_entry(connection_struct *conn,
485 uint32 dev, uint32 inode, int token)
487 return share_ops->unlock_entry(conn, dev, inode, token);
490 /*******************************************************************
491 Get all share mode entries for a dev/inode pair.
492 ********************************************************************/
493 int get_share_modes(connection_struct *conn,
494 int token, uint32 dev, uint32 inode,
495 share_mode_entry **shares)
497 return share_ops->get_entries(conn, token, dev, inode, shares);
500 /*******************************************************************
501 Del the share mode of a file.
502 ********************************************************************/
504 void del_share_mode(int token, int fnum)
506 share_ops->del_entry(token, fnum);
509 /*******************************************************************
510 Set the share mode of a file. Return False on fail, True on success.
511 ********************************************************************/
513 BOOL set_share_mode(int token, int fnum, uint16 port, uint16 op_type)
515 return share_ops->set_entry(token, fnum, port, op_type);
518 /*******************************************************************
519 Remove an oplock port and mode entry from a share mode.
520 ********************************************************************/
521 BOOL remove_share_oplock(int fnum, int token)
523 return share_ops->remove_oplock(fnum, token);
526 /*******************************************************************
527 Call the specified function on each entry under management by the
529 ********************************************************************/
531 int share_mode_forall(void (*fn)(share_mode_entry *, char *))
533 return share_ops->forall(fn);
536 /*******************************************************************
537 Dump the state of the system.
538 ********************************************************************/
540 void share_status(FILE *f)
542 share_ops->status(f);