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.
31 extern int DEBUGLEVEL;
32 extern connection_struct Connections[];
33 extern files_struct Files[];
35 /****************************************************************************
36 utility function called to see if a file region is locked
37 ****************************************************************************/
38 BOOL is_locked(int fnum,int cnum,uint32 count,uint32 offset)
40 int snum = SNUM(cnum);
45 if (!lp_locking(snum) || !lp_strict_locking(snum))
48 return(fcntl_lock(Files[fnum].fd_ptr->fd,F_GETLK,offset,count,
49 (Files[fnum].can_write?F_WRLCK:F_RDLCK)));
53 /****************************************************************************
54 utility function called by locking requests
55 ****************************************************************************/
56 BOOL do_lock(int fnum,int cnum,uint32 count,uint32 offset,int *eclass,uint32 *ecode)
60 if (!lp_locking(SNUM(cnum)))
69 if (Files[fnum].can_lock && OPEN_FNUM(fnum) && (Files[fnum].cnum == cnum))
70 ok = fcntl_lock(Files[fnum].fd_ptr->fd,F_SETLK,offset,count,
71 (Files[fnum].can_write?F_WRLCK:F_RDLCK));
78 return True; /* Got lock */
82 /****************************************************************************
83 utility function called by unlocking requests
84 ****************************************************************************/
85 BOOL do_unlock(int fnum,int cnum,uint32 count,uint32 offset,int *eclass,uint32 *ecode)
89 if (!lp_locking(SNUM(cnum)))
92 if (Files[fnum].can_lock && OPEN_FNUM(fnum) && (Files[fnum].cnum == cnum))
93 ok = fcntl_lock(Files[fnum].fd_ptr->fd,F_SETLK,offset,count,F_UNLCK);
100 return True; /* Did unlock */
103 #ifdef FAST_SHARE_MODES
104 /*******************************************************************
105 initialize the shared memory for share_mode management
106 ******************************************************************/
107 BOOL start_share_mode_mgmt(void)
109 pstring shmem_file_name;
111 pstrcpy(shmem_file_name,lp_lockdir());
112 if (!directory_exist(shmem_file_name,NULL))
113 mkdir(shmem_file_name,0755);
114 trim_string(shmem_file_name,"","/");
115 if (!*shmem_file_name) return(False);
116 strcat(shmem_file_name, "/SHARE_MEM_FILE");
117 return smb_shm_open(shmem_file_name, lp_shmem_size());
121 /*******************************************************************
122 deinitialize the shared memory for share_mode management
123 ******************************************************************/
124 BOOL stop_share_mode_mgmt(void)
126 return smb_shm_close();
129 /*******************************************************************
130 lock a hash bucket entry in shared memory for share_mode management
131 ******************************************************************/
132 BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok)
134 return smb_shm_lock_hash_entry(HASH_ENTRY(dev, inode));
137 /*******************************************************************
138 unlock a hash bucket entry in shared memory for share_mode management
139 ******************************************************************/
140 BOOL unlock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token token)
142 return smb_shm_unlock_hash_entry(HASH_ENTRY(dev, inode));
145 /*******************************************************************
146 get all share mode entries in shared memory for a dev/inode pair.
147 ********************************************************************/
148 int get_share_modes(int cnum, share_lock_token token, uint32 dev, uint32 inode,
149 min_share_mode_entry **old_shares)
151 smb_shm_offset_t *mode_array;
152 unsigned int hash_entry = HASH_ENTRY(dev, inode);
153 share_mode_record *file_scanner_p;
154 share_mode_record *file_prev_p;
155 share_mode_entry *entry_scanner_p;
156 share_mode_entry *entry_prev_p;
158 int num_entries_copied;
160 min_share_mode_entry *share_array = (min_share_mode_entry *)0;
164 if(hash_entry > lp_shmem_hash_size() )
167 ("PANIC ERROR : get_share_modes (FAST_SHARE_MODES): hash_entry %d too large \
169 hash_entry, lp_shmem_hash_size() ));
173 mode_array = (smb_shm_offset_t *)smb_shm_offset2addr(smb_shm_get_userdef_off());
175 if(mode_array[hash_entry] == NULL_OFFSET)
177 DEBUG(5,("get_share_modes (FAST_SHARE_MODES): hash bucket %d empty\n", hash_entry));
181 file_scanner_p = (share_mode_record *)smb_shm_offset2addr(mode_array[hash_entry]);
182 file_prev_p = file_scanner_p;
183 while(file_scanner_p)
185 if( (file_scanner_p->st_dev == dev) && (file_scanner_p->st_ino == inode) )
192 file_prev_p = file_scanner_p ;
193 file_scanner_p = (share_mode_record *)smb_shm_offset2addr(
194 file_scanner_p->next_offset);
200 DEBUG(5,("get_share_modes (FAST_SHARE_MODES): no entry for \
201 file dev = %d, ino = %d in hash_bucket %d\n", dev, inode, hash_entry));
205 if(file_scanner_p->locking_version != LOCKING_VERSION)
207 DEBUG(0,("ERROR:get_share_modes (FAST_SHARE_MODES): Deleting old share mode \
208 record due to old locking version %d for file dev = %d, inode = %d in hash \
209 bucket %d\n", file_scanner_p->locking_version, dev, inode, hash_entry));
210 if(file_prev_p == file_scanner_p)
211 mode_array[hash_entry] = file_scanner_p->next_offset;
213 file_prev_p->next_offset = file_scanner_p->next_offset;
214 smb_shm_free(smb_shm_addr2offset(file_scanner_p));
218 /* Allocate the old_shares array */
219 num_entries = file_scanner_p->num_share_mode_entries;
222 *old_shares = share_array = (min_share_mode_entry *)
223 malloc(num_entries * sizeof(min_share_mode_entry));
226 DEBUG(0,("get_share_modes (FAST_SHARE_MODES): malloc fail !\n"));
231 num_entries_copied = 0;
233 entry_scanner_p = (share_mode_entry*)smb_shm_offset2addr(
234 file_scanner_p->share_mode_entries);
235 entry_prev_p = entry_scanner_p;
236 while(entry_scanner_p)
238 int pid = entry_scanner_p->pid;
240 if (pid && !process_exists(pid))
242 /* Delete this share mode entry */
243 share_mode_entry *delete_entry_p = entry_scanner_p;
245 if(entry_prev_p == entry_scanner_p)
247 /* We are at start of list */
248 file_scanner_p->share_mode_entries = entry_scanner_p->next_share_mode_entry;
249 entry_scanner_p = (share_mode_entry*)smb_shm_offset2addr(
250 file_scanner_p->share_mode_entries);
251 entry_prev_p = entry_scanner_p;
255 entry_prev_p->next_share_mode_entry = entry_scanner_p->next_share_mode_entry;
256 entry_scanner_p = (share_mode_entry*)
257 smb_shm_offset2addr(entry_scanner_p->next_share_mode_entry);
259 /* Decrement the number of share mode entries on this share mode record */
260 file_scanner_p->num_share_mode_entries -= 1;
263 if(file_scanner_p->num_share_mode_entries < 0)
265 DEBUG(0,("PANIC ERROR:get_share_mode (FAST_SHARE_MODES): num_share_mode_entries < 0 (%d) \
266 for dev = %d, ino = %d, hashbucket %d\n", file_scanner_p->num_share_mode_entries,
267 dev, inode, hash_entry));
271 DEBUG(0,("get_share_modes (FAST_SHARE_MODES): process %d no longer exists and \
272 it left a share mode entry with mode 0x%X for file dev = %d, ino = %d in hash \
273 bucket %d (number of entries now = %d)\n",
274 pid, entry_scanner_p->share_mode, dev, inode, hash_entry,
275 file_scanner_p->num_share_mode_entries));
277 smb_shm_free(smb_shm_addr2offset(delete_entry_p));
281 /* This is a valid share mode entry and the process that
282 created it still exists. Copy it into the output array.
284 share_array[num_entries_copied].pid = entry_scanner_p->pid;
285 share_array[num_entries_copied].share_mode = entry_scanner_p->share_mode;
287 share_array[num_entries_copied].op_port = entry_scanner_p->op_port;
288 share_array[num_entries_copied].op_type = entry_scanner_p->op_type;
289 #endif /* USE_OPLOCKS */
290 memcpy(&share_array[num_entries_copied].time, &entry_scanner_p->time,
291 sizeof(struct timeval));
292 num_entries_copied++;
293 DEBUG(5,("get_share_modes (FAST_SHARE_MODES): Read share mode \
294 record mode 0x%X pid=%d\n", entry_scanner_p->share_mode, entry_scanner_p->pid));
295 entry_prev_p = entry_scanner_p;
296 entry_scanner_p = (share_mode_entry *)
297 smb_shm_offset2addr(entry_scanner_p->next_share_mode_entry);
301 /* If no valid share mode entries were found then this record shouldn't exist ! */
302 if(num_entries_copied == 0)
304 DEBUG(0,("get_share_modes (FAST_SHARE_MODES): file with dev %d, inode %d in \
305 hash bucket %d has a share mode record but no entries - deleting\n",
306 dev, inode, hash_entry));
308 free((char *)*old_shares);
311 if(file_prev_p == file_scanner_p)
312 mode_array[hash_entry] = file_scanner_p->next_offset;
314 file_prev_p->next_offset = file_scanner_p->next_offset;
315 smb_shm_free(smb_shm_addr2offset(file_scanner_p));
318 DEBUG(5,("get_share_modes (FAST_SHARE_MODES): file with dev %d, inode %d in \
319 hash bucket %d returning %d entries\n", dev, inode, hash_entry, num_entries_copied));
321 return(num_entries_copied);
324 /*******************************************************************
325 del the share mode of a file.
326 ********************************************************************/
327 void del_share_mode(share_lock_token token, int fnum)
330 smb_shm_offset_t *mode_array;
331 unsigned int hash_entry;
332 share_mode_record *file_scanner_p;
333 share_mode_record *file_prev_p;
334 share_mode_entry *entry_scanner_p;
335 share_mode_entry *entry_prev_p;
339 dev = Files[fnum].fd_ptr->dev;
340 inode = Files[fnum].fd_ptr->inode;
342 hash_entry = HASH_ENTRY(dev, inode);
344 if(hash_entry > lp_shmem_hash_size() )
347 ("PANIC ERROR:del_share_mode (FAST_SHARE_MODES): hash_entry %d too large \
349 hash_entry, lp_shmem_hash_size() ));
353 mode_array = (smb_shm_offset_t *)smb_shm_offset2addr(smb_shm_get_userdef_off());
355 if(mode_array[hash_entry] == NULL_OFFSET)
357 DEBUG(0,("PANIC ERROR:del_share_mode (FAST_SHARE_MODES): hash bucket %d empty\n",
362 file_scanner_p = (share_mode_record *)smb_shm_offset2addr(mode_array[hash_entry]);
363 file_prev_p = file_scanner_p;
365 while(file_scanner_p)
367 if( (file_scanner_p->st_dev == dev) && (file_scanner_p->st_ino == inode) )
374 file_prev_p = file_scanner_p ;
375 file_scanner_p = (share_mode_record *)
376 smb_shm_offset2addr(file_scanner_p->next_offset);
382 DEBUG(0,("ERROR:del_share_mode (FAST_SHARE_MODES): no entry found for dev %d, \
383 inode %d in hash bucket %d\n", dev, inode, hash_entry));
387 if(file_scanner_p->locking_version != LOCKING_VERSION)
389 DEBUG(0,("ERROR: del_share_modes (FAST_SHARE_MODES): Deleting old share mode \
390 record due to old locking version %d for file dev %d, inode %d hash bucket %d\n",
391 file_scanner_p->locking_version, dev, inode, hash_entry ));
392 if(file_prev_p == file_scanner_p)
393 mode_array[hash_entry] = file_scanner_p->next_offset;
395 file_prev_p->next_offset = file_scanner_p->next_offset;
396 smb_shm_free(smb_shm_addr2offset(file_scanner_p));
401 entry_scanner_p = (share_mode_entry*)smb_shm_offset2addr(
402 file_scanner_p->share_mode_entries);
403 entry_prev_p = entry_scanner_p;
404 while(entry_scanner_p)
406 if( (pid == entry_scanner_p->pid) &&
407 (memcmp(&entry_scanner_p->time,
408 &Files[fnum].open_time,sizeof(struct timeval)) == 0) )
415 entry_prev_p = entry_scanner_p;
416 entry_scanner_p = (share_mode_entry *)
417 smb_shm_offset2addr(entry_scanner_p->next_share_mode_entry);
423 /* Decrement the number of entries in the record. */
424 file_scanner_p->num_share_mode_entries -= 1;
426 DEBUG(2,("del_share_modes (FAST_SHARE_MODES): \
427 Deleting share mode entry dev = %d, inode = %d in hash bucket %d (num entries now = %d)\n",
428 dev, inode, hash_entry, file_scanner_p->num_share_mode_entries));
429 if(entry_prev_p == entry_scanner_p)
430 /* We are at start of list */
431 file_scanner_p->share_mode_entries = entry_scanner_p->next_share_mode_entry;
433 entry_prev_p->next_share_mode_entry = entry_scanner_p->next_share_mode_entry;
434 smb_shm_free(smb_shm_addr2offset(entry_scanner_p));
437 if(file_scanner_p->num_share_mode_entries < 0)
439 DEBUG(0,("PANIC ERROR:del_share_mode (FAST_SHARE_MODES): num_share_mode_entries < 0 (%d) \
440 for dev = %d, ino = %d, hashbucket %d\n", file_scanner_p->num_share_mode_entries,
441 dev, inode, hash_entry));
445 /* If we deleted the last share mode entry then remove the share mode record. */
446 if(file_scanner_p->num_share_mode_entries == 0)
448 DEBUG(2,("del_share_modes (FAST_SHARE_MODES): num entries = 0, deleting share_mode \
449 record dev = %d, inode = %d in hash bucket %d\n", dev, inode, hash_entry));
450 if(file_prev_p == file_scanner_p)
451 mode_array[hash_entry] = file_scanner_p->next_offset;
453 file_prev_p->next_offset = file_scanner_p->next_offset;
454 smb_shm_free(smb_shm_addr2offset(file_scanner_p));
459 DEBUG(0,("ERROR: del_share_modes (FAST_SHARE_MODES): No share mode record found \
460 dev = %d, inode = %d in hash bucket %d\n", dev, inode, hash_entry));
464 /*******************************************************************
465 set the share mode of a file. Return False on fail, True on success.
466 ********************************************************************/
467 BOOL set_share_mode(share_lock_token token, int fnum, uint16 port, uint16 op_type)
469 files_struct *fs_p = &Files[fnum];
471 smb_shm_offset_t *mode_array;
472 unsigned int hash_entry;
473 share_mode_record *file_scanner_p;
474 share_mode_record *file_prev_p;
475 share_mode_entry *new_entry_p;
476 smb_shm_offset_t new_entry_offset;
479 dev = fs_p->fd_ptr->dev;
480 inode = fs_p->fd_ptr->inode;
482 hash_entry = HASH_ENTRY(dev, inode);
483 if(hash_entry > lp_shmem_hash_size() )
486 ("PANIC ERROR:set_share_mode (FAST_SHARE_MODES): hash_entry %d too large \
488 hash_entry, lp_shmem_hash_size() ));
492 mode_array = (smb_shm_offset_t *)smb_shm_offset2addr(smb_shm_get_userdef_off());
494 file_scanner_p = (share_mode_record *)smb_shm_offset2addr(mode_array[hash_entry]);
495 file_prev_p = file_scanner_p;
497 while(file_scanner_p)
499 if( (file_scanner_p->st_dev == dev) && (file_scanner_p->st_ino == inode) )
506 file_prev_p = file_scanner_p ;
507 file_scanner_p = (share_mode_record *)
508 smb_shm_offset2addr(file_scanner_p->next_offset);
514 /* We must create a share_mode_record */
515 share_mode_record *new_mode_p = NULL;
516 smb_shm_offset_t new_offset = smb_shm_alloc( sizeof(share_mode_record) +
517 strlen(fs_p->name) + 1);
518 if(new_offset == NULL_OFFSET)
520 DEBUG(0,("ERROR:set_share_mode (FAST_SHARE_MODES): smb_shm_alloc fail !\n"));
523 new_mode_p = smb_shm_offset2addr(new_offset);
524 new_mode_p->locking_version = LOCKING_VERSION;
525 new_mode_p->st_dev = dev;
526 new_mode_p->st_ino = inode;
527 new_mode_p->num_share_mode_entries = 0;
528 new_mode_p->share_mode_entries = NULL_OFFSET;
529 strcpy(new_mode_p->file_name, fs_p->name);
531 /* Chain onto the start of the hash chain (in the hope we will be used first). */
532 new_mode_p->next_offset = mode_array[hash_entry];
533 mode_array[hash_entry] = new_offset;
535 file_scanner_p = new_mode_p;
537 DEBUG(3,("set_share_mode (FAST_SHARE_MODES): Created share record for %s (dev %d \
538 inode %d in hash bucket %d\n", fs_p->name, dev, inode, hash_entry));
541 /* Now create the share mode entry */
542 new_entry_offset = smb_shm_alloc( sizeof(share_mode_entry));
543 if(new_entry_offset == NULL_OFFSET)
545 smb_shm_offset_t delete_offset = mode_array[hash_entry];
546 DEBUG(0,("ERROR:set_share_mode (FAST_SHARE_MODES): smb_shm_alloc fail 1!\n"));
547 /* Unlink the damaged record */
548 mode_array[hash_entry] = file_scanner_p->next_offset;
550 smb_shm_free( delete_offset );
554 new_entry_p = smb_shm_offset2addr(new_entry_offset);
556 new_entry_p->pid = getpid();
557 new_entry_p->share_mode = fs_p->share_mode;
559 new_entry_p->op_port = port;
560 new_entry_p->op_type = op_type;
561 #endif /* USE_OPLOCKS */
562 memcpy( (char *)&new_entry_p->time, (char *)&fs_p->open_time, sizeof(struct timeval));
564 /* Chain onto the share_mode_record */
565 new_entry_p->next_share_mode_entry = file_scanner_p->share_mode_entries;
566 file_scanner_p->share_mode_entries = new_entry_offset;
569 if(file_scanner_p->num_share_mode_entries < 0)
571 DEBUG(0,("PANIC ERROR:set_share_mode (FAST_SHARE_MODES): num_share_mode_entries < 0 (%d) \
572 for dev = %d, ino = %d, hashbucket %d\n", file_scanner_p->num_share_mode_entries,
573 dev, inode, hash_entry));
577 /* Increment the share_mode_entries counter */
578 file_scanner_p->num_share_mode_entries += 1;
580 DEBUG(3,("set_share_mode (FAST_SHARE_MODES): Created share entry for %s with mode \
581 0x%X pid=%d (num_entries now = %d)\n",fs_p->name, fs_p->share_mode, new_entry_p->pid,
582 file_scanner_p->num_share_mode_entries));
587 /*******************************************************************
588 Remove an oplock port and mode entry from a share mode.
589 ********************************************************************/
590 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));
697 #else /* USE_OPLOCKS */
699 #endif /* USE_OPLOCKS */
702 #else /* FAST_SHARE_MODES */
704 /* SHARE MODE LOCKS USING SLOW DESCRIPTION FILES */
706 /*******************************************************************
708 ******************************************************************/
709 static BOOL share_name(int cnum, uint32 dev, uint32 inode, char *name)
711 strcpy(name,lp_lockdir());
712 standard_sub(cnum,name);
713 trim_string(name,"","/");
714 if (!*name) return(False);
715 name += strlen(name);
717 sprintf(name,"/share.%u.%u",dev,inode);
721 /*******************************************************************
722 lock a share mode file.
723 ******************************************************************/
724 BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok)
729 *ptok = (share_lock_token)-1;
731 if(!share_name(cnum, dev, inode, fname))
737 old_umask = umask(0);
738 #ifdef SECURE_SHARE_MODES
739 fd = (share_lock_token)open(fname,O_RDWR|O_CREAT,0600);
740 #else /* SECURE_SHARE_MODES */
741 fd = (share_lock_token)open(fname,O_RDWR|O_CREAT,0666);
742 #endif /* SECURE_SHARE_MODES */
744 if(!become_user(cnum,Connections[cnum].vuid))
746 DEBUG(0,("lock_share_entry: Can't become connected user!\n"));
750 /* We need to change directory back to the connection root. */
751 if (ChDir(Connections[cnum].connectpath) != 0)
753 DEBUG(0,("lock_share_entry: Can't change directory to %s (%s)\n",
754 Connections[cnum].connectpath, strerror(errno)));
760 /* At this point we have an open fd to the share mode file.
761 Lock the first byte exclusively to signify a lock. */
762 if(fcntl_lock(fd, F_SETLKW, 0, 1, F_WRLCK) == False)
764 DEBUG(0,("ERROR lock_share_entry: fcntl_lock failed with %s\n",
770 *ptok = (share_lock_token)fd;
774 /*******************************************************************
775 unlock a share mode file.
776 ******************************************************************/
777 BOOL unlock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token token)
782 /* token is the fd of the open share mode file. */
783 /* Unlock the first byte. */
784 if(fcntl_lock(fd, F_SETLKW, 0, 1, F_UNLCK) == False)
786 DEBUG(0,("ERROR unlock_share_entry: fcntl_lock failed with %s\n",
795 /*******************************************************************
796 Force a share file to be deleted.
797 ********************************************************************/
799 static int delete_share_file( int cnum, char *fname )
802 if(unlink(fname) != 0)
804 DEBUG(0,("delete_share_file: Can't delete share file %s (%s)\n",
805 fname, strerror(errno)));
808 DEBUG(5,("delete_share_file: Deleted share file %s\n", fname));
810 if(!become_user(cnum,Connections[cnum].vuid))
812 DEBUG(0,("delete_share_file: Can't become connected user!\n"));
815 /* We need to change directory back to the connection root. */
816 if (ChDir(Connections[cnum].connectpath) != 0)
818 DEBUG(0,("delete_share_file: Can't change directory to %s (%s)\n",
819 Connections[cnum].connectpath, strerror(errno)));
825 /*******************************************************************
826 Read a share file into a buffer.
827 ********************************************************************/
829 static int read_share_file(int cnum, int fd, char *fname, char **out, BOOL *p_new_file)
838 if(fstat(fd, &sb) != 0)
840 DEBUG(0,("ERROR: read_share_file: Failed to do stat on share file %s (%s)\n",
841 fname, strerror(errno)));
851 /* Allocate space for the file */
852 if((buf = (char *)malloc(sb.st_size)) == NULL)
854 DEBUG(0,("read_share_file: malloc for file size %d fail !\n", sb.st_size));
858 if(lseek(fd, 0, SEEK_SET) != 0)
860 DEBUG(0,("ERROR: read_share_file: Failed to reset position to 0 \
861 for share file %s (%s)\n", fname, strerror(errno)));
867 if (read(fd,buf,sb.st_size) != sb.st_size)
869 DEBUG(0,("ERROR: read_share_file: Failed to read share file %s (%s)\n",
870 fname, strerror(errno)));
876 if (IVAL(buf,SMF_VERSION_OFFSET) != LOCKING_VERSION) {
877 DEBUG(0,("ERROR: read_share_file: share file %s has incorrect \
878 locking version (was %d, should be %d).\n",fname,
879 IVAL(buf,SMF_VERSION_OFFSET), LOCKING_VERSION));
882 delete_share_file(cnum, fname);
886 /* Sanity check for file contents */
888 size -= SMF_HEADER_LENGTH; /* Remove the header */
890 /* Remove the filename component. */
891 size -= SVAL(buf, SMF_FILENAME_LEN_OFFSET);
893 /* The remaining size must be a multiple of SMF_ENTRY_LENGTH - error if not. */
894 if((size % SMF_ENTRY_LENGTH) != 0)
896 DEBUG(0,("ERROR: read_share_file: share file %s is an incorrect length - \
897 deleting it.\n", fname));
900 delete_share_file(cnum, fname);
908 /*******************************************************************
909 get all share mode entries in a share file for a dev/inode pair.
910 ********************************************************************/
911 int get_share_modes(int cnum, share_lock_token token, uint32 dev, uint32 inode,
912 min_share_mode_entry **old_shares)
918 int num_entries_copied;
920 min_share_mode_entry *share_array;
927 /* Read the share file header - this is of the form:
929 4 - number of share mode entries.
930 8 - 2 byte name length
931 [n bytes] file name (zero terminated).
933 Followed by <n> share mode entries of the form :
939 16 - oplock port (if oplocks in use) - 2 bytes.
942 share_name(cnum, dev, inode, fname);
944 if(read_share_file( cnum, fd, fname, &buf, &new_file) != 0)
946 DEBUG(0,("ERROR: get_share_modes: Failed to read share file %s\n",
954 num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET);
956 DEBUG(5,("get_share_modes: share file %s has %d share mode entries.\n",
957 fname, num_entries));
962 DEBUG(0,("PANIC ERROR:get_share_mode: num_share_mode_entries < 0 (%d) \
963 for share file %d\n", num_entries, fname));
969 *old_shares = share_array = (min_share_mode_entry *)
970 malloc(num_entries * sizeof(min_share_mode_entry));
973 DEBUG(0,("get_share_modes: malloc fail !\n"));
979 /* No entries - just delete the file. */
980 DEBUG(0,("get_share_modes: share file %s has no share mode entries - deleting.\n",
984 delete_share_file(cnum, fname);
988 num_entries_copied = 0;
989 base = buf + SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET);
991 for( i = 0; i < num_entries; i++)
994 char *p = base + (i*SMF_ENTRY_LENGTH);
996 pid = IVAL(p,SME_PID_OFFSET);
998 if(!process_exists(pid))
1000 DEBUG(0,("get_share_modes: process %d no longer exists and \
1001 it left a share mode entry with mode 0x%X in share file %s\n",
1002 pid, IVAL(p,SME_SHAREMODE_OFFSET), fname));
1005 share_array[num_entries_copied].time.tv_sec = IVAL(p,SME_SEC_OFFSET);
1006 share_array[num_entries_copied].time.tv_usec = IVAL(p,SME_USEC_OFFSET);
1007 share_array[num_entries_copied].share_mode = IVAL(p,SME_SHAREMODE_OFFSET);
1008 share_array[num_entries_copied].pid = pid;
1010 share_array[num_entries_copied].op_port = SVAL(p,SME_PORT_OFFSET);
1011 share_array[num_entries_copied].op_type = SVAL(p,SME_OPLOCK_TYPE_OFFSET);
1012 #endif /* USE_OPLOCKS */
1014 num_entries_copied++;
1017 if(num_entries_copied == 0)
1019 /* Delete the whole file. */
1020 DEBUG(0,("get_share_modes: share file %s had no valid entries - deleting it !\n",
1023 free((char *)*old_shares);
1027 delete_share_file(cnum, fname);
1031 /* If we deleted some entries we need to re-write the whole number of
1032 share mode entries back into the file. */
1034 if(num_entries_copied != num_entries)
1036 if(lseek(fd, 0, SEEK_SET) != 0)
1038 DEBUG(0,("ERROR: get_share_modes: lseek failed to reset to \
1039 position 0 for share mode file %s (%s)\n", fname, strerror(errno)));
1041 free((char *)*old_shares);
1048 SIVAL(buf, SMF_NUM_ENTRIES_OFFSET, num_entries_copied);
1049 for( i = 0; i < num_entries_copied; i++)
1051 char *p = base + (i*SMF_ENTRY_LENGTH);
1053 SIVAL(p,SME_PID_OFFSET,share_array[i].pid);
1054 SIVAL(p,SME_SHAREMODE_OFFSET,share_array[i].share_mode);
1055 SIVAL(p,SME_SEC_OFFSET,share_array[i].time.tv_sec);
1056 SIVAL(p,SME_USEC_OFFSET,share_array[i].time.tv_usec);
1058 SSVAL(p,SME_PORT_OFFSET,share_array[i].op_port);
1059 SSVAL(p,SME_OPLOCK_TYPE_OFFSET,share_array[i].op_type);
1060 #endif /* USE_OPLOCKS */
1063 newsize = (base - buf) + (SMF_ENTRY_LENGTH*num_entries_copied);
1064 if(write(fd, buf, newsize) != newsize)
1066 DEBUG(0,("ERROR: get_share_modes: failed to re-write share \
1067 mode file %s (%s)\n", fname, strerror(errno)));
1069 free((char *)*old_shares);
1075 /* Now truncate the file at this point. */
1076 if(ftruncate(fd, newsize)!= 0)
1078 DEBUG(0,("ERROR: get_share_modes: failed to ftruncate share \
1079 mode file %s to size %d (%s)\n", fname, newsize, strerror(errno)));
1081 free((char *)*old_shares);
1092 DEBUG(5,("get_share_modes: Read share file %s returning %d entries\n",fname,
1093 num_entries_copied));
1095 return num_entries_copied;
1098 /*******************************************************************
1099 del a share mode from a share mode file.
1100 ********************************************************************/
1101 void del_share_mode(share_lock_token token, int fnum)
1104 int fd = (int)token;
1110 files_struct *fs_p = &Files[fnum];
1112 BOOL deleted = False;
1115 share_name(fs_p->cnum, fs_p->fd_ptr->dev,
1116 fs_p->fd_ptr->inode, fname);
1118 if(read_share_file( fs_p->cnum, fd, fname, &buf, &new_file) != 0)
1120 DEBUG(0,("ERROR: del_share_mode: Failed to read share file %s\n",
1125 if(new_file == True)
1127 DEBUG(0,("ERROR:del_share_mode: share file %s is new (size zero), deleting it.\n",
1129 delete_share_file(fs_p->cnum, fname);
1133 num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET);
1135 DEBUG(5,("del_share_mode: share file %s has %d share mode entries.\n",
1136 fname, num_entries));
1141 DEBUG(0,("PANIC ERROR:del_share_mode: num_share_mode_entries < 0 (%d) \
1142 for share file %d\n", num_entries, fname));
1146 if(num_entries == 0)
1148 /* No entries - just delete the file. */
1149 DEBUG(0,("del_share_mode: share file %s has no share mode entries - deleting.\n",
1153 delete_share_file(fs_p->cnum, fname);
1159 /* Go through the entries looking for the particular one
1160 we have set - delete it.
1163 base = buf + SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET);
1165 for(i = 0; i < num_entries; i++)
1167 char *p = base + (i*SMF_ENTRY_LENGTH);
1169 if((IVAL(p,SME_SEC_OFFSET) != fs_p->open_time.tv_sec) ||
1170 (IVAL(p,SME_USEC_OFFSET) != fs_p->open_time.tv_usec) ||
1171 (IVAL(p,SME_SHAREMODE_OFFSET) != fs_p->share_mode) ||
1172 (IVAL(p,SME_PID_OFFSET) != pid))
1175 DEBUG(5,("del_share_mode: deleting entry number %d (of %d) from the share file %s\n",
1176 i, num_entries, fname));
1178 /* Remove this entry. */
1179 if(i != num_entries - 1)
1180 memcpy(p, p + SMF_ENTRY_LENGTH, (num_entries - i - 1)*SMF_ENTRY_LENGTH);
1188 DEBUG(0,("del_share_mode: entry not found in share file %s\n", fname));
1195 SIVAL(buf,SMF_NUM_ENTRIES_OFFSET, num_entries);
1197 if(num_entries == 0)
1199 /* Deleted the last entry - remove the file. */
1200 DEBUG(5,("del_share_mode: removed last entry in share file - deleting share file %s\n",
1204 delete_share_file(fs_p->cnum,fname);
1208 /* Re-write the file - and truncate it at the correct point. */
1209 if(lseek(fd, 0, SEEK_SET) != 0)
1211 DEBUG(0,("ERROR: del_share_mode: lseek failed to reset to \
1212 position 0 for share mode file %s (%s)\n", fname, strerror(errno)));
1218 newsize = (base - buf) + (SMF_ENTRY_LENGTH*num_entries);
1219 if(write(fd, buf, newsize) != newsize)
1221 DEBUG(0,("ERROR: del_share_mode: failed to re-write share \
1222 mode file %s (%s)\n", fname, strerror(errno)));
1227 /* Now truncate the file at this point. */
1228 if(ftruncate(fd, newsize) != 0)
1230 DEBUG(0,("ERROR: del_share_mode: failed to ftruncate share \
1231 mode file %s to size %d (%s)\n", fname, newsize, strerror(errno)));
1238 /*******************************************************************
1239 set the share mode of a file
1240 ********************************************************************/
1241 BOOL set_share_mode(share_lock_token token,int fnum, uint16 port, uint16 op_type)
1243 files_struct *fs_p = &Files[fnum];
1245 int fd = (int)token;
1246 int pid = (int)getpid();
1253 share_name(fs_p->cnum, fs_p->fd_ptr->dev,
1254 fs_p->fd_ptr->inode, fname);
1256 if(fstat(fd, &sb) != 0)
1258 DEBUG(0,("ERROR: set_share_mode: Failed to do stat on share file %s\n",
1263 /* Sanity check for file contents (if it's not a new share file). */
1266 int size = sb.st_size;
1268 /* Allocate space for the file plus one extra entry */
1269 if((buf = (char *)malloc(sb.st_size + SMF_ENTRY_LENGTH)) == NULL)
1271 DEBUG(0,("set_share_mode: malloc for file size %d fail !\n",
1272 sb.st_size + SMF_ENTRY_LENGTH));
1276 if(lseek(fd, 0, SEEK_SET) != 0)
1278 DEBUG(0,("ERROR: set_share_mode: Failed to reset position \
1279 to 0 for share file %s (%s)\n", fname, strerror(errno)));
1285 if (read(fd,buf,sb.st_size) != sb.st_size)
1287 DEBUG(0,("ERROR: set_share_mode: Failed to read share file %s (%s)\n",
1288 fname, strerror(errno)));
1294 if (IVAL(buf,SMF_VERSION_OFFSET) != LOCKING_VERSION)
1296 DEBUG(0,("ERROR: set_share_mode: share file %s has incorrect \
1297 locking version (was %d, should be %d).\n",fname, IVAL(buf,SMF_VERSION_OFFSET),
1301 delete_share_file(fs_p->cnum, fname);
1305 size -= (SMF_HEADER_LENGTH + SVAL(buf, SMF_FILENAME_LEN_OFFSET)); /* Remove the header */
1307 /* The remaining size must be a multiple of SMF_ENTRY_LENGTH - error if not. */
1308 if((size % SMF_ENTRY_LENGTH) != 0)
1310 DEBUG(0,("ERROR: set_share_mode: share file %s is an incorrect length - \
1311 deleting it.\n", fname));
1314 delete_share_file(fs_p->cnum, fname);
1321 /* New file - just use a single_entry. */
1322 if((buf = (char *)malloc(SMF_HEADER_LENGTH +
1323 strlen(fs_p->name) + 1 + SMF_ENTRY_LENGTH)) == NULL)
1325 DEBUG(0,("ERROR: set_share_mode: malloc failed for single entry.\n"));
1328 SIVAL(buf,SMF_VERSION_OFFSET,LOCKING_VERSION);
1329 SIVAL(buf,SMF_NUM_ENTRIES_OFFSET,0);
1330 SSVAL(buf,SMF_FILENAME_LEN_OFFSET,strlen(fs_p->name) + 1);
1331 strcpy(buf + SMF_HEADER_LENGTH, fs_p->name);
1334 num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET);
1335 header_size = SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET);
1336 p = buf + header_size + (num_entries * SMF_ENTRY_LENGTH);
1337 SIVAL(p,SME_SEC_OFFSET,fs_p->open_time.tv_sec);
1338 SIVAL(p,SME_USEC_OFFSET,fs_p->open_time.tv_usec);
1339 SIVAL(p,SME_SHAREMODE_OFFSET,fs_p->share_mode);
1340 SIVAL(p,SME_PID_OFFSET,pid);
1342 SSVAL(p,SME_PORT_OFFSET,port);
1343 SSVAL(p,SME_OPLOCK_TYPE_OFFSET,op_type);
1344 #endif /* USE_OPLOCKS */
1348 SIVAL(buf,SMF_NUM_ENTRIES_OFFSET,num_entries);
1350 if(lseek(fd, 0, SEEK_SET) != 0)
1352 DEBUG(0,("ERROR: set_share_mode: (1) Failed to reset position to \
1353 0 for share file %s (%s)\n", fname, strerror(errno)));
1359 if (write(fd,buf,header_size + (num_entries*SMF_ENTRY_LENGTH)) !=
1360 (header_size + (num_entries*SMF_ENTRY_LENGTH)))
1362 DEBUG(2,("ERROR: set_share_mode: Failed to write share file %s - \
1363 deleting it (%s).\n",fname, strerror(errno)));
1364 delete_share_file(fs_p->cnum, fname);
1370 /* Now truncate the file at this point - just for safety. */
1371 if(ftruncate(fd, header_size + (SMF_ENTRY_LENGTH*num_entries))!= 0)
1373 DEBUG(0,("ERROR: set_share_mode: failed to ftruncate share \
1374 mode file %s to size %d (%s)\n", fname, header_size + (SMF_ENTRY_LENGTH*num_entries),
1384 DEBUG(3,("set_share_mode: Created share file %s with \
1385 mode 0x%X pid=%d\n",fname,fs_p->share_mode,pid));
1390 /*******************************************************************
1391 Remove an oplock port and mode entry from a share mode.
1392 ********************************************************************/
1393 BOOL remove_share_oplock(int fnum, share_lock_token token)
1397 int fd = (int)token;
1403 files_struct *fs_p = &Files[fnum];
1408 share_name(fs_p->cnum, fs_p->fd_ptr->dev,
1409 fs_p->fd_ptr->inode, fname);
1411 if(read_share_file( fs_p->cnum, fd, fname, &buf, &new_file) != 0)
1413 DEBUG(0,("ERROR: remove_share_oplock: Failed to read share file %s\n",
1418 if(new_file == True)
1420 DEBUG(0,("ERROR: remove_share_oplock: share file %s is new (size zero), \
1421 deleting it.\n", fname));
1422 delete_share_file(fs_p->cnum, fname);
1426 num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET);
1428 DEBUG(5,("remove_share_oplock: share file %s has %d share mode entries.\n",
1429 fname, num_entries));
1434 DEBUG(0,("PANIC ERROR:remove_share_oplock: num_share_mode_entries < 0 (%d) \
1435 for share file %d\n", num_entries, fname));
1439 if(num_entries == 0)
1441 /* No entries - just delete the file. */
1442 DEBUG(0,("remove_share_oplock: share file %s has no share mode entries - deleting.\n",
1446 delete_share_file(fs_p->cnum, fname);
1452 /* Go through the entries looking for the particular one
1453 we have set - remove the oplock settings on it.
1456 base = buf + SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET);
1458 for(i = 0; i < num_entries; i++)
1460 char *p = base + (i*SMF_ENTRY_LENGTH);
1462 if((IVAL(p,SME_SEC_OFFSET) != fs_p->open_time.tv_sec) ||
1463 (IVAL(p,SME_USEC_OFFSET) != fs_p->open_time.tv_usec) ||
1464 (IVAL(p,SME_SHAREMODE_OFFSET) != fs_p->share_mode) ||
1465 (IVAL(p,SME_PID_OFFSET) != pid))
1468 DEBUG(5,("remove_share_oplock: clearing oplock on entry number %d (of %d) \
1469 from the share file %s\n", i, num_entries, fname));
1471 SSVAL(p,SME_PORT_OFFSET,0);
1472 SSVAL(p,SME_OPLOCK_TYPE_OFFSET,0);
1479 DEBUG(0,("remove_share_oplock: entry not found in share file %s\n", fname));
1485 /* Re-write the file - and truncate it at the correct point. */
1486 if(lseek(fd, 0, SEEK_SET) != 0)
1488 DEBUG(0,("ERROR: remove_share_oplock: lseek failed to reset to \
1489 position 0 for share mode file %s (%s)\n", fname, strerror(errno)));
1495 fsize = (base - buf) + (SMF_ENTRY_LENGTH*num_entries);
1496 if(write(fd, buf, fsize) != fsize)
1498 DEBUG(0,("ERROR: remove_share_oplock: failed to re-write share \
1499 mode file %s (%s)\n", fname, strerror(errno)));
1507 #else /* USE_OPLOCKS */
1509 #endif /* USE_OPLOCKS */
1511 #endif /* FAST_SHARE_MODES */