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->op_port != 0) &&
672 (entry_scanner_p->op_type != 0) &&
673 (memcmp(&entry_scanner_p->time,
674 &Files[fnum].open_time,sizeof(struct timeval)) == 0) )
676 /* Delete the oplock info. */
677 entry_scanner_p->op_port = 0;
678 entry_scanner_p->op_type = 0;
684 entry_prev_p = entry_scanner_p;
685 entry_scanner_p = (share_mode_entry *)
686 smb_shm_offset2addr(entry_scanner_p->next_share_mode_entry);
692 DEBUG(0,("ERROR: remove_share_oplock (FAST_SHARE_MODES): No oplock granted share \
693 mode record found dev = %d, inode = %d in hash bucket %d\n", dev, inode, hash_entry));
698 #else /* USE_OPLOCKS */
700 #endif /* USE_OPLOCKS */
703 #else /* FAST_SHARE_MODES */
705 /* SHARE MODE LOCKS USING SLOW DESCRIPTION FILES */
707 /*******************************************************************
709 ******************************************************************/
710 static BOOL share_name(int cnum, uint32 dev, uint32 inode, char *name)
712 strcpy(name,lp_lockdir());
713 standard_sub(cnum,name);
714 trim_string(name,"","/");
715 if (!*name) return(False);
716 name += strlen(name);
718 sprintf(name,"/share.%u.%u",dev,inode);
722 /*******************************************************************
723 lock a share mode file.
724 ******************************************************************/
725 BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok)
730 *ptok = (share_lock_token)-1;
732 if(!share_name(cnum, dev, inode, fname))
738 old_umask = umask(0);
739 #ifdef SECURE_SHARE_MODES
740 fd = (share_lock_token)open(fname,O_RDWR|O_CREAT,0600);
741 #else /* SECURE_SHARE_MODES */
742 fd = (share_lock_token)open(fname,O_RDWR|O_CREAT,0666);
743 #endif /* SECURE_SHARE_MODES */
745 if(!become_user(cnum,Connections[cnum].vuid))
747 DEBUG(0,("lock_share_entry: Can't become connected user!\n"));
751 /* We need to change directory back to the connection root. */
752 if (ChDir(Connections[cnum].connectpath) != 0)
754 DEBUG(0,("lock_share_entry: Can't change directory to %s (%s)\n",
755 Connections[cnum].connectpath, strerror(errno)));
761 /* At this point we have an open fd to the share mode file.
762 Lock the first byte exclusively to signify a lock. */
763 if(fcntl_lock(fd, F_SETLKW, 0, 1, F_WRLCK) == False)
765 DEBUG(0,("ERROR lock_share_entry: fcntl_lock failed with %s\n",
771 *ptok = (share_lock_token)fd;
775 /*******************************************************************
776 unlock a share mode file.
777 ******************************************************************/
778 BOOL unlock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token token)
783 /* token is the fd of the open share mode file. */
784 /* Unlock the first byte. */
785 if(fcntl_lock(fd, F_SETLKW, 0, 1, F_UNLCK) == False)
787 DEBUG(0,("ERROR unlock_share_entry: fcntl_lock failed with %s\n",
796 /*******************************************************************
797 Force a share file to be deleted.
798 ********************************************************************/
800 static int delete_share_file( int cnum, char *fname )
803 if(unlink(fname) != 0)
805 DEBUG(0,("delete_share_file: Can't delete share file %s (%s)\n",
806 fname, strerror(errno)));
809 DEBUG(5,("delete_share_file: Deleted share file %s\n", fname));
811 if(!become_user(cnum,Connections[cnum].vuid))
813 DEBUG(0,("delete_share_file: Can't become connected user!\n"));
816 /* We need to change directory back to the connection root. */
817 if (ChDir(Connections[cnum].connectpath) != 0)
819 DEBUG(0,("delete_share_file: Can't change directory to %s (%s)\n",
820 Connections[cnum].connectpath, strerror(errno)));
826 /*******************************************************************
827 Read a share file into a buffer.
828 ********************************************************************/
830 static int read_share_file(int cnum, int fd, char *fname, char **out, BOOL *p_new_file)
839 if(fstat(fd, &sb) != 0)
841 DEBUG(0,("ERROR: read_share_file: Failed to do stat on share file %s (%s)\n",
842 fname, strerror(errno)));
852 /* Allocate space for the file */
853 if((buf = (char *)malloc(sb.st_size)) == NULL)
855 DEBUG(0,("read_share_file: malloc for file size %d fail !\n", sb.st_size));
859 if(lseek(fd, 0, SEEK_SET) != 0)
861 DEBUG(0,("ERROR: read_share_file: Failed to reset position to 0 \
862 for share file %s (%s)\n", fname, strerror(errno)));
868 if (read(fd,buf,sb.st_size) != sb.st_size)
870 DEBUG(0,("ERROR: read_share_file: Failed to read share file %s (%s)\n",
871 fname, strerror(errno)));
877 if (IVAL(buf,SMF_VERSION_OFFSET) != LOCKING_VERSION) {
878 DEBUG(0,("ERROR: read_share_file: share file %s has incorrect \
879 locking version (was %d, should be %d).\n",fname,
880 IVAL(buf,SMF_VERSION_OFFSET), LOCKING_VERSION));
883 delete_share_file(cnum, fname);
887 /* Sanity check for file contents */
889 size -= SMF_HEADER_LENGTH; /* Remove the header */
891 /* Remove the filename component. */
892 size -= SVAL(buf, SMF_FILENAME_LEN_OFFSET);
894 /* The remaining size must be a multiple of SMF_ENTRY_LENGTH - error if not. */
895 if((size % SMF_ENTRY_LENGTH) != 0)
897 DEBUG(0,("ERROR: read_share_file: share file %s is an incorrect length - \
898 deleting it.\n", fname));
901 delete_share_file(cnum, fname);
909 /*******************************************************************
910 get all share mode entries in a share file for a dev/inode pair.
911 ********************************************************************/
912 int get_share_modes(int cnum, share_lock_token token, uint32 dev, uint32 inode,
913 min_share_mode_entry **old_shares)
919 int num_entries_copied;
921 min_share_mode_entry *share_array;
928 /* Read the share file header - this is of the form:
930 4 - number of share mode entries.
931 8 - 2 byte name length
932 [n bytes] file name (zero terminated).
934 Followed by <n> share mode entries of the form :
940 16 - oplock port (if oplocks in use) - 2 bytes.
943 share_name(cnum, dev, inode, fname);
945 if(read_share_file( cnum, fd, fname, &buf, &new_file) != 0)
947 DEBUG(0,("ERROR: get_share_modes: Failed to read share file %s\n",
955 num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET);
957 DEBUG(5,("get_share_modes: share file %s has %d share mode entries.\n",
958 fname, num_entries));
963 DEBUG(0,("PANIC ERROR:get_share_mode: num_share_mode_entries < 0 (%d) \
964 for share file %d\n", num_entries, fname));
970 *old_shares = share_array = (min_share_mode_entry *)
971 malloc(num_entries * sizeof(min_share_mode_entry));
974 DEBUG(0,("get_share_modes: malloc fail !\n"));
980 /* No entries - just delete the file. */
981 DEBUG(0,("get_share_modes: share file %s has no share mode entries - deleting.\n",
985 delete_share_file(cnum, fname);
989 num_entries_copied = 0;
990 base = buf + SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET);
992 for( i = 0; i < num_entries; i++)
995 char *p = base + (i*SMF_ENTRY_LENGTH);
997 pid = IVAL(p,SME_PID_OFFSET);
999 if(!process_exists(pid))
1001 DEBUG(0,("get_share_modes: process %d no longer exists and \
1002 it left a share mode entry with mode 0x%X in share file %s\n",
1003 pid, IVAL(p,SME_SHAREMODE_OFFSET), fname));
1006 share_array[num_entries_copied].time.tv_sec = IVAL(p,SME_SEC_OFFSET);
1007 share_array[num_entries_copied].time.tv_usec = IVAL(p,SME_USEC_OFFSET);
1008 share_array[num_entries_copied].share_mode = IVAL(p,SME_SHAREMODE_OFFSET);
1009 share_array[num_entries_copied].pid = pid;
1011 share_array[num_entries_copied].op_port = SVAL(p,SME_PORT_OFFSET);
1012 share_array[num_entries_copied].op_type = SVAL(p,SME_OPLOCK_TYPE_OFFSET);
1013 #endif /* USE_OPLOCKS */
1015 num_entries_copied++;
1018 if(num_entries_copied == 0)
1020 /* Delete the whole file. */
1021 DEBUG(0,("get_share_modes: share file %s had no valid entries - deleting it !\n",
1024 free((char *)*old_shares);
1028 delete_share_file(cnum, fname);
1032 /* If we deleted some entries we need to re-write the whole number of
1033 share mode entries back into the file. */
1035 if(num_entries_copied != num_entries)
1037 if(lseek(fd, 0, SEEK_SET) != 0)
1039 DEBUG(0,("ERROR: get_share_modes: lseek failed to reset to \
1040 position 0 for share mode file %s (%s)\n", fname, strerror(errno)));
1042 free((char *)*old_shares);
1049 SIVAL(buf, SMF_NUM_ENTRIES_OFFSET, num_entries_copied);
1050 for( i = 0; i < num_entries_copied; i++)
1052 char *p = base + (i*SMF_ENTRY_LENGTH);
1054 SIVAL(p,SME_PID_OFFSET,share_array[i].pid);
1055 SIVAL(p,SME_SHAREMODE_OFFSET,share_array[i].share_mode);
1056 SIVAL(p,SME_SEC_OFFSET,share_array[i].time.tv_sec);
1057 SIVAL(p,SME_USEC_OFFSET,share_array[i].time.tv_usec);
1059 SSVAL(p,SME_PORT_OFFSET,share_array[i].op_port);
1060 SSVAL(p,SME_OPLOCK_TYPE_OFFSET,share_array[i].op_type);
1061 #endif /* USE_OPLOCKS */
1064 newsize = (base - buf) + (SMF_ENTRY_LENGTH*num_entries_copied);
1065 if(write(fd, buf, newsize) != newsize)
1067 DEBUG(0,("ERROR: get_share_modes: failed to re-write share \
1068 mode file %s (%s)\n", fname, strerror(errno)));
1070 free((char *)*old_shares);
1076 /* Now truncate the file at this point. */
1077 if(ftruncate(fd, newsize)!= 0)
1079 DEBUG(0,("ERROR: get_share_modes: failed to ftruncate share \
1080 mode file %s to size %d (%s)\n", fname, newsize, strerror(errno)));
1082 free((char *)*old_shares);
1093 DEBUG(5,("get_share_modes: Read share file %s returning %d entries\n",fname,
1094 num_entries_copied));
1096 return num_entries_copied;
1099 /*******************************************************************
1100 del a share mode from a share mode file.
1101 ********************************************************************/
1102 void del_share_mode(share_lock_token token, int fnum)
1105 int fd = (int)token;
1111 files_struct *fs_p = &Files[fnum];
1113 BOOL deleted = False;
1116 share_name(fs_p->cnum, fs_p->fd_ptr->dev,
1117 fs_p->fd_ptr->inode, fname);
1119 if(read_share_file( fs_p->cnum, fd, fname, &buf, &new_file) != 0)
1121 DEBUG(0,("ERROR: del_share_mode: Failed to read share file %s\n",
1126 if(new_file == True)
1128 DEBUG(0,("ERROR:del_share_mode: share file %s is new (size zero), deleting it.\n",
1130 delete_share_file(fs_p->cnum, fname);
1134 num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET);
1136 DEBUG(5,("del_share_mode: share file %s has %d share mode entries.\n",
1137 fname, num_entries));
1142 DEBUG(0,("PANIC ERROR:del_share_mode: num_share_mode_entries < 0 (%d) \
1143 for share file %d\n", num_entries, fname));
1147 if(num_entries == 0)
1149 /* No entries - just delete the file. */
1150 DEBUG(0,("del_share_mode: share file %s has no share mode entries - deleting.\n",
1154 delete_share_file(fs_p->cnum, fname);
1160 /* Go through the entries looking for the particular one
1161 we have set - delete it.
1164 base = buf + SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET);
1166 for(i = 0; i < num_entries; i++)
1168 char *p = base + (i*SMF_ENTRY_LENGTH);
1170 if((IVAL(p,SME_SEC_OFFSET) != fs_p->open_time.tv_sec) ||
1171 (IVAL(p,SME_USEC_OFFSET) != fs_p->open_time.tv_usec) ||
1172 (IVAL(p,SME_SHAREMODE_OFFSET) != fs_p->share_mode) ||
1173 (IVAL(p,SME_PID_OFFSET) != pid))
1176 DEBUG(5,("del_share_mode: deleting entry number %d (of %d) from the share file %s\n",
1177 i, num_entries, fname));
1179 /* Remove this entry. */
1180 if(i != num_entries - 1)
1181 memcpy(p, p + SMF_ENTRY_LENGTH, (num_entries - i - 1)*SMF_ENTRY_LENGTH);
1189 DEBUG(0,("del_share_mode: entry not found in share file %s\n", fname));
1196 SIVAL(buf,SMF_NUM_ENTRIES_OFFSET, num_entries);
1198 if(num_entries == 0)
1200 /* Deleted the last entry - remove the file. */
1201 DEBUG(5,("del_share_mode: removed last entry in share file - deleting share file %s\n",
1205 delete_share_file(fs_p->cnum,fname);
1209 /* Re-write the file - and truncate it at the correct point. */
1210 if(lseek(fd, 0, SEEK_SET) != 0)
1212 DEBUG(0,("ERROR: del_share_mode: lseek failed to reset to \
1213 position 0 for share mode file %s (%s)\n", fname, strerror(errno)));
1219 newsize = (base - buf) + (SMF_ENTRY_LENGTH*num_entries);
1220 if(write(fd, buf, newsize) != newsize)
1222 DEBUG(0,("ERROR: del_share_mode: failed to re-write share \
1223 mode file %s (%s)\n", fname, strerror(errno)));
1228 /* Now truncate the file at this point. */
1229 if(ftruncate(fd, newsize) != 0)
1231 DEBUG(0,("ERROR: del_share_mode: failed to ftruncate share \
1232 mode file %s to size %d (%s)\n", fname, newsize, strerror(errno)));
1239 /*******************************************************************
1240 set the share mode of a file
1241 ********************************************************************/
1242 BOOL set_share_mode(share_lock_token token,int fnum, uint16 port, uint16 op_type)
1244 files_struct *fs_p = &Files[fnum];
1246 int fd = (int)token;
1247 int pid = (int)getpid();
1254 share_name(fs_p->cnum, fs_p->fd_ptr->dev,
1255 fs_p->fd_ptr->inode, fname);
1257 if(fstat(fd, &sb) != 0)
1259 DEBUG(0,("ERROR: set_share_mode: Failed to do stat on share file %s\n",
1264 /* Sanity check for file contents (if it's not a new share file). */
1267 int size = sb.st_size;
1269 /* Allocate space for the file plus one extra entry */
1270 if((buf = (char *)malloc(sb.st_size + SMF_ENTRY_LENGTH)) == NULL)
1272 DEBUG(0,("set_share_mode: malloc for file size %d fail !\n",
1273 sb.st_size + SMF_ENTRY_LENGTH));
1277 if(lseek(fd, 0, SEEK_SET) != 0)
1279 DEBUG(0,("ERROR: set_share_mode: Failed to reset position \
1280 to 0 for share file %s (%s)\n", fname, strerror(errno)));
1286 if (read(fd,buf,sb.st_size) != sb.st_size)
1288 DEBUG(0,("ERROR: set_share_mode: Failed to read share file %s (%s)\n",
1289 fname, strerror(errno)));
1295 if (IVAL(buf,SMF_VERSION_OFFSET) != LOCKING_VERSION)
1297 DEBUG(0,("ERROR: set_share_mode: share file %s has incorrect \
1298 locking version (was %d, should be %d).\n",fname, IVAL(buf,SMF_VERSION_OFFSET),
1302 delete_share_file(fs_p->cnum, fname);
1306 size -= (SMF_HEADER_LENGTH + SVAL(buf, SMF_FILENAME_LEN_OFFSET)); /* Remove the header */
1308 /* The remaining size must be a multiple of SMF_ENTRY_LENGTH - error if not. */
1309 if((size % SMF_ENTRY_LENGTH) != 0)
1311 DEBUG(0,("ERROR: set_share_mode: share file %s is an incorrect length - \
1312 deleting it.\n", fname));
1315 delete_share_file(fs_p->cnum, fname);
1322 /* New file - just use a single_entry. */
1323 if((buf = (char *)malloc(SMF_HEADER_LENGTH +
1324 strlen(fs_p->name) + 1 + SMF_ENTRY_LENGTH)) == NULL)
1326 DEBUG(0,("ERROR: set_share_mode: malloc failed for single entry.\n"));
1329 SIVAL(buf,SMF_VERSION_OFFSET,LOCKING_VERSION);
1330 SIVAL(buf,SMF_NUM_ENTRIES_OFFSET,0);
1331 SSVAL(buf,SMF_FILENAME_LEN_OFFSET,strlen(fs_p->name) + 1);
1332 strcpy(buf + SMF_HEADER_LENGTH, fs_p->name);
1335 num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET);
1336 header_size = SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET);
1337 p = buf + header_size + (num_entries * SMF_ENTRY_LENGTH);
1338 SIVAL(p,SME_SEC_OFFSET,fs_p->open_time.tv_sec);
1339 SIVAL(p,SME_USEC_OFFSET,fs_p->open_time.tv_usec);
1340 SIVAL(p,SME_SHAREMODE_OFFSET,fs_p->share_mode);
1341 SIVAL(p,SME_PID_OFFSET,pid);
1343 SSVAL(p,SME_PORT_OFFSET,port);
1344 SSVAL(p,SME_OPLOCK_TYPE_OFFSET,op_type);
1345 #endif /* USE_OPLOCKS */
1349 SIVAL(buf,SMF_NUM_ENTRIES_OFFSET,num_entries);
1351 if(lseek(fd, 0, SEEK_SET) != 0)
1353 DEBUG(0,("ERROR: set_share_mode: (1) Failed to reset position to \
1354 0 for share file %s (%s)\n", fname, strerror(errno)));
1360 if (write(fd,buf,header_size + (num_entries*SMF_ENTRY_LENGTH)) !=
1361 (header_size + (num_entries*SMF_ENTRY_LENGTH)))
1363 DEBUG(2,("ERROR: set_share_mode: Failed to write share file %s - \
1364 deleting it (%s).\n",fname, strerror(errno)));
1365 delete_share_file(fs_p->cnum, fname);
1371 /* Now truncate the file at this point - just for safety. */
1372 if(ftruncate(fd, header_size + (SMF_ENTRY_LENGTH*num_entries))!= 0)
1374 DEBUG(0,("ERROR: set_share_mode: failed to ftruncate share \
1375 mode file %s to size %d (%s)\n", fname, header_size + (SMF_ENTRY_LENGTH*num_entries),
1385 DEBUG(3,("set_share_mode: Created share file %s with \
1386 mode 0x%X pid=%d\n",fname,fs_p->share_mode,pid));
1391 /*******************************************************************
1392 Remove an oplock port and mode entry from a share mode.
1393 ********************************************************************/
1394 BOOL remove_share_oplock(int fnum, share_lock_token token)
1398 int fd = (int)token;
1404 files_struct *fs_p = &Files[fnum];
1409 share_name(fs_p->cnum, fs_p->fd_ptr->dev,
1410 fs_p->fd_ptr->inode, fname);
1412 if(read_share_file( fs_p->cnum, fd, fname, &buf, &new_file) != 0)
1414 DEBUG(0,("ERROR: remove_share_oplock: Failed to read share file %s\n",
1419 if(new_file == True)
1421 DEBUG(0,("ERROR: remove_share_oplock: share file %s is new (size zero), \
1422 deleting it.\n", fname));
1423 delete_share_file(fs_p->cnum, fname);
1427 num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET);
1429 DEBUG(5,("remove_share_oplock: share file %s has %d share mode entries.\n",
1430 fname, num_entries));
1435 DEBUG(0,("PANIC ERROR:remove_share_oplock: num_share_mode_entries < 0 (%d) \
1436 for share file %d\n", num_entries, fname));
1440 if(num_entries == 0)
1442 /* No entries - just delete the file. */
1443 DEBUG(0,("remove_share_oplock: share file %s has no share mode entries - deleting.\n",
1447 delete_share_file(fs_p->cnum, fname);
1453 /* Go through the entries looking for the particular one
1454 we have set - remove the oplock settings on it.
1457 base = buf + SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET);
1459 for(i = 0; i < num_entries; i++)
1461 char *p = base + (i*SMF_ENTRY_LENGTH);
1463 if((IVAL(p,SME_SEC_OFFSET) != fs_p->open_time.tv_sec) ||
1464 (IVAL(p,SME_USEC_OFFSET) != fs_p->open_time.tv_usec) ||
1465 (IVAL(p,SME_SHAREMODE_OFFSET) != fs_p->share_mode) ||
1466 (IVAL(p,SME_PID_OFFSET) != pid) ||
1467 (SVAL(p,SME_PORT_OFFSET) == 0) ||
1468 (SVAL(p,SME_OPLOCK_TYPE_OFFSET) == 0))
1471 DEBUG(5,("remove_share_oplock: clearing oplock on entry number %d (of %d) \
1472 from the share file %s\n", i, num_entries, fname));
1474 SSVAL(p,SME_PORT_OFFSET,0);
1475 SSVAL(p,SME_OPLOCK_TYPE_OFFSET,0);
1482 DEBUG(0,("remove_share_oplock: entry not found in share file %s\n", fname));
1488 /* Re-write the file - and truncate it at the correct point. */
1489 if(lseek(fd, 0, SEEK_SET) != 0)
1491 DEBUG(0,("ERROR: remove_share_oplock: lseek failed to reset to \
1492 position 0 for share mode file %s (%s)\n", fname, strerror(errno)));
1498 fsize = (base - buf) + (SMF_ENTRY_LENGTH*num_entries);
1499 if(write(fd, buf, fsize) != fsize)
1501 DEBUG(0,("ERROR: remove_share_oplock: failed to re-write share \
1502 mode file %s (%s)\n", fname, strerror(errno)));
1510 #else /* USE_OPLOCKS */
1512 #endif /* USE_OPLOCKS */
1514 #endif /* FAST_SHARE_MODES */