2 Unix SMB/Netbios implementation.
5 Copyright (C) Andrew Tridgell 1992-1997
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 connection_struct Connections[];
37 extern files_struct Files[];
39 /****************************************************************************
40 utility function called to see if a file region is locked
41 ****************************************************************************/
42 BOOL is_locked(int fnum,int cnum,uint32 count,uint32 offset)
44 int snum = SNUM(cnum);
49 if (!lp_locking(snum) || !lp_strict_locking(snum))
52 return(fcntl_lock(Files[fnum].fd_ptr->fd,F_GETLK,offset,count,
53 (Files[fnum].can_write?F_WRLCK:F_RDLCK)));
57 /****************************************************************************
58 utility function called by locking requests
59 ****************************************************************************/
60 BOOL do_lock(int fnum,int cnum,uint32 count,uint32 offset,int *eclass,uint32 *ecode)
64 if (!lp_locking(SNUM(cnum)))
73 if (Files[fnum].can_lock && OPEN_FNUM(fnum) && (Files[fnum].cnum == cnum))
74 ok = fcntl_lock(Files[fnum].fd_ptr->fd,F_SETLK,offset,count,
75 (Files[fnum].can_write?F_WRLCK:F_RDLCK));
82 return True; /* Got lock */
86 /****************************************************************************
87 utility function called by unlocking requests
88 ****************************************************************************/
89 BOOL do_unlock(int fnum,int cnum,uint32 count,uint32 offset,int *eclass,uint32 *ecode)
93 if (!lp_locking(SNUM(cnum)))
96 if (Files[fnum].can_lock && OPEN_FNUM(fnum) && (Files[fnum].cnum == cnum))
97 ok = fcntl_lock(Files[fnum].fd_ptr->fd,F_SETLK,offset,count,F_UNLCK);
104 return True; /* Did unlock */
107 #ifdef FAST_SHARE_MODES
108 /*******************************************************************
109 initialize the shared memory for share_mode management
110 ******************************************************************/
111 BOOL start_share_mode_mgmt(void)
113 pstring shmem_file_name;
115 pstrcpy(shmem_file_name,lp_lockdir());
116 if (!directory_exist(shmem_file_name,NULL))
117 mkdir(shmem_file_name,0755);
118 trim_string(shmem_file_name,"","/");
119 if (!*shmem_file_name) return(False);
120 strcat(shmem_file_name, "/SHARE_MEM_FILE");
121 return smb_shm_open(shmem_file_name, lp_shmem_size());
125 /*******************************************************************
126 deinitialize the shared memory for share_mode management
127 ******************************************************************/
128 BOOL stop_share_mode_mgmt(void)
130 return smb_shm_close();
133 /*******************************************************************
134 lock a hash bucket entry in shared memory for share_mode management
135 ******************************************************************/
136 BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok)
138 return smb_shm_lock_hash_entry(HASH_ENTRY(dev, inode));
141 /*******************************************************************
142 unlock a hash bucket entry in shared memory for share_mode management
143 ******************************************************************/
144 BOOL unlock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token token)
146 return smb_shm_unlock_hash_entry(HASH_ENTRY(dev, inode));
149 /*******************************************************************
150 get all share mode entries in shared memory for a dev/inode pair.
151 ********************************************************************/
152 int get_share_modes(int cnum, share_lock_token token, uint32 dev, uint32 inode,
153 min_share_mode_entry **old_shares)
155 smb_shm_offset_t *mode_array;
156 unsigned int hash_entry = HASH_ENTRY(dev, inode);
157 share_mode_record *file_scanner_p;
158 share_mode_record *file_prev_p;
159 share_mode_entry *entry_scanner_p;
160 share_mode_entry *entry_prev_p;
162 int num_entries_copied;
164 min_share_mode_entry *share_array = (min_share_mode_entry *)0;
168 if(hash_entry > lp_shmem_hash_size() )
171 ("PANIC ERROR : get_share_modes (FAST_SHARE_MODES): hash_entry %d too large \
173 hash_entry, lp_shmem_hash_size() ));
177 mode_array = (smb_shm_offset_t *)smb_shm_offset2addr(smb_shm_get_userdef_off());
179 if(mode_array[hash_entry] == NULL_OFFSET)
181 DEBUG(5,("get_share_modes (FAST_SHARE_MODES): hash bucket %d empty\n", hash_entry));
185 file_scanner_p = (share_mode_record *)smb_shm_offset2addr(mode_array[hash_entry]);
186 file_prev_p = file_scanner_p;
187 while(file_scanner_p)
189 if( (file_scanner_p->st_dev == dev) && (file_scanner_p->st_ino == inode) )
196 file_prev_p = file_scanner_p ;
197 file_scanner_p = (share_mode_record *)smb_shm_offset2addr(
198 file_scanner_p->next_offset);
204 DEBUG(5,("get_share_modes (FAST_SHARE_MODES): no entry for \
205 file dev = %d, ino = %d in hash_bucket %d\n", dev, inode, hash_entry));
209 if(file_scanner_p->locking_version != LOCKING_VERSION)
211 DEBUG(0,("ERROR:get_share_modes (FAST_SHARE_MODES): Deleting old share mode \
212 record due to old locking version %d for file dev = %d, inode = %d in hash \
213 bucket %d\n", file_scanner_p->locking_version, dev, inode, hash_entry));
214 if(file_prev_p == file_scanner_p)
215 mode_array[hash_entry] = file_scanner_p->next_offset;
217 file_prev_p->next_offset = file_scanner_p->next_offset;
218 smb_shm_free(smb_shm_addr2offset(file_scanner_p));
222 /* Allocate the old_shares array */
223 num_entries = file_scanner_p->num_share_mode_entries;
226 *old_shares = share_array = (min_share_mode_entry *)
227 malloc(num_entries * sizeof(min_share_mode_entry));
230 DEBUG(0,("get_share_modes (FAST_SHARE_MODES): malloc fail !\n"));
235 num_entries_copied = 0;
237 entry_scanner_p = (share_mode_entry*)smb_shm_offset2addr(
238 file_scanner_p->share_mode_entries);
239 entry_prev_p = entry_scanner_p;
240 while(entry_scanner_p)
242 int pid = entry_scanner_p->pid;
244 if (pid && !process_exists(pid))
246 /* Delete this share mode entry */
247 share_mode_entry *delete_entry_p = entry_scanner_p;
248 int share_mode = entry_scanner_p->share_mode;
250 if(entry_prev_p == entry_scanner_p)
252 /* We are at start of list */
253 file_scanner_p->share_mode_entries = entry_scanner_p->next_share_mode_entry;
254 entry_scanner_p = (share_mode_entry*)smb_shm_offset2addr(
255 file_scanner_p->share_mode_entries);
256 entry_prev_p = entry_scanner_p;
260 entry_prev_p->next_share_mode_entry = entry_scanner_p->next_share_mode_entry;
261 entry_scanner_p = (share_mode_entry*)
262 smb_shm_offset2addr(entry_scanner_p->next_share_mode_entry);
264 /* Decrement the number of share mode entries on this share mode record */
265 file_scanner_p->num_share_mode_entries -= 1;
268 if(file_scanner_p->num_share_mode_entries < 0)
270 DEBUG(0,("PANIC ERROR:get_share_mode (FAST_SHARE_MODES): num_share_mode_entries < 0 (%d) \
271 for dev = %d, ino = %d, hashbucket %d\n", file_scanner_p->num_share_mode_entries,
272 dev, inode, hash_entry));
276 DEBUG(0,("get_share_modes (FAST_SHARE_MODES): process %d no longer exists and \
277 it left a share mode entry with mode 0x%X for file dev = %d, ino = %d in hash \
278 bucket %d (number of entries now = %d)\n",
279 pid, share_mode, dev, inode, hash_entry,
280 file_scanner_p->num_share_mode_entries));
282 smb_shm_free(smb_shm_addr2offset(delete_entry_p));
286 /* This is a valid share mode entry and the process that
287 created it still exists. Copy it into the output array.
289 share_array[num_entries_copied].pid = entry_scanner_p->pid;
290 share_array[num_entries_copied].share_mode = entry_scanner_p->share_mode;
291 share_array[num_entries_copied].op_port = entry_scanner_p->op_port;
292 share_array[num_entries_copied].op_type = entry_scanner_p->op_type;
293 memcpy(&share_array[num_entries_copied].time, &entry_scanner_p->time,
294 sizeof(struct timeval));
295 num_entries_copied++;
296 DEBUG(5,("get_share_modes (FAST_SHARE_MODES): Read share mode \
297 record mode 0x%X pid=%d\n", entry_scanner_p->share_mode, entry_scanner_p->pid));
298 entry_prev_p = entry_scanner_p;
299 entry_scanner_p = (share_mode_entry *)
300 smb_shm_offset2addr(entry_scanner_p->next_share_mode_entry);
304 /* If no valid share mode entries were found then this record shouldn't exist ! */
305 if(num_entries_copied == 0)
307 DEBUG(0,("get_share_modes (FAST_SHARE_MODES): file with dev %d, inode %d in \
308 hash bucket %d has a share mode record but no entries - deleting\n",
309 dev, inode, hash_entry));
311 free((char *)*old_shares);
314 if(file_prev_p == file_scanner_p)
315 mode_array[hash_entry] = file_scanner_p->next_offset;
317 file_prev_p->next_offset = file_scanner_p->next_offset;
318 smb_shm_free(smb_shm_addr2offset(file_scanner_p));
321 DEBUG(5,("get_share_modes (FAST_SHARE_MODES): file with dev %d, inode %d in \
322 hash bucket %d returning %d entries\n", dev, inode, hash_entry, num_entries_copied));
324 return(num_entries_copied);
327 /*******************************************************************
328 del the share mode of a file.
329 ********************************************************************/
330 void del_share_mode(share_lock_token token, int fnum)
333 smb_shm_offset_t *mode_array;
334 unsigned int hash_entry;
335 share_mode_record *file_scanner_p;
336 share_mode_record *file_prev_p;
337 share_mode_entry *entry_scanner_p;
338 share_mode_entry *entry_prev_p;
342 dev = Files[fnum].fd_ptr->dev;
343 inode = Files[fnum].fd_ptr->inode;
345 hash_entry = HASH_ENTRY(dev, inode);
347 if(hash_entry > lp_shmem_hash_size() )
350 ("PANIC ERROR:del_share_mode (FAST_SHARE_MODES): hash_entry %d too large \
352 hash_entry, lp_shmem_hash_size() ));
356 mode_array = (smb_shm_offset_t *)smb_shm_offset2addr(smb_shm_get_userdef_off());
358 if(mode_array[hash_entry] == NULL_OFFSET)
360 DEBUG(0,("PANIC ERROR:del_share_mode (FAST_SHARE_MODES): hash bucket %d empty\n",
365 file_scanner_p = (share_mode_record *)smb_shm_offset2addr(mode_array[hash_entry]);
366 file_prev_p = file_scanner_p;
368 while(file_scanner_p)
370 if( (file_scanner_p->st_dev == dev) && (file_scanner_p->st_ino == inode) )
377 file_prev_p = file_scanner_p ;
378 file_scanner_p = (share_mode_record *)
379 smb_shm_offset2addr(file_scanner_p->next_offset);
385 DEBUG(0,("ERROR:del_share_mode (FAST_SHARE_MODES): no entry found for dev %d, \
386 inode %d in hash bucket %d\n", dev, inode, hash_entry));
390 if(file_scanner_p->locking_version != LOCKING_VERSION)
392 DEBUG(0,("ERROR: del_share_modes (FAST_SHARE_MODES): Deleting old share mode \
393 record due to old locking version %d for file dev %d, inode %d hash bucket %d\n",
394 file_scanner_p->locking_version, dev, inode, hash_entry ));
395 if(file_prev_p == file_scanner_p)
396 mode_array[hash_entry] = file_scanner_p->next_offset;
398 file_prev_p->next_offset = file_scanner_p->next_offset;
399 smb_shm_free(smb_shm_addr2offset(file_scanner_p));
404 entry_scanner_p = (share_mode_entry*)smb_shm_offset2addr(
405 file_scanner_p->share_mode_entries);
406 entry_prev_p = entry_scanner_p;
407 while(entry_scanner_p)
409 if( (pid == entry_scanner_p->pid) &&
410 (memcmp(&entry_scanner_p->time,
411 &Files[fnum].open_time,sizeof(struct timeval)) == 0) )
418 entry_prev_p = entry_scanner_p;
419 entry_scanner_p = (share_mode_entry *)
420 smb_shm_offset2addr(entry_scanner_p->next_share_mode_entry);
426 /* Decrement the number of entries in the record. */
427 file_scanner_p->num_share_mode_entries -= 1;
429 DEBUG(2,("del_share_modes (FAST_SHARE_MODES): \
430 Deleting share mode entry dev = %d, inode = %d in hash bucket %d (num entries now = %d)\n",
431 dev, inode, hash_entry, file_scanner_p->num_share_mode_entries));
432 if(entry_prev_p == entry_scanner_p)
433 /* We are at start of list */
434 file_scanner_p->share_mode_entries = entry_scanner_p->next_share_mode_entry;
436 entry_prev_p->next_share_mode_entry = entry_scanner_p->next_share_mode_entry;
437 smb_shm_free(smb_shm_addr2offset(entry_scanner_p));
440 if(file_scanner_p->num_share_mode_entries < 0)
442 DEBUG(0,("PANIC ERROR:del_share_mode (FAST_SHARE_MODES): num_share_mode_entries < 0 (%d) \
443 for dev = %d, ino = %d, hashbucket %d\n", file_scanner_p->num_share_mode_entries,
444 dev, inode, hash_entry));
448 /* If we deleted the last share mode entry then remove the share mode record. */
449 if(file_scanner_p->num_share_mode_entries == 0)
451 DEBUG(2,("del_share_modes (FAST_SHARE_MODES): num entries = 0, deleting share_mode \
452 record dev = %d, inode = %d in hash bucket %d\n", dev, inode, hash_entry));
453 if(file_prev_p == file_scanner_p)
454 mode_array[hash_entry] = file_scanner_p->next_offset;
456 file_prev_p->next_offset = file_scanner_p->next_offset;
457 smb_shm_free(smb_shm_addr2offset(file_scanner_p));
462 DEBUG(0,("ERROR: del_share_modes (FAST_SHARE_MODES): No share mode record found \
463 dev = %d, inode = %d in hash bucket %d\n", dev, inode, hash_entry));
467 /*******************************************************************
468 set the share mode of a file. Return False on fail, True on success.
469 ********************************************************************/
470 BOOL set_share_mode(share_lock_token token, int fnum, uint16 port, uint16 op_type)
472 files_struct *fs_p = &Files[fnum];
474 smb_shm_offset_t *mode_array;
475 unsigned int hash_entry;
476 share_mode_record *file_scanner_p;
477 share_mode_record *file_prev_p;
478 share_mode_entry *new_entry_p;
479 smb_shm_offset_t new_entry_offset;
482 dev = fs_p->fd_ptr->dev;
483 inode = fs_p->fd_ptr->inode;
485 hash_entry = HASH_ENTRY(dev, inode);
486 if(hash_entry > lp_shmem_hash_size() )
489 ("PANIC ERROR:set_share_mode (FAST_SHARE_MODES): hash_entry %d too large \
491 hash_entry, lp_shmem_hash_size() ));
495 mode_array = (smb_shm_offset_t *)smb_shm_offset2addr(smb_shm_get_userdef_off());
497 file_scanner_p = (share_mode_record *)smb_shm_offset2addr(mode_array[hash_entry]);
498 file_prev_p = file_scanner_p;
500 while(file_scanner_p)
502 if( (file_scanner_p->st_dev == dev) && (file_scanner_p->st_ino == inode) )
509 file_prev_p = file_scanner_p ;
510 file_scanner_p = (share_mode_record *)
511 smb_shm_offset2addr(file_scanner_p->next_offset);
517 /* We must create a share_mode_record */
518 share_mode_record *new_mode_p = NULL;
519 smb_shm_offset_t new_offset = smb_shm_alloc( sizeof(share_mode_record) +
520 strlen(fs_p->name) + 1);
521 if(new_offset == NULL_OFFSET)
523 DEBUG(0,("ERROR:set_share_mode (FAST_SHARE_MODES): smb_shm_alloc fail !\n"));
526 new_mode_p = smb_shm_offset2addr(new_offset);
527 new_mode_p->locking_version = LOCKING_VERSION;
528 new_mode_p->st_dev = dev;
529 new_mode_p->st_ino = inode;
530 new_mode_p->num_share_mode_entries = 0;
531 new_mode_p->share_mode_entries = NULL_OFFSET;
532 strcpy(new_mode_p->file_name, fs_p->name);
534 /* Chain onto the start of the hash chain (in the hope we will be used first). */
535 new_mode_p->next_offset = mode_array[hash_entry];
536 mode_array[hash_entry] = new_offset;
538 file_scanner_p = new_mode_p;
540 DEBUG(3,("set_share_mode (FAST_SHARE_MODES): Created share record for %s (dev %d \
541 inode %d in hash bucket %d\n", fs_p->name, dev, inode, hash_entry));
544 /* Now create the share mode entry */
545 new_entry_offset = smb_shm_alloc( sizeof(share_mode_entry));
546 if(new_entry_offset == NULL_OFFSET)
548 smb_shm_offset_t delete_offset = mode_array[hash_entry];
549 DEBUG(0,("ERROR:set_share_mode (FAST_SHARE_MODES): smb_shm_alloc fail 1!\n"));
550 /* Unlink the damaged record */
551 mode_array[hash_entry] = file_scanner_p->next_offset;
553 smb_shm_free( delete_offset );
557 new_entry_p = smb_shm_offset2addr(new_entry_offset);
559 new_entry_p->pid = getpid();
560 new_entry_p->share_mode = fs_p->share_mode;
561 new_entry_p->op_port = port;
562 new_entry_p->op_type = op_type;
563 memcpy( (char *)&new_entry_p->time, (char *)&fs_p->open_time, sizeof(struct timeval));
565 /* Chain onto the share_mode_record */
566 new_entry_p->next_share_mode_entry = file_scanner_p->share_mode_entries;
567 file_scanner_p->share_mode_entries = new_entry_offset;
570 if(file_scanner_p->num_share_mode_entries < 0)
572 DEBUG(0,("PANIC ERROR:set_share_mode (FAST_SHARE_MODES): num_share_mode_entries < 0 (%d) \
573 for dev = %d, ino = %d, hashbucket %d\n", file_scanner_p->num_share_mode_entries,
574 dev, inode, hash_entry));
578 /* Increment the share_mode_entries counter */
579 file_scanner_p->num_share_mode_entries += 1;
581 DEBUG(3,("set_share_mode (FAST_SHARE_MODES): Created share entry for %s with mode \
582 0x%X pid=%d (num_entries now = %d)\n",fs_p->name, fs_p->share_mode, new_entry_p->pid,
583 file_scanner_p->num_share_mode_entries));
588 /*******************************************************************
589 Remove an oplock port and mode entry from a share mode.
590 ********************************************************************/
591 BOOL remove_share_oplock(int fnum, share_lock_token token)
594 smb_shm_offset_t *mode_array;
595 unsigned int hash_entry;
596 share_mode_record *file_scanner_p;
597 share_mode_record *file_prev_p;
598 share_mode_entry *entry_scanner_p;
599 share_mode_entry *entry_prev_p;
603 dev = Files[fnum].fd_ptr->dev;
604 inode = Files[fnum].fd_ptr->inode;
606 hash_entry = HASH_ENTRY(dev, inode);
608 if(hash_entry > lp_shmem_hash_size() )
611 ("PANIC ERROR:remove_share_oplock (FAST_SHARE_MODES): hash_entry %d too large \
613 hash_entry, lp_shmem_hash_size() ));
617 mode_array = (smb_shm_offset_t *)smb_shm_offset2addr(smb_shm_get_userdef_off());
619 if(mode_array[hash_entry] == NULL_OFFSET)
621 DEBUG(0,("PANIC ERROR:remove_share_oplock (FAST_SHARE_MODES): hash bucket %d empty\n",
626 file_scanner_p = (share_mode_record *)smb_shm_offset2addr(mode_array[hash_entry]);
627 file_prev_p = file_scanner_p;
629 while(file_scanner_p)
631 if( (file_scanner_p->st_dev == dev) && (file_scanner_p->st_ino == inode) )
638 file_prev_p = file_scanner_p ;
639 file_scanner_p = (share_mode_record *)
640 smb_shm_offset2addr(file_scanner_p->next_offset);
646 DEBUG(0,("ERROR:remove_share_oplock (FAST_SHARE_MODES): no entry found for dev %d, \
647 inode %d in hash bucket %d\n", dev, inode, hash_entry));
651 if(file_scanner_p->locking_version != LOCKING_VERSION)
653 DEBUG(0,("ERROR: remove_share_oplock (FAST_SHARE_MODES): Deleting old share mode \
654 record due to old locking version %d for file dev %d, inode %d hash bucket %d\n",
655 file_scanner_p->locking_version, dev, inode, hash_entry ));
656 if(file_prev_p == file_scanner_p)
657 mode_array[hash_entry] = file_scanner_p->next_offset;
659 file_prev_p->next_offset = file_scanner_p->next_offset;
660 smb_shm_free(smb_shm_addr2offset(file_scanner_p));
665 entry_scanner_p = (share_mode_entry*)smb_shm_offset2addr(
666 file_scanner_p->share_mode_entries);
667 entry_prev_p = entry_scanner_p;
668 while(entry_scanner_p)
670 if( (pid == entry_scanner_p->pid) &&
671 (entry_scanner_p->share_mode == Files[fnum].share_mode) &&
672 (memcmp(&entry_scanner_p->time,
673 &Files[fnum].open_time,sizeof(struct timeval)) == 0) )
675 /* Delete the oplock info. */
676 entry_scanner_p->op_port = 0;
677 entry_scanner_p->op_type = 0;
683 entry_prev_p = entry_scanner_p;
684 entry_scanner_p = (share_mode_entry *)
685 smb_shm_offset2addr(entry_scanner_p->next_share_mode_entry);
691 DEBUG(0,("ERROR: remove_share_oplock (FAST_SHARE_MODES): No oplock granted share \
692 mode record found dev = %d, inode = %d in hash bucket %d\n", dev, inode, hash_entry));
699 #else /* FAST_SHARE_MODES */
701 /* SHARE MODE LOCKS USING SLOW DESCRIPTION FILES */
703 /*******************************************************************
705 ******************************************************************/
706 static BOOL share_name(int cnum, uint32 dev, uint32 inode, char *name)
708 strcpy(name,lp_lockdir());
709 standard_sub(cnum,name);
710 trim_string(name,"","/");
711 if (!*name) return(False);
712 name += strlen(name);
714 sprintf(name,"/share.%u.%u",dev,inode);
718 /*******************************************************************
719 lock a share mode file.
720 ******************************************************************/
721 BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok)
727 *ptok = (share_lock_token)-1;
729 if(!share_name(cnum, dev, inode, fname))
734 BOOL gotlock = False;
736 old_umask = umask(0);
739 * There was a race condition in the original slow share mode code.
740 * A smbd could open a share mode file, and before getting
741 * the lock, another smbd could delete the last entry for
742 * the share mode file and delete the file entry from the
743 * directory. Thus this smbd would be left with a locked
744 * share mode fd attached to a file that no longer had a
745 * directory entry. Thus another smbd would think that
746 * there were no outstanding opens on the file. To fix
747 * this we now check we can do a stat() call on the filename
748 * before allowing the lock to proceed, and back out completely
749 * and try the open again if we cannot.
750 * Jeremy Allison (jallison@whistle.com).
755 struct stat dummy_stat;
757 #ifdef SECURE_SHARE_MODES
758 fd = (share_lock_token)open(fname,O_RDWR|O_CREAT,0600);
759 #else /* SECURE_SHARE_MODES */
760 fd = (share_lock_token)open(fname,O_RDWR|O_CREAT,0666);
761 #endif /* SECURE_SHARE_MODES */
765 DEBUG(0,("ERROR lock_share_entry: failed to open share file %s. Error was %s\n",
766 fname, strerror(errno)));
771 /* At this point we have an open fd to the share mode file.
772 Lock the first byte exclusively to signify a lock. */
773 if(fcntl_lock(fd, F_SETLKW, 0, 1, F_WRLCK) == False)
775 DEBUG(0,("ERROR lock_share_entry: fcntl_lock on file %s failed with %s\n",
776 fname, strerror(errno)));
783 * If we cannot stat the filename, the file was deleted between
784 * the open and the lock call. Back out and try again.
787 if(stat(fname, &dummy_stat)!=0)
789 DEBUG(2,("lock_share_entry: Re-issuing open on %s to fix race. Error was %s\n",
790 fname, strerror(errno)));
798 * We have to come here if any of the above calls fail
799 * as we don't want to return and leave ourselves running
804 if(!become_user(cnum,Connections[cnum].vuid))
806 DEBUG(0,("lock_share_entry: Can't become connected user!\n"));
810 /* We need to change directory back to the connection root. */
811 if (ChDir(Connections[cnum].connectpath) != 0)
813 DEBUG(0,("lock_share_entry: Can't change directory to %s (%s)\n",
814 Connections[cnum].connectpath, strerror(errno)));
820 *ptok = (share_lock_token)fd;
824 /*******************************************************************
825 unlock a share mode file.
826 ******************************************************************/
827 BOOL unlock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token token)
832 /* token is the fd of the open share mode file. */
833 /* Unlock the first byte. */
834 if(fcntl_lock(fd, F_SETLKW, 0, 1, F_UNLCK) == False)
836 DEBUG(0,("ERROR unlock_share_entry: fcntl_lock failed with %s\n",
845 /*******************************************************************
846 Force a share file to be deleted.
847 ********************************************************************/
849 static int delete_share_file( int cnum, char *fname )
852 if(unlink(fname) != 0)
854 DEBUG(0,("delete_share_file: Can't delete share file %s (%s)\n",
855 fname, strerror(errno)));
858 DEBUG(5,("delete_share_file: Deleted share file %s\n", fname));
860 if(!become_user(cnum,Connections[cnum].vuid))
862 DEBUG(0,("delete_share_file: Can't become connected user!\n"));
865 /* We need to change directory back to the connection root. */
866 if (ChDir(Connections[cnum].connectpath) != 0)
868 DEBUG(0,("delete_share_file: Can't change directory to %s (%s)\n",
869 Connections[cnum].connectpath, strerror(errno)));
875 /*******************************************************************
876 Read a share file into a buffer.
877 ********************************************************************/
879 static int read_share_file(int cnum, int fd, char *fname, char **out, BOOL *p_new_file)
888 if(fstat(fd, &sb) != 0)
890 DEBUG(0,("ERROR: read_share_file: Failed to do stat on share file %s (%s)\n",
891 fname, strerror(errno)));
901 /* Allocate space for the file */
902 if((buf = (char *)malloc(sb.st_size)) == NULL)
904 DEBUG(0,("read_share_file: malloc for file size %d fail !\n", sb.st_size));
908 if(lseek(fd, 0, SEEK_SET) != 0)
910 DEBUG(0,("ERROR: read_share_file: Failed to reset position to 0 \
911 for share file %s (%s)\n", fname, strerror(errno)));
917 if (read(fd,buf,sb.st_size) != sb.st_size)
919 DEBUG(0,("ERROR: read_share_file: Failed to read share file %s (%s)\n",
920 fname, strerror(errno)));
926 if (IVAL(buf,SMF_VERSION_OFFSET) != LOCKING_VERSION) {
927 DEBUG(0,("ERROR: read_share_file: share file %s has incorrect \
928 locking version (was %d, should be %d).\n",fname,
929 IVAL(buf,SMF_VERSION_OFFSET), LOCKING_VERSION));
932 delete_share_file(cnum, fname);
936 /* Sanity check for file contents */
938 size -= SMF_HEADER_LENGTH; /* Remove the header */
940 /* Remove the filename component. */
941 size -= SVAL(buf, SMF_FILENAME_LEN_OFFSET);
943 /* The remaining size must be a multiple of SMF_ENTRY_LENGTH - error if not. */
944 if((size % SMF_ENTRY_LENGTH) != 0)
946 DEBUG(0,("ERROR: read_share_file: share file %s is an incorrect length - \
947 deleting it.\n", fname));
950 delete_share_file(cnum, fname);
958 /*******************************************************************
959 get all share mode entries in a share file for a dev/inode pair.
960 ********************************************************************/
961 int get_share_modes(int cnum, share_lock_token token, uint32 dev, uint32 inode,
962 min_share_mode_entry **old_shares)
968 int num_entries_copied;
970 min_share_mode_entry *share_array;
977 /* Read the share file header - this is of the form:
979 4 - number of share mode entries.
980 8 - 2 byte name length
981 [n bytes] file name (zero terminated).
983 Followed by <n> share mode entries of the form :
989 16 - oplock port (if oplocks in use) - 2 bytes.
992 share_name(cnum, dev, inode, fname);
994 if(read_share_file( cnum, fd, fname, &buf, &new_file) != 0)
996 DEBUG(0,("ERROR: get_share_modes: Failed to read share file %s\n",
1001 if(new_file == True)
1004 num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET);
1006 DEBUG(5,("get_share_modes: share file %s has %d share mode entries.\n",
1007 fname, num_entries));
1012 DEBUG(0,("PANIC ERROR:get_share_mode: num_share_mode_entries < 0 (%d) \
1013 for share file %d\n", num_entries, fname));
1019 *old_shares = share_array = (min_share_mode_entry *)
1020 malloc(num_entries * sizeof(min_share_mode_entry));
1021 if(*old_shares == 0)
1023 DEBUG(0,("get_share_modes: malloc fail !\n"));
1029 /* No entries - just delete the file. */
1030 DEBUG(0,("get_share_modes: share file %s has no share mode entries - deleting.\n",
1034 delete_share_file(cnum, fname);
1038 num_entries_copied = 0;
1039 base = buf + SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET);
1041 for( i = 0; i < num_entries; i++)
1044 char *p = base + (i*SMF_ENTRY_LENGTH);
1046 pid = IVAL(p,SME_PID_OFFSET);
1048 if(!process_exists(pid))
1050 DEBUG(0,("get_share_modes: process %d no longer exists and \
1051 it left a share mode entry with mode 0x%X in share file %s\n",
1052 pid, IVAL(p,SME_SHAREMODE_OFFSET), fname));
1055 share_array[num_entries_copied].time.tv_sec = IVAL(p,SME_SEC_OFFSET);
1056 share_array[num_entries_copied].time.tv_usec = IVAL(p,SME_USEC_OFFSET);
1057 share_array[num_entries_copied].share_mode = IVAL(p,SME_SHAREMODE_OFFSET);
1058 share_array[num_entries_copied].pid = pid;
1059 share_array[num_entries_copied].op_port = SVAL(p,SME_PORT_OFFSET);
1060 share_array[num_entries_copied].op_type = SVAL(p,SME_OPLOCK_TYPE_OFFSET);
1062 num_entries_copied++;
1065 if(num_entries_copied == 0)
1067 /* Delete the whole file. */
1068 DEBUG(0,("get_share_modes: share file %s had no valid entries - deleting it !\n",
1071 free((char *)*old_shares);
1075 delete_share_file(cnum, fname);
1079 /* If we deleted some entries we need to re-write the whole number of
1080 share mode entries back into the file. */
1082 if(num_entries_copied != num_entries)
1084 if(lseek(fd, 0, SEEK_SET) != 0)
1086 DEBUG(0,("ERROR: get_share_modes: lseek failed to reset to \
1087 position 0 for share mode file %s (%s)\n", fname, strerror(errno)));
1089 free((char *)*old_shares);
1096 SIVAL(buf, SMF_NUM_ENTRIES_OFFSET, num_entries_copied);
1097 for( i = 0; i < num_entries_copied; i++)
1099 char *p = base + (i*SMF_ENTRY_LENGTH);
1101 SIVAL(p,SME_PID_OFFSET,share_array[i].pid);
1102 SIVAL(p,SME_SHAREMODE_OFFSET,share_array[i].share_mode);
1103 SIVAL(p,SME_SEC_OFFSET,share_array[i].time.tv_sec);
1104 SIVAL(p,SME_USEC_OFFSET,share_array[i].time.tv_usec);
1105 SSVAL(p,SME_PORT_OFFSET,share_array[i].op_port);
1106 SSVAL(p,SME_OPLOCK_TYPE_OFFSET,share_array[i].op_type);
1109 newsize = (base - buf) + (SMF_ENTRY_LENGTH*num_entries_copied);
1110 if(write(fd, buf, newsize) != newsize)
1112 DEBUG(0,("ERROR: get_share_modes: failed to re-write share \
1113 mode file %s (%s)\n", fname, strerror(errno)));
1115 free((char *)*old_shares);
1121 /* Now truncate the file at this point. */
1122 if(ftruncate(fd, newsize)!= 0)
1124 DEBUG(0,("ERROR: get_share_modes: failed to ftruncate share \
1125 mode file %s to size %d (%s)\n", fname, newsize, strerror(errno)));
1127 free((char *)*old_shares);
1138 DEBUG(5,("get_share_modes: Read share file %s returning %d entries\n",fname,
1139 num_entries_copied));
1141 return num_entries_copied;
1144 /*******************************************************************
1145 del a share mode from a share mode file.
1146 ********************************************************************/
1147 void del_share_mode(share_lock_token token, int fnum)
1150 int fd = (int)token;
1156 files_struct *fs_p = &Files[fnum];
1158 BOOL deleted = False;
1161 share_name(fs_p->cnum, fs_p->fd_ptr->dev,
1162 fs_p->fd_ptr->inode, fname);
1164 if(read_share_file( fs_p->cnum, fd, fname, &buf, &new_file) != 0)
1166 DEBUG(0,("ERROR: del_share_mode: Failed to read share file %s\n",
1171 if(new_file == True)
1173 DEBUG(0,("ERROR:del_share_mode: share file %s is new (size zero), deleting it.\n",
1175 delete_share_file(fs_p->cnum, fname);
1179 num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET);
1181 DEBUG(5,("del_share_mode: share file %s has %d share mode entries.\n",
1182 fname, num_entries));
1187 DEBUG(0,("PANIC ERROR:del_share_mode: num_share_mode_entries < 0 (%d) \
1188 for share file %d\n", num_entries, fname));
1192 if(num_entries == 0)
1194 /* No entries - just delete the file. */
1195 DEBUG(0,("del_share_mode: share file %s has no share mode entries - deleting.\n",
1199 delete_share_file(fs_p->cnum, fname);
1205 /* Go through the entries looking for the particular one
1206 we have set - delete it.
1209 base = buf + SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET);
1211 for(i = 0; i < num_entries; i++)
1213 char *p = base + (i*SMF_ENTRY_LENGTH);
1215 if((IVAL(p,SME_SEC_OFFSET) != fs_p->open_time.tv_sec) ||
1216 (IVAL(p,SME_USEC_OFFSET) != fs_p->open_time.tv_usec) ||
1217 (IVAL(p,SME_SHAREMODE_OFFSET) != fs_p->share_mode) ||
1218 (IVAL(p,SME_PID_OFFSET) != pid))
1221 DEBUG(5,("del_share_mode: deleting entry number %d (of %d) from the share file %s\n",
1222 i, num_entries, fname));
1224 /* Remove this entry. */
1225 if(i != num_entries - 1)
1226 memcpy(p, p + SMF_ENTRY_LENGTH, (num_entries - i - 1)*SMF_ENTRY_LENGTH);
1234 DEBUG(0,("del_share_mode: entry not found in share file %s\n", fname));
1241 SIVAL(buf,SMF_NUM_ENTRIES_OFFSET, num_entries);
1243 if(num_entries == 0)
1245 /* Deleted the last entry - remove the file. */
1246 DEBUG(5,("del_share_mode: removed last entry in share file - deleting share file %s\n",
1250 delete_share_file(fs_p->cnum,fname);
1254 /* Re-write the file - and truncate it at the correct point. */
1255 if(lseek(fd, 0, SEEK_SET) != 0)
1257 DEBUG(0,("ERROR: del_share_mode: lseek failed to reset to \
1258 position 0 for share mode file %s (%s)\n", fname, strerror(errno)));
1264 newsize = (base - buf) + (SMF_ENTRY_LENGTH*num_entries);
1265 if(write(fd, buf, newsize) != newsize)
1267 DEBUG(0,("ERROR: del_share_mode: failed to re-write share \
1268 mode file %s (%s)\n", fname, strerror(errno)));
1273 /* Now truncate the file at this point. */
1274 if(ftruncate(fd, newsize) != 0)
1276 DEBUG(0,("ERROR: del_share_mode: failed to ftruncate share \
1277 mode file %s to size %d (%s)\n", fname, newsize, strerror(errno)));
1284 /*******************************************************************
1285 set the share mode of a file
1286 ********************************************************************/
1287 BOOL set_share_mode(share_lock_token token,int fnum, uint16 port, uint16 op_type)
1289 files_struct *fs_p = &Files[fnum];
1291 int fd = (int)token;
1292 int pid = (int)getpid();
1299 share_name(fs_p->cnum, fs_p->fd_ptr->dev,
1300 fs_p->fd_ptr->inode, fname);
1302 if(fstat(fd, &sb) != 0)
1304 DEBUG(0,("ERROR: set_share_mode: Failed to do stat on share file %s\n",
1309 /* Sanity check for file contents (if it's not a new share file). */
1312 int size = sb.st_size;
1314 /* Allocate space for the file plus one extra entry */
1315 if((buf = (char *)malloc(sb.st_size + SMF_ENTRY_LENGTH)) == NULL)
1317 DEBUG(0,("set_share_mode: malloc for file size %d fail !\n",
1318 sb.st_size + SMF_ENTRY_LENGTH));
1322 if(lseek(fd, 0, SEEK_SET) != 0)
1324 DEBUG(0,("ERROR: set_share_mode: Failed to reset position \
1325 to 0 for share file %s (%s)\n", fname, strerror(errno)));
1331 if (read(fd,buf,sb.st_size) != sb.st_size)
1333 DEBUG(0,("ERROR: set_share_mode: Failed to read share file %s (%s)\n",
1334 fname, strerror(errno)));
1340 if (IVAL(buf,SMF_VERSION_OFFSET) != LOCKING_VERSION)
1342 DEBUG(0,("ERROR: set_share_mode: share file %s has incorrect \
1343 locking version (was %d, should be %d).\n",fname, IVAL(buf,SMF_VERSION_OFFSET),
1347 delete_share_file(fs_p->cnum, fname);
1351 size -= (SMF_HEADER_LENGTH + SVAL(buf, SMF_FILENAME_LEN_OFFSET)); /* Remove the header */
1353 /* The remaining size must be a multiple of SMF_ENTRY_LENGTH - error if not. */
1354 if((size % SMF_ENTRY_LENGTH) != 0)
1356 DEBUG(0,("ERROR: set_share_mode: share file %s is an incorrect length - \
1357 deleting it.\n", fname));
1360 delete_share_file(fs_p->cnum, fname);
1367 /* New file - just use a single_entry. */
1368 if((buf = (char *)malloc(SMF_HEADER_LENGTH +
1369 strlen(fs_p->name) + 1 + SMF_ENTRY_LENGTH)) == NULL)
1371 DEBUG(0,("ERROR: set_share_mode: malloc failed for single entry.\n"));
1374 SIVAL(buf,SMF_VERSION_OFFSET,LOCKING_VERSION);
1375 SIVAL(buf,SMF_NUM_ENTRIES_OFFSET,0);
1376 SSVAL(buf,SMF_FILENAME_LEN_OFFSET,strlen(fs_p->name) + 1);
1377 strcpy(buf + SMF_HEADER_LENGTH, fs_p->name);
1380 num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET);
1381 header_size = SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET);
1382 p = buf + header_size + (num_entries * SMF_ENTRY_LENGTH);
1383 SIVAL(p,SME_SEC_OFFSET,fs_p->open_time.tv_sec);
1384 SIVAL(p,SME_USEC_OFFSET,fs_p->open_time.tv_usec);
1385 SIVAL(p,SME_SHAREMODE_OFFSET,fs_p->share_mode);
1386 SIVAL(p,SME_PID_OFFSET,pid);
1387 SSVAL(p,SME_PORT_OFFSET,port);
1388 SSVAL(p,SME_OPLOCK_TYPE_OFFSET,op_type);
1392 SIVAL(buf,SMF_NUM_ENTRIES_OFFSET,num_entries);
1394 if(lseek(fd, 0, SEEK_SET) != 0)
1396 DEBUG(0,("ERROR: set_share_mode: (1) Failed to reset position to \
1397 0 for share file %s (%s)\n", fname, strerror(errno)));
1403 if (write(fd,buf,header_size + (num_entries*SMF_ENTRY_LENGTH)) !=
1404 (header_size + (num_entries*SMF_ENTRY_LENGTH)))
1406 DEBUG(2,("ERROR: set_share_mode: Failed to write share file %s - \
1407 deleting it (%s).\n",fname, strerror(errno)));
1408 delete_share_file(fs_p->cnum, fname);
1414 /* Now truncate the file at this point - just for safety. */
1415 if(ftruncate(fd, header_size + (SMF_ENTRY_LENGTH*num_entries))!= 0)
1417 DEBUG(0,("ERROR: set_share_mode: failed to ftruncate share \
1418 mode file %s to size %d (%s)\n", fname, header_size + (SMF_ENTRY_LENGTH*num_entries),
1428 DEBUG(3,("set_share_mode: Created share file %s with \
1429 mode 0x%X pid=%d\n",fname,fs_p->share_mode,pid));
1434 /*******************************************************************
1435 Remove an oplock port and mode entry from a share mode.
1436 ********************************************************************/
1437 BOOL remove_share_oplock(int fnum, share_lock_token token)
1440 int fd = (int)token;
1446 files_struct *fs_p = &Files[fnum];
1451 share_name(fs_p->cnum, fs_p->fd_ptr->dev,
1452 fs_p->fd_ptr->inode, fname);
1454 if(read_share_file( fs_p->cnum, fd, fname, &buf, &new_file) != 0)
1456 DEBUG(0,("ERROR: remove_share_oplock: Failed to read share file %s\n",
1461 if(new_file == True)
1463 DEBUG(0,("ERROR: remove_share_oplock: share file %s is new (size zero), \
1464 deleting it.\n", fname));
1465 delete_share_file(fs_p->cnum, fname);
1469 num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET);
1471 DEBUG(5,("remove_share_oplock: share file %s has %d share mode entries.\n",
1472 fname, num_entries));
1477 DEBUG(0,("PANIC ERROR:remove_share_oplock: num_share_mode_entries < 0 (%d) \
1478 for share file %d\n", num_entries, fname));
1482 if(num_entries == 0)
1484 /* No entries - just delete the file. */
1485 DEBUG(0,("remove_share_oplock: share file %s has no share mode entries - deleting.\n",
1489 delete_share_file(fs_p->cnum, fname);
1495 /* Go through the entries looking for the particular one
1496 we have set - remove the oplock settings on it.
1499 base = buf + SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET);
1501 for(i = 0; i < num_entries; i++)
1503 char *p = base + (i*SMF_ENTRY_LENGTH);
1505 if((IVAL(p,SME_SEC_OFFSET) != fs_p->open_time.tv_sec) ||
1506 (IVAL(p,SME_USEC_OFFSET) != fs_p->open_time.tv_usec) ||
1507 (IVAL(p,SME_SHAREMODE_OFFSET) != fs_p->share_mode) ||
1508 (IVAL(p,SME_PID_OFFSET) != pid))
1511 DEBUG(5,("remove_share_oplock: clearing oplock on entry number %d (of %d) \
1512 from the share file %s\n", i, num_entries, fname));
1514 SSVAL(p,SME_PORT_OFFSET,0);
1515 SSVAL(p,SME_OPLOCK_TYPE_OFFSET,0);
1522 DEBUG(0,("remove_share_oplock: entry not found in share file %s\n", fname));
1528 /* Re-write the file - and truncate it at the correct point. */
1529 if(lseek(fd, 0, SEEK_SET) != 0)
1531 DEBUG(0,("ERROR: remove_share_oplock: lseek failed to reset to \
1532 position 0 for share mode file %s (%s)\n", fname, strerror(errno)));
1538 fsize = (base - buf) + (SMF_ENTRY_LENGTH*num_entries);
1539 if(write(fd, buf, fsize) != fsize)
1541 DEBUG(0,("ERROR: remove_share_oplock: failed to re-write share \
1542 mode file %s (%s)\n", fname, strerror(errno)));
1551 #endif /* FAST_SHARE_MODES */