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 strcpy(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",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 (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
;
286 memcpy(&share_array
[num_entries_copied
].time
, &entry_scanner_p
->time
,
287 sizeof(struct timeval
));
288 num_entries_copied
++;
289 DEBUG(5,("get_share_modes (FAST_SHARE_MODES): Read share mode \
290 record mode 0x%X pid=%d\n", entry_scanner_p
->share_mode
, entry_scanner_p
->pid
));
291 entry_prev_p
= entry_scanner_p
;
292 entry_scanner_p
= (share_mode_entry
*)
293 smb_shm_offset2addr(entry_scanner_p
->next_share_mode_entry
);
297 /* If no valid share mode entries were found then this record shouldn't exist ! */
298 if(num_entries_copied
== 0)
300 DEBUG(0,("get_share_modes (FAST_SHARE_MODES): file with dev %d, inode %d in \
301 hash bucket %d has a share mode record but no entries - deleting\n",
302 dev
, inode
, hash_entry
));
304 free((char *)old_shares
);
307 if(file_prev_p
== file_scanner_p
)
308 mode_array
[hash_entry
] = file_scanner_p
->next_offset
;
310 file_prev_p
->next_offset
= file_scanner_p
->next_offset
;
311 smb_shm_free(smb_shm_addr2offset(file_scanner_p
));
314 DEBUG(5,("get_share_modes (FAST_SHARE_MODES): file with dev %d, inode %d in \
315 hash bucket %d returning %d entries\n", dev
, inode
, hash_entry
,
316 num_entries_copied
));
318 return(num_entries_copied
);
321 /*******************************************************************
322 del the share mode of a file.
323 ********************************************************************/
324 void del_share_mode(share_lock_token token
, int fnum
)
327 smb_shm_offset_t
*mode_array
;
328 unsigned int hash_entry
;
329 share_mode_record
*file_scanner_p
;
330 share_mode_record
*file_prev_p
;
331 share_mode_entry
*entry_scanner_p
;
332 share_mode_entry
*entry_prev_p
;
336 dev
= Files
[fnum
].fd_ptr
->dev
;
337 inode
= Files
[fnum
].fd_ptr
->inode
;
339 hash_entry
= HASH_ENTRY(dev
, inode
);
341 if(hash_entry
> lp_shmem_hash_size() )
344 ("PANIC ERROR:del_share_mode (FAST_SHARE_MODES): hash_entry %d too large \
346 hash_entry
, lp_shmem_hash_size() ));
350 mode_array
= (smb_shm_offset_t
*)smb_shm_offset2addr(smb_shm_get_userdef_off());
352 if(mode_array
[hash_entry
] == NULL_OFFSET
)
354 DEBUG(0,("PANIC ERROR:del_share_mode (FAST_SHARE_MODES): hash bucket %d empty\n",
359 file_scanner_p
= (share_mode_record
*)smb_shm_offset2addr(mode_array
[hash_entry
]);
360 file_prev_p
= file_scanner_p
;
362 while(file_scanner_p
)
364 if( (file_scanner_p
->st_dev
== dev
) && (file_scanner_p
->st_ino
== inode
) )
371 file_prev_p
= file_scanner_p
;
372 file_scanner_p
= (share_mode_record
*)
373 smb_shm_offset2addr(file_scanner_p
->next_offset
);
379 DEBUG(0,("ERROR:del_share_mode (FAST_SHARE_MODES): no entry found for dev %d, \
380 inode %d in hash bucket %d\n", dev
, inode
, hash_entry
));
384 if(file_scanner_p
->locking_version
!= LOCKING_VERSION
)
386 DEBUG(0,("ERROR: del_share_modes (FAST_SHARE_MODES): Deleting old share mode \
387 record due to old locking version %d for file dev %d, inode %d hash bucket %d\n",
388 file_scanner_p
->locking_version
, dev
, inode
, hash_entry
));
389 if(file_prev_p
== file_scanner_p
)
390 mode_array
[hash_entry
] = file_scanner_p
->next_offset
;
392 file_prev_p
->next_offset
= file_scanner_p
->next_offset
;
393 smb_shm_free(smb_shm_addr2offset(file_scanner_p
));
398 entry_scanner_p
= (share_mode_entry
*)smb_shm_offset2addr(
399 file_scanner_p
->share_mode_entries
);
400 entry_prev_p
= entry_scanner_p
;
401 while(entry_scanner_p
)
403 if( (pid
== entry_scanner_p
->pid
) &&
404 (memcmp(&entry_scanner_p
->time
,
405 &Files
[fnum
].open_time
,sizeof(struct timeval
)) == 0) )
412 entry_prev_p
= entry_scanner_p
;
413 entry_scanner_p
= (share_mode_entry
*)
414 smb_shm_offset2addr(entry_scanner_p
->next_share_mode_entry
);
420 /* Decrement the number of entries in the record. */
421 file_scanner_p
->num_share_mode_entries
-= 1;
423 DEBUG(2,("del_share_modes (FAST_SHARE_MODES): \
424 Deleting share mode entry dev = %d, inode = %d in hash bucket %d (num entries now = %d)\n",
425 dev
, inode
, hash_entry
, file_scanner_p
->num_share_mode_entries
));
426 if(entry_prev_p
== entry_scanner_p
)
427 /* We are at start of list */
428 file_scanner_p
->share_mode_entries
= entry_scanner_p
->next_share_mode_entry
;
430 entry_prev_p
->next_share_mode_entry
= entry_scanner_p
->next_share_mode_entry
;
431 smb_shm_free(smb_shm_addr2offset(entry_scanner_p
));
434 if(file_scanner_p
->num_share_mode_entries
< 0)
436 DEBUG(0,("PANIC ERROR:del_share_mode (FAST_SHARE_MODES): num_share_mode_entries < 0 (%d) \
437 for dev = %d, ino = %d, hashbucket %d\n", file_scanner_p
->num_share_mode_entries
,
438 dev
, inode
, hash_entry
));
442 /* If we deleted the last share mode entry then remove the share mode record. */
443 if(file_scanner_p
->num_share_mode_entries
== 0)
445 DEBUG(2,("del_share_modes (FAST_SHARE_MODES): num entries = 0, deleting share_mode \
446 record dev = %d, inode = %d in hash bucket %d\n", dev
, inode
, hash_entry
));
447 if(file_prev_p
== file_scanner_p
)
448 mode_array
[hash_entry
] = file_scanner_p
->next_offset
;
450 file_prev_p
->next_offset
= file_scanner_p
->next_offset
;
451 smb_shm_free(smb_shm_addr2offset(file_scanner_p
));
456 DEBUG(0,("ERROR: del_share_modes (FAST_SHARE_MODES): No share mode record found \
457 dev = %d, inode = %d in hash bucket %d\n", dev
, inode
, hash_entry
));
461 /*******************************************************************
462 set the share mode of a file. Return False on fail, True on success.
463 ********************************************************************/
464 BOOL
set_share_mode(share_lock_token token
, int fnum
)
466 files_struct
*fs_p
= &Files
[fnum
];
468 smb_shm_offset_t
*mode_array
;
469 unsigned int hash_entry
;
470 share_mode_record
*file_scanner_p
;
471 share_mode_record
*file_prev_p
;
472 share_mode_entry
*new_entry_p
;
473 smb_shm_offset_t new_entry_offset
;
476 dev
= fs_p
->fd_ptr
->dev
;
477 inode
= fs_p
->fd_ptr
->inode
;
479 hash_entry
= HASH_ENTRY(dev
, inode
);
480 if(hash_entry
> lp_shmem_hash_size() )
483 ("PANIC ERROR:set_share_mode (FAST_SHARE_MODES): hash_entry %d too large \
485 hash_entry
, lp_shmem_hash_size() ));
489 mode_array
= (smb_shm_offset_t
*)smb_shm_offset2addr(smb_shm_get_userdef_off());
491 file_scanner_p
= (share_mode_record
*)smb_shm_offset2addr(mode_array
[hash_entry
]);
492 file_prev_p
= file_scanner_p
;
494 while(file_scanner_p
)
496 if( (file_scanner_p
->st_dev
== dev
) && (file_scanner_p
->st_ino
== inode
) )
503 file_prev_p
= file_scanner_p
;
504 file_scanner_p
= (share_mode_record
*)
505 smb_shm_offset2addr(file_scanner_p
->next_offset
);
511 /* We must create a share_mode_record */
512 share_mode_record
*new_mode_p
= NULL
;
513 smb_shm_offset_t new_offset
= smb_shm_alloc( sizeof(share_mode_record
) +
514 strlen(fs_p
->name
) + 1);
515 if(new_offset
== NULL_OFFSET
)
517 DEBUG(0,("ERROR:set_share_mode (FAST_SHARE_MODES): smb_shm_alloc fail !\n"));
520 new_mode_p
= smb_shm_offset2addr(new_offset
);
521 new_mode_p
->locking_version
= LOCKING_VERSION
;
522 new_mode_p
->st_dev
= dev
;
523 new_mode_p
->st_ino
= inode
;
524 new_mode_p
->num_share_mode_entries
= 0;
525 new_mode_p
->share_mode_entries
= NULL_OFFSET
;
526 strcpy(new_mode_p
->file_name
, fs_p
->name
);
528 /* Chain onto the start of the hash chain (in the hope we will be used first). */
529 new_mode_p
->next_offset
= mode_array
[hash_entry
];
530 mode_array
[hash_entry
] = new_offset
;
532 file_scanner_p
= new_mode_p
;
534 DEBUG(3,("set_share_mode (FAST_SHARE_MODES): Created share record for %s (dev %d \
535 inode %d in hash bucket %d\n", fs_p
->name
, dev
, inode
, hash_entry
));
538 /* Now create the share mode entry */
539 new_entry_offset
= smb_shm_alloc( sizeof(share_mode_entry
));
540 if(new_entry_offset
== NULL_OFFSET
)
542 smb_shm_offset_t delete_offset
= mode_array
[hash_entry
];
543 DEBUG(0,("ERROR:set_share_mode (FAST_SHARE_MODES): smb_shm_alloc fail 1!\n"));
544 /* Unlink the damaged record */
545 mode_array
[hash_entry
] = file_scanner_p
->next_offset
;
547 smb_shm_free( delete_offset
);
551 new_entry_p
= smb_shm_offset2addr(new_entry_offset
);
553 new_entry_p
->pid
= getpid();
554 new_entry_p
->share_mode
= fs_p
->share_mode
;
555 memcpy( (char *)&new_entry_p
->time
, (char *)&fs_p
->open_time
, sizeof(struct timeval
));
557 /* Chain onto the share_mode_record */
558 new_entry_p
->next_share_mode_entry
= file_scanner_p
->share_mode_entries
;
559 file_scanner_p
->share_mode_entries
= new_entry_offset
;
562 if(file_scanner_p
->num_share_mode_entries
< 0)
564 DEBUG(0,("PANIC ERROR:set_share_mode (FAST_SHARE_MODES): num_share_mode_entries < 0 (%d) \
565 for dev = %d, ino = %d, hashbucket %d\n", file_scanner_p
->num_share_mode_entries
,
566 dev
, inode
, hash_entry
));
570 /* Increment the share_mode_entries counter */
571 file_scanner_p
->num_share_mode_entries
+= 1;
573 DEBUG(3,("set_share_mode (FAST_SHARE_MODES): Created share entry for %s with mode \
574 0x%X pid=%d (num_entries now = %d)\n",fs_p
->name
, fs_p
->share_mode
, new_entry_p
->pid
,
575 file_scanner_p
->num_share_mode_entries
));
580 #else /* FAST_SHARE_MODES */
582 /* SHARE MODE LOCKS USING SLOW DESCRIPTION FILES */
584 /*******************************************************************
586 ******************************************************************/
587 static BOOL
share_name(int cnum
, uint32 dev
, uint32 inode
, char *name
)
589 strcpy(name
,lp_lockdir());
590 standard_sub(cnum
,name
);
591 trim_string(name
,"","/");
592 if (!*name
) return(False
);
593 name
+= strlen(name
);
595 sprintf(name
,"/share.%u.%u",dev
,inode
);
599 /*******************************************************************
600 lock a share mode file.
601 ******************************************************************/
602 BOOL
lock_share_entry(int cnum
, uint32 dev
, uint32 inode
, share_lock_token
*ptok
)
607 *ptok
= (share_lock_token
)-1;
609 if(!share_name(cnum
, dev
, inode
, fname
))
615 old_umask
= umask(0);
616 #ifdef SECURE_SHARE_MODES
617 fd
= (share_lock_token
)open(fname
,O_RDWR
|O_CREAT
,0600);
618 #else /* SECURE_SHARE_MODES */
619 fd
= (share_lock_token
)open(fname
,O_RDWR
|O_CREAT
,0644);
620 #endif /* SECURE_SHARE_MODES */
622 if(!become_user(cnum
,Connections
[cnum
].vuid
))
624 DEBUG(0,("lock_share_entry: Can't become connected user!\n"));
628 /* We need to change directory back to the connection root. */
629 if (ChDir(Connections
[cnum
].connectpath
) != 0)
631 DEBUG(0,("lock_share_entry: Can't change directory to %s (%s)\n",
632 Connections
[cnum
].connectpath
, strerror(errno
)));
638 /* At this point we have an open fd to the share mode file.
639 Lock the first byte exclusively to signify a lock. */
640 if(fcntl_lock(fd
, F_SETLKW
, 0, 1, F_WRLCK
) == False
)
642 DEBUG(0,("ERROR lock_share_entry: fcntl_lock failed with %s\n",
648 *ptok
= (share_lock_token
)fd
;
652 /*******************************************************************
653 unlock a share mode file.
654 ******************************************************************/
655 BOOL
unlock_share_entry(int cnum
, uint32 dev
, uint32 inode
, share_lock_token token
)
660 /* token is the fd of the open share mode file. */
661 /* Unlock the first byte. */
662 if(fcntl_lock(fd
, F_SETLKW
, 0, 1, F_UNLCK
) == False
)
664 DEBUG(0,("ERROR unlock_share_entry: fcntl_lock failed with %s\n",
673 /*******************************************************************
674 Force a share file to be deleted.
675 ********************************************************************/
677 static int delete_share_file( int cnum
, char *fname
)
680 if(unlink(fname
) != 0)
682 DEBUG(0,("delete_share_file: Can't delete share file %s (%s)\n",
683 fname
, strerror(errno
)));
686 DEBUG(5,("delete_share_file: Deleted share file %s\n", fname
));
688 if(!become_user(cnum
,Connections
[cnum
].vuid
))
690 DEBUG(0,("delete_share_file: Can't become connected user!\n"));
693 /* We need to change directory back to the connection root. */
694 if (ChDir(Connections
[cnum
].connectpath
) != 0)
696 DEBUG(0,("delete_share_file: Can't change directory to %s (%s)\n",
697 Connections
[cnum
].connectpath
, strerror(errno
)));
703 /*******************************************************************
704 Read a share file into a buffer.
705 ********************************************************************/
707 static int read_share_file(int cnum
, int fd
, char *fname
, char **out
, BOOL
*p_new_file
)
716 if(fstat(fd
, &sb
) != 0)
718 DEBUG(0,("ERROR: read_share_file: Failed to do stat on share file %s (%s)\n",
719 fname
, strerror(errno
)));
729 /* Allocate space for the file */
730 if((buf
= (char *)malloc(sb
.st_size
)) == NULL
)
732 DEBUG(0,("read_share_file: malloc for file size %d fail !\n", sb
.st_size
));
736 if(lseek(fd
, 0, SEEK_SET
) != 0)
738 DEBUG(0,("ERROR: read_share_file: Failed to reset position to 0 \
739 for share file %s (%s)\n", fname
, strerror(errno
)));
745 if (read(fd
,buf
,sb
.st_size
) != sb
.st_size
)
747 DEBUG(0,("ERROR: read_share_file: Failed to read share file %s (%s)\n",
748 fname
, strerror(errno
)));
754 if (IVAL(buf
,0) != LOCKING_VERSION
) {
755 DEBUG(0,("ERROR: read_share_file: share file %s has incorrect \
756 locking version (was %d, should be %d).\n",fname
, IVAL(buf
,0), LOCKING_VERSION
));
759 delete_share_file(cnum
, fname
);
763 /* Sanity check for file contents */
765 size
-= 10; /* Remove the header */
767 /* Remove the filename component. */
768 size
-= SVAL(buf
, 8);
770 /* The remaining size must be a multiple of 16 - error if not. */
773 DEBUG(0,("ERROR: read_share_file: share file %s is an incorrect length - \
774 deleting it.\n", fname
));
777 delete_share_file(cnum
, fname
);
785 /*******************************************************************
786 get all share mode entries in a share file for a dev/inode pair.
787 ********************************************************************/
788 int get_share_modes(int cnum
, share_lock_token token
, uint32 dev
, uint32 inode
,
789 min_share_mode_entry
**old_shares
)
795 int num_entries_copied
;
797 min_share_mode_entry
*share_array
;
804 /* Read the share file header - this is of the form:
806 4 - number of share mode entries.
807 8 - 2 byte name length
808 [n bytes] file name (zero terminated).
810 Followed by <n> share mode entries of the form :
819 share_name(cnum
, dev
, inode
, fname
);
821 if(read_share_file( cnum
, fd
, fname
, &buf
, &new_file
) != 0)
823 DEBUG(0,("ERROR: get_share_modes: Failed to read share file %s\n",
831 num_entries
= IVAL(buf
,4);
833 DEBUG(5,("get_share_modes: share file %s has %d share mode entries.\n",
834 fname
, num_entries
));
839 DEBUG(0,("PANIC ERROR:get_share_mode: num_share_mode_entries < 0 (%d) \
840 for share file %d\n", num_entries
, fname
));
846 *old_shares
= share_array
= (min_share_mode_entry
*)
847 malloc(num_entries
* sizeof(min_share_mode_entry
));
850 DEBUG(0,("get_share_modes: malloc fail !\n"));
856 /* No entries - just delete the file. */
857 DEBUG(0,("get_share_modes: share file %s has no share mode entries - deleting.\n",
861 delete_share_file(cnum
, fname
);
865 num_entries_copied
= 0;
866 base
= buf
+ 10 + SVAL(buf
,8);
868 for( i
= 0; i
< num_entries
; i
++)
871 char *p
= base
+ (i
*16);
875 if(!process_exists(pid
))
877 DEBUG(0,("get_share_modes: process %d no longer exists and \
878 it left a share mode entry with mode 0x%X in share file %s\n",
879 pid
, IVAL(p
,8), fname
));
882 share_array
[num_entries_copied
].time
.tv_sec
= IVAL(p
,0);
883 share_array
[num_entries_copied
].time
.tv_usec
= IVAL(p
,4);
884 share_array
[num_entries_copied
].share_mode
= IVAL(p
,8);
885 share_array
[num_entries_copied
].pid
= pid
;
887 num_entries_copied
++;
890 if(num_entries_copied
== 0)
892 /* Delete the whole file. */
893 DEBUG(0,("get_share_modes: share file %s had no valid entries - deleting it !\n",
896 free((char *)old_shares
);
899 delete_share_file(cnum
, fname
);
903 /* If we deleted some entries we need to re-write the whole number of
904 share mode entries back into the file. */
906 if(num_entries_copied
!= num_entries
)
908 if(lseek(fd
, 0, SEEK_SET
) != 0)
910 DEBUG(0,("ERROR: get_share_modes: lseek failed to reset to \
911 position 0 for share mode file %s (%s)\n", fname
, strerror(errno
)));
913 free((char *)old_shares
);
919 SIVAL(buf
, 4, num_entries_copied
);
920 for( i
= 0; i
< num_entries_copied
; i
++)
922 char *p
= base
+ (i
*16);
924 SIVAL(p
,12,share_array
[i
].pid
);
925 SIVAL(p
,8,share_array
[i
].share_mode
);
926 SIVAL(p
,0,share_array
[i
].time
.tv_sec
);
927 SIVAL(p
,4,share_array
[i
].time
.tv_usec
);
930 newsize
= (base
- buf
) + (16*num_entries_copied
);
931 if(write(fd
, buf
, newsize
) != newsize
)
933 DEBUG(0,("ERROR: get_share_modes: failed to re-write share \
934 mode file %s (%s)\n", fname
, strerror(errno
)));
936 free((char *)old_shares
);
941 /* Now truncate the file at this point. */
942 if(ftruncate(fd
, newsize
)!= 0)
944 DEBUG(0,("ERROR: get_share_modes: failed to ftruncate share \
945 mode file %s to size %d (%s)\n", fname
, newsize
, strerror(errno
)));
947 free((char *)old_shares
);
957 DEBUG(5,("get_share_modes: Read share file %s returning %d entries\n",fname
,
958 num_entries_copied
));
960 return num_entries_copied
;
963 /*******************************************************************
964 del a share mode from a share mode file.
965 ********************************************************************/
966 void del_share_mode(share_lock_token token
, int fnum
)
975 files_struct
*fs_p
= &Files
[fnum
];
977 BOOL deleted
= False
;
980 share_name(fs_p
->cnum
, fs_p
->fd_ptr
->dev
,
981 fs_p
->fd_ptr
->inode
, fname
);
983 if(read_share_file( fs_p
->cnum
, fd
, fname
, &buf
, &new_file
) != 0)
985 DEBUG(0,("ERROR: del_share_mode: Failed to read share file %s\n",
992 DEBUG(0,("ERROR:del_share_mode: share file %s is new (size zero), deleting it.\n",
994 delete_share_file(fs_p
->cnum
, fname
);
998 num_entries
= IVAL(buf
,4);
1000 DEBUG(5,("del_share_mode: share file %s has %d share mode entries.\n",
1001 fname
, num_entries
));
1006 DEBUG(0,("PANIC ERROR:del_share_mode: num_share_mode_entries < 0 (%d) \
1007 for share file %d\n", num_entries
, fname
));
1011 if(num_entries
== 0)
1013 /* No entries - just delete the file. */
1014 DEBUG(0,("del_share_mode: share file %s has no share mode entries - deleting.\n",
1018 delete_share_file(fs_p
->cnum
, fname
);
1024 /* Go through the entries looking for the particular one
1025 we have set - delete it.
1028 base
= buf
+ 10 + SVAL(buf
,8);
1030 for(i
= 0; i
< num_entries
; i
++)
1032 char *p
= base
+ (i
*16);
1034 if((IVAL(p
,0) != fs_p
->open_time
.tv_sec
) || (IVAL(p
,4) != fs_p
->open_time
.tv_usec
) ||
1035 (IVAL(p
,8) != fs_p
->share_mode
) || (IVAL(p
,12) != pid
))
1038 DEBUG(5,("del_share_mode: deleting entry number %d (of %d) from the share file %s\n",
1039 i
, num_entries
, fname
));
1041 /* Remove this entry. */
1042 if(i
!= num_entries
- 1)
1043 memcpy(p
, p
+ 16, (num_entries
- i
- 1)*16);
1051 DEBUG(0,("del_share_mode: entry not found in share file %s\n", fname
));
1058 SIVAL(buf
,4, num_entries
);
1060 if(num_entries
== 0)
1062 /* Deleted the last entry - remove the file. */
1063 DEBUG(5,("del_share_mode: removed last entry in share file - deleting share file %s\n",
1067 delete_share_file(fs_p
->cnum
,fname
);
1071 /* Re-write the file - and truncate it at the correct point. */
1072 if(lseek(fd
, 0, SEEK_SET
) != 0)
1074 DEBUG(0,("ERROR: del_share_mode: lseek failed to reset to \
1075 position 0 for share mode file %s (%s)\n", fname
, strerror(errno
)));
1081 newsize
= (base
- buf
) + (16*num_entries
);
1082 if(write(fd
, buf
, newsize
) != newsize
)
1084 DEBUG(0,("ERROR: del_share_mode: failed to re-write share \
1085 mode file %s (%s)\n", fname
, strerror(errno
)));
1090 /* Now truncate the file at this point. */
1091 if(ftruncate(fd
, newsize
) != 0)
1093 DEBUG(0,("ERROR: del_share_mode: failed to ftruncate share \
1094 mode file %s to size %d (%s)\n", fname
, newsize
, strerror(errno
)));
1101 /*******************************************************************
1102 set the share mode of a file
1103 ********************************************************************/
1104 BOOL
set_share_mode(share_lock_token token
,int fnum
)
1106 files_struct
*fs_p
= &Files
[fnum
];
1108 int fd
= (int)token
;
1109 int pid
= (int)getpid();
1116 share_name(fs_p
->cnum
, fs_p
->fd_ptr
->dev
,
1117 fs_p
->fd_ptr
->inode
, fname
);
1119 if(fstat(fd
, &sb
) != 0)
1121 DEBUG(0,("ERROR: set_share_mode: Failed to do stat on share file %s\n",
1126 /* Sanity check for file contents (if it's not a new share file). */
1129 int size
= sb
.st_size
;
1131 /* Allocate space for the file plus one extra entry */
1132 if((buf
= (char *)malloc(sb
.st_size
+ 16)) == NULL
)
1134 DEBUG(0,("set_share_mode: malloc for file size %d fail !\n", sb
.st_size
+ 16));
1138 if(lseek(fd
, 0, SEEK_SET
) != 0)
1140 DEBUG(0,("ERROR: set_share_mode: Failed to reset position \
1141 to 0 for share file %s (%s)\n", fname
, strerror(errno
)));
1147 if (read(fd
,buf
,sb
.st_size
) != sb
.st_size
)
1149 DEBUG(0,("ERROR: set_share_mode: Failed to read share file %s (%s)\n",
1150 fname
, strerror(errno
)));
1156 if (IVAL(buf
,0) != LOCKING_VERSION
)
1158 DEBUG(0,("ERROR: set_share_mode: share file %s has incorrect \
1159 locking version (was %d, should be %d).\n",fname
, IVAL(buf
,0), LOCKING_VERSION
));
1162 delete_share_file(fs_p
->cnum
, fname
);
1166 size
-= (10 + SVAL(buf
, 8)); /* Remove the header */
1168 /* The remaining size must be a multiple of 16 - error if not. */
1169 if((size
% 16) != 0)
1171 DEBUG(0,("ERROR: set_share_mode: share file %s is an incorrect length - \
1172 deleting it.\n", fname
));
1175 delete_share_file(fs_p
->cnum
, fname
);
1182 /* New file - just use a single_entry. */
1183 if((buf
= (char *)malloc(10 + strlen(fs_p
->name
) + 1 + 16)) == NULL
)
1185 DEBUG(0,("ERROR: set_share_mode: malloc failed for single entry.\n"));
1188 SIVAL(buf
,0,LOCKING_VERSION
);
1190 SSVAL(buf
,8,strlen(fs_p
->name
) + 1);
1191 strcpy(buf
+ 10, fs_p
->name
);
1194 num_entries
= IVAL(buf
,4);
1195 header_size
= 10 + SVAL(buf
,8);
1196 p
= buf
+ header_size
+ (num_entries
* 16);
1197 SIVAL(p
,0,fs_p
->open_time
.tv_sec
);
1198 SIVAL(p
,4,fs_p
->open_time
.tv_usec
);
1199 SIVAL(p
,8,fs_p
->share_mode
);
1204 SIVAL(buf
,4,num_entries
);
1206 if(lseek(fd
, 0, SEEK_SET
) != 0)
1208 DEBUG(0,("ERROR: set_share_mode: (1) Failed to reset position to \
1209 0 for share file %s (%s)\n", fname
, strerror(errno
)));
1215 if (write(fd
,buf
,header_size
+ (num_entries
*16)) != (header_size
+ (num_entries
*16)))
1217 DEBUG(2,("ERROR: set_share_mode: Failed to write share file %s - \
1218 deleting it (%s).\n",fname
, strerror(errno
)));
1219 delete_share_file(fs_p
->cnum
, fname
);
1225 /* Now truncate the file at this point - just for safety. */
1226 if(ftruncate(fd
, header_size
+ (16*num_entries
))!= 0)
1228 DEBUG(0,("ERROR: set_share_mode: failed to ftruncate share \
1229 mode file %s to size %d (%s)\n", fname
, header_size
+ (16*num_entries
), strerror(errno
)));
1238 DEBUG(3,("set_share_mode: Created share file %s with \
1239 mode 0x%X pid=%d\n",fname
,fs_p
->share_mode
,pid
));
1243 #endif /* FAST_SHARE_MODES */