this is the bug change to using connection_struct* instead of cnum.
[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 extern files_struct Files[];
37 extern int Client;
38
39 static struct share_ops *share_ops;
40
41 #if 0 /* JRATEST - blocking lock code - under development. */
42
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 *****************************************************************************/
47
48 typedef struct {
49   ubi_slNode msg_next;
50   time_t expire_time;
51   int lock_num;
52   char *inbuf;
53   int length;
54 } blocking_lock_record;
55
56 static ubi_slList blocking_lock_queue = { NULL, (ubi_slNodePtr)&blocking_lock_queue, 0};
57
58 /****************************************************************************
59  Function to push a blocking lockingX request onto the lock queue.
60 ****************************************************************************/
61
62 BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout, int lock_num)
63 {
64   blocking_lock_record *blr;
65   int fnum = GETFNUM(inbuf,smb_vwv2);
66
67   /*
68    * Now queue an entry on the blocking lock queue. We setup
69    * the expiration time here.
70    */
71
72   if((blr = (blocking_lock_record *)malloc(sizeof(blocking_lock_record))) == NULL) {
73     DEBUG(0,("push_blocking_lock_request: Malloc fail !\n" ));
74     return False;
75   }
76
77   if((blr->inbuf = (char *)malloc(length)) == NULL) {
78     DEBUG(0,("push_blocking_lock_request: Malloc fail (2)!\n" ));
79     free((char *)blr);
80     return False;
81   }
82
83   memcpy(blr->inbuf, inbuf, length);
84   blr->length = length;
85   blr->lock_num = lock_num;
86   blr->expire_time = (lock_timeout == -1) ? (time_t)-1 : time(NULL) + (time_t)lock_timeout;
87
88   ubi_slAddTail(&blocking_lock_queue, blr);
89
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 ));
92
93   return True;
94 }
95
96 /****************************************************************************
97  Return a blocking lock success SMB.
98 *****************************************************************************/
99
100 static void blocking_lock_reply_success(blocking_lock_record *blr)
101 {
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);
109   int outsize = 0;
110
111   construct_reply_common(inbuf, outbuf);
112   set_message(outbuf,2,0,True);
113
114   /*
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.
120    */
121
122   chain_fnum = fnum;
123   chain_size = 0;
124
125   outsize = chain_reply(inbuf,outbuf,blr->length,bufsize);
126
127   outsize += chain_size;
128
129   if(outsize > 4)
130     smb_setlen(outbuf,outsize - 4);
131
132   send_smb(Client,outbuf);
133 }
134
135 /****************************************************************************
136  Return a lock fail error. Undo all the locks we have obtained first.
137 *****************************************************************************/
138
139 static void blocking_lock_reply_error(blocking_lock_record *blr, int eclass, int32 ecode)
140 {
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;
150   char *data;
151   int i;
152
153   data = smb_buf(inbuf) + 10*num_ulocks;
154
155   /* 
156    * Data now points at the beginning of the list
157    * of smb_lkrng structs.
158    */
159
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);
164   }
165
166   construct_reply_common(inbuf, outbuf);
167   ERROR(eclass,ecode);
168   send_smb(Client,outbuf);
169 }
170
171 /****************************************************************************
172  Attempt to finish off getting all pending blocking locks.
173  Returns True if we want to be removed from the list.
174 *****************************************************************************/
175
176 static BOOL blocking_lock_record_process(blocking_lock_record *blr)
177 {
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;
185   char *data;
186   int eclass=0;
187   uint32 ecode=0;
188
189   data = smb_buf(inbuf) + 10*num_ulocks;
190
191   /* 
192    * Data now points at the beginning of the list
193    * of smb_lkrng structs.
194    */
195
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),
200                 &eclass, &ecode))
201       break;
202   }
203
204   if(blr->lock_num == num_locks) {
205
206     /*
207      * Success - we got all the locks.
208      */
209
210     DEBUG(3,("blocking_lock_record_process fnum=%d type=%d num_locks=%d\n",
211           fnum, (unsigned int)locktype, num_locks) );
212
213     blocking_lock_reply_success(blr);
214     return True;
215
216   } else if((errno != EACCES) && (errno != EAGAIN)) {
217
218     /*
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.
222      */
223
224     blocking_lock_reply_error(blr, eclass, ecode);
225     return True;
226   }
227
228   /*
229    * Still can't get all the locks - keep waiting.
230    */
231
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 ));
234
235   return False;
236 }
237
238 /****************************************************************************
239  Process the blocking lock queue. Note that this is only called as root.
240 *****************************************************************************/
241
242 void process_blocking_lock_queue(time_t t)
243 {
244   blocking_lock_record *blr = (blocking_lock_record *)ubi_slFirst( &blocking_lock_queue );
245   blocking_lock_record *prev = NULL;
246
247   if(blr == NULL)
248     return;
249
250   /*
251    * Go through the queue and see if we can get any of the locks.
252    */
253
254   while(blr != NULL) {
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);
259
260     DEBUG(5,("process_blocking_lock_queue: examining pending lock fnum = %d for file %s\n",
261           fnum, fsp->name ));
262
263     if((blr->expire_time != -1) && (blr->expire_time > t)) {
264       /*
265        * Lock expired - throw away all previously
266        * obtained locks and return lock error.
267        */
268       DEBUG(5,("process_blocking_lock_queue: pending lock fnum = %d for file %s timed out.\n",
269           fnum, fsp->name ));
270
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));
274       continue;
275     }
276
277     if(!become_user(conn,vuid)) {
278       DEBUG(0,("process_blocking_lock_queue: Unable to become user vuid=%d.\n",
279             vuid ));
280       /*
281        * Remove the entry and return an error to the client.
282        */
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));
286       continue;
287     }
288
289     if(!become_service(conn,True)) {
290       DEBUG(0,("process_blocking_lock_queue: Unable to become service Error was %s.\n", strerror(errno) ));
291       /*
292        * Remove the entry and return an error to the client.
293        */
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));
297       unbecome_user();
298       continue;
299     }
300
301     /*
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.
305      */
306
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));
310       unbecome_user();
311       continue;
312     }
313
314     unbecome_user();
315
316     /*
317      * Move to the next in the list.
318      */
319     prev = blr;
320     blr = (blocking_lock_record *)ubi_slNext(blr);
321   }
322 }
323 #endif /* JRATEST */
324
325 /****************************************************************************
326  Utility function to map a lock type correctly depending on the real open
327  mode of a file.
328 ****************************************************************************/
329
330 static int map_lock_type( files_struct *fsp, int lock_type)
331 {
332   if((lock_type == F_WRLCK) && (fsp->fd_ptr->real_open_flags == O_RDONLY)) {
333     /*
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.
337      */
338     DEBUG(10,("map_lock_type: Downgrading write lock to read due to read-only file.\n"));
339     return F_RDLCK;
340   } else if( (lock_type == F_RDLCK) && (fsp->fd_ptr->real_open_flags == O_WRONLY)) {
341     /*
342      * Ditto for read locks on write only files.
343      */
344     DEBUG(10,("map_lock_type: Changing read lock to write due to write-only file.\n"));
345     return F_WRLCK;
346   }
347
348   /*
349    * This return should be the most normal, as we attempt
350    * to always open files read/write.
351    */
352
353   return lock_type;
354 }
355
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)
361 {
362         int snum = SNUM(conn);
363         files_struct *fsp = &Files[fnum];
364
365         if (count == 0)
366                 return(False);
367
368         if (!lp_locking(snum) || !lp_strict_locking(snum))
369                 return(False);
370
371         /*
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.
375          */
376         
377         return(fcntl_lock(fsp->fd_ptr->fd,F_GETLK,offset,count,lock_type));
378 }
379
380
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)
387 {
388   BOOL ok = False;
389   files_struct *fsp = &Files[fnum];
390
391   if (!lp_locking(SNUM(conn)))
392     return(True);
393
394   if (count == 0) {
395     *eclass = ERRDOS;
396     *ecode = ERRnoaccess;
397     return False;
398   }
399
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));
403
404   if (!ok) {
405     *eclass = ERRDOS;
406     *ecode = ERRlock;
407     return False;
408   }
409   return True; /* Got lock */
410 }
411
412
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)
418 {
419   BOOL ok = False;
420   files_struct *fsp = &Files[fnum];
421
422   if (!lp_locking(SNUM(conn)))
423     return(True);
424
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);
427    
428   if (!ok) {
429     *eclass = ERRDOS;
430     *ecode = ERRlock;
431     return False;
432   }
433   return True; /* Did unlock */
434 }
435
436
437
438 /****************************************************************************
439  Initialise the locking functions.
440 ****************************************************************************/
441
442 BOOL locking_init(int read_only)
443 {
444         if (share_ops) return True;
445
446 #ifdef FAST_SHARE_MODES
447         share_ops = locking_shm_init(read_only);
448 #else
449         share_ops = locking_slow_init(read_only);
450 #endif
451
452         if (!share_ops) {
453                 DEBUG(0,("ERROR: Failed to initialise share modes!\n"));
454                 return False;
455         }
456         
457         return True;
458 }
459
460 /*******************************************************************
461  Deinitialize the share_mode management.
462 ******************************************************************/
463
464 BOOL locking_end(void)
465 {
466         if (share_ops)
467                 return share_ops->stop_mgmt();
468         return True;
469 }
470
471
472 /*******************************************************************
473  Lock a hash bucket entry.
474 ******************************************************************/
475 BOOL lock_share_entry(connection_struct *conn,
476                       uint32 dev, uint32 inode, int *ptok)
477 {
478         return share_ops->lock_entry(conn, dev, inode, ptok);
479 }
480
481 /*******************************************************************
482  Unlock a hash bucket entry.
483 ******************************************************************/
484 BOOL unlock_share_entry(connection_struct *conn,
485                         uint32 dev, uint32 inode, int token)
486 {
487         return share_ops->unlock_entry(conn, dev, inode, token);
488 }
489
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)
496 {
497         return share_ops->get_entries(conn, token, dev, inode, shares);
498 }
499
500 /*******************************************************************
501  Del the share mode of a file.
502 ********************************************************************/
503
504 void del_share_mode(int token, int fnum)
505 {
506         share_ops->del_entry(token, fnum);
507 }
508
509 /*******************************************************************
510  Set the share mode of a file. Return False on fail, True on success.
511 ********************************************************************/
512
513 BOOL set_share_mode(int token, int fnum, uint16 port, uint16 op_type)
514 {
515         return share_ops->set_entry(token, fnum, port, op_type);
516 }
517
518 /*******************************************************************
519  Remove an oplock port and mode entry from a share mode.
520 ********************************************************************/
521 BOOL remove_share_oplock(int fnum, int token)
522 {
523         return share_ops->remove_oplock(fnum, token);
524 }
525
526 /*******************************************************************
527  Call the specified function on each entry under management by the
528  share mode system.
529 ********************************************************************/
530
531 int share_mode_forall(void (*fn)(share_mode_entry *, char *))
532 {
533         return share_ops->forall(fn);
534 }
535
536 /*******************************************************************
537  Dump the state of the system.
538 ********************************************************************/
539
540 void share_status(FILE *f)
541 {
542         share_ops->status(f);
543 }