coding standards issue: should never compare a boolean expression == False
[Samba.git] / source / locking / locking.c
blobe63e347a262ebbf2df46e9e09cf7ca62271cd26b
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 Locking functions
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.
21 Revision History:
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.
30 #include "includes.h"
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);
42 if (count == 0)
43 return(False);
45 if (!lp_locking(snum) || !lp_strict_locking(snum))
46 return(False);
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)
58 BOOL ok = False;
60 if (!lp_locking(SNUM(cnum)))
61 return(True);
63 if (count == 0) {
64 *eclass = ERRDOS;
65 *ecode = ERRnoaccess;
66 return False;
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));
73 if (!ok) {
74 *eclass = ERRDOS;
75 *ecode = ERRlock;
76 return False;
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)
87 BOOL ok = False;
89 if (!lp_locking(SNUM(cnum)))
90 return(True);
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);
95 if (!ok) {
96 *eclass = ERRDOS;
97 *ecode = ERRlock;
98 return False;
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;
157 int num_entries;
158 int num_entries_copied;
159 BOOL found = False;
160 min_share_mode_entry *share_array = (min_share_mode_entry *)0;
162 *old_shares = 0;
164 if(hash_entry > lp_shmem_hash_size() )
166 DEBUG(0,
167 ("PANIC ERROR : get_share_modes (FAST_SHARE_MODES): hash_entry %d too large \
168 (max = %d)\n",
169 hash_entry, lp_shmem_hash_size() ));
170 abort();
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));
178 return 0;
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) )
187 found = True;
188 break;
190 else
192 file_prev_p = file_scanner_p ;
193 file_scanner_p = (share_mode_record *)smb_shm_offset2addr(
194 file_scanner_p->next_offset);
198 if(!found)
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));
202 return (0);
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;
212 else
213 file_prev_p->next_offset = file_scanner_p->next_offset;
214 smb_shm_free(smb_shm_addr2offset(file_scanner_p));
215 return (0);
218 /* Allocate the old_shares array */
219 num_entries = file_scanner_p->num_share_mode_entries;
220 if(num_entries)
222 *old_shares = share_array = (min_share_mode_entry *)
223 malloc(num_entries * sizeof(min_share_mode_entry));
224 if(*old_shares == 0)
226 DEBUG(0,("get_share_modes (FAST_SHARE_MODES): malloc fail !\n"));
227 return 0;
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;
253 else
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;
262 /* PARANOIA TEST */
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));
268 abort();
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));
279 else
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));
303 if(*old_shares)
304 free((char *)old_shares);
305 *old_shares = 0;
307 if(file_prev_p == file_scanner_p)
308 mode_array[hash_entry] = file_scanner_p->next_offset;
309 else
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)
326 uint32 dev, inode;
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;
333 BOOL found = False;
334 int pid = getpid();
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() )
343 DEBUG(0,
344 ("PANIC ERROR:del_share_mode (FAST_SHARE_MODES): hash_entry %d too large \
345 (max = %d)\n",
346 hash_entry, lp_shmem_hash_size() ));
347 abort();
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",
355 hash_entry));
356 abort();
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) )
366 found = True;
367 break;
369 else
371 file_prev_p = file_scanner_p ;
372 file_scanner_p = (share_mode_record *)
373 smb_shm_offset2addr(file_scanner_p->next_offset);
377 if(!found)
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));
381 return;
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;
391 else
392 file_prev_p->next_offset = file_scanner_p->next_offset;
393 smb_shm_free(smb_shm_addr2offset(file_scanner_p));
394 return;
397 found = False;
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) )
407 found = True;
408 break;
410 else
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);
418 if (found)
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;
429 else
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));
433 /* PARANOIA TEST */
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));
439 abort();
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;
449 else
450 file_prev_p->next_offset = file_scanner_p->next_offset;
451 smb_shm_free(smb_shm_addr2offset(file_scanner_p));
454 else
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];
467 int32 dev, inode;
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;
474 BOOL found = False;
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() )
482 DEBUG(0,
483 ("PANIC ERROR:set_share_mode (FAST_SHARE_MODES): hash_entry %d too large \
484 (max = %d)\n",
485 hash_entry, lp_shmem_hash_size() ));
486 abort();
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) )
498 found = True;
499 break;
501 else
503 file_prev_p = file_scanner_p ;
504 file_scanner_p = (share_mode_record *)
505 smb_shm_offset2addr(file_scanner_p->next_offset);
509 if(!found)
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"));
518 return False;
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;
546 /* And delete it */
547 smb_shm_free( delete_offset );
548 return False;
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;
561 /* PARANOIA TEST */
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));
567 abort();
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));
577 return(True);
580 #else /* FAST_SHARE_MODES */
582 /* SHARE MODE LOCKS USING SLOW DESCRIPTION FILES */
584 /*******************************************************************
585 name a share file
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);
596 return(True);
599 /*******************************************************************
600 lock a share mode file.
601 ******************************************************************/
602 BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok)
604 pstring fname;
605 int fd;
607 *ptok = (share_lock_token)-1;
609 if(!share_name(cnum, dev, inode, fname))
610 return False;
613 int old_umask;
614 unbecome_user();
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 */
621 umask(old_umask);
622 if(!become_user(cnum,Connections[cnum].vuid))
624 DEBUG(0,("lock_share_entry: Can't become connected user!\n"));
625 close(fd);
626 return False;
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)));
633 close(fd);
634 return False;
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",
643 strerror(errno)));
644 close(fd);
645 return False;
648 *ptok = (share_lock_token)fd;
649 return True;
652 /*******************************************************************
653 unlock a share mode file.
654 ******************************************************************/
655 BOOL unlock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token token)
657 int fd = (int)token;
658 int ret = True;
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",
665 strerror(errno)));
666 ret = False;
669 close((int)token);
670 return ret;
673 /*******************************************************************
674 Force a share file to be deleted.
675 ********************************************************************/
677 static int delete_share_file( int cnum, char *fname )
679 unbecome_user();
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"));
691 return -1;
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)));
698 return -1;
700 return 0;
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)
709 struct stat sb;
710 char *buf;
711 int size;
713 *out = 0;
714 *p_new_file = False;
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)));
720 return -1;
723 if(sb.st_size == 0)
725 *p_new_file = True;
726 return 0;
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));
733 return -1;
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)));
740 if(buf)
741 free(buf);
742 return -1;
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)));
749 if(buf)
750 free(buf);
751 return -1;
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));
757 if(buf)
758 free(buf);
759 delete_share_file(cnum, fname);
760 return -1;
763 /* Sanity check for file contents */
764 size = sb.st_size;
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. */
771 if((size % 16) != 0)
773 DEBUG(0,("ERROR: read_share_file: share file %s is an incorrect length - \
774 deleting it.\n", fname));
775 if(buf)
776 free(buf);
777 delete_share_file(cnum, fname);
778 return -1;
781 *out = buf;
782 return 0;
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)
791 int fd = (int)token;
792 pstring fname;
793 int i;
794 int num_entries;
795 int num_entries_copied;
796 int newsize;
797 min_share_mode_entry *share_array;
798 char *buf = 0;
799 char *base = 0;
800 BOOL new_file;
802 *old_shares = 0;
804 /* Read the share file header - this is of the form:
805 0 - locking version.
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 :
812 0 - tv_sec
813 4 - tv_usec
814 8 - share_mode
815 12 - pid
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",
824 fname));
825 return 0;
828 if(new_file == True)
829 return 0;
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));
836 /* PARANOIA TEST */
837 if(num_entries < 0)
839 DEBUG(0,("PANIC ERROR:get_share_mode: num_share_mode_entries < 0 (%d) \
840 for share file %d\n", num_entries, fname));
841 abort();
844 if(num_entries)
846 *old_shares = share_array = (min_share_mode_entry *)
847 malloc(num_entries * sizeof(min_share_mode_entry));
848 if(*old_shares == 0)
850 DEBUG(0,("get_share_modes: malloc fail !\n"));
851 return 0;
854 else
856 /* No entries - just delete the file. */
857 DEBUG(0,("get_share_modes: share file %s has no share mode entries - deleting.\n",
858 fname));
859 if(buf)
860 free(buf);
861 delete_share_file(cnum, fname);
862 return 0;
865 num_entries_copied = 0;
866 base = buf + 10 + SVAL(buf,8);
868 for( i = 0; i < num_entries; i++)
870 int pid;
871 char *p = base + (i*16);
873 pid = IVAL(p,12);
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));
880 continue;
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",
894 fname));
895 if(*old_shares)
896 free((char *)old_shares);
897 if(buf)
898 free(buf);
899 delete_share_file(cnum, fname);
900 return 0;
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)));
912 if(*old_shares)
913 free((char *)old_shares);
914 if(buf)
915 free(buf);
916 return 0;
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)));
935 if(*old_shares)
936 free((char *)old_shares);
937 if(buf)
938 free(buf);
939 return 0;
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)));
946 if(*old_shares)
947 free((char *)old_shares);
948 if(buf)
949 free(buf);
950 return 0;
954 if(buf)
955 free(buf);
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)
968 pstring fname;
969 int fd = (int)token;
970 char *buf = 0;
971 char *base = 0;
972 int num_entries;
973 int newsize;
974 int i;
975 files_struct *fs_p = &Files[fnum];
976 int pid;
977 BOOL deleted = False;
978 BOOL new_file;
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",
986 fname));
987 return;
990 if(new_file == True)
992 DEBUG(0,("ERROR:del_share_mode: share file %s is new (size zero), deleting it.\n",
993 fname));
994 delete_share_file(fs_p->cnum, fname);
995 return;
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));
1003 /* PARANOIA TEST */
1004 if(num_entries < 0)
1006 DEBUG(0,("PANIC ERROR:del_share_mode: num_share_mode_entries < 0 (%d) \
1007 for share file %d\n", num_entries, fname));
1008 abort();
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",
1015 fname));
1016 if(buf)
1017 free(buf);
1018 delete_share_file(fs_p->cnum, fname);
1019 return;
1022 pid = getpid();
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))
1036 continue;
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);
1045 deleted = True;
1046 break;
1049 if(!deleted)
1051 DEBUG(0,("del_share_mode: entry not found in share file %s\n", fname));
1052 if(buf)
1053 free(buf);
1054 return;
1057 num_entries--;
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",
1064 fname));
1065 if(buf)
1066 free(buf);
1067 delete_share_file(fs_p->cnum,fname);
1068 return;
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)));
1076 if(buf)
1077 free(buf);
1078 return;
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)));
1086 if(buf)
1087 free(buf);
1088 return;
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)));
1095 if(buf)
1096 free(buf);
1097 return;
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];
1107 pstring fname;
1108 int fd = (int)token;
1109 int pid = (int)getpid();
1110 struct stat sb;
1111 char *buf;
1112 int num_entries;
1113 int header_size;
1114 char *p;
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",
1122 fname));
1123 return False;
1126 /* Sanity check for file contents (if it's not a new share file). */
1127 if(sb.st_size != 0)
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));
1135 return False;
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)));
1142 if(buf)
1143 free(buf);
1144 return False;
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)));
1151 if(buf)
1152 free(buf);
1153 return False;
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));
1160 if(buf)
1161 free(buf);
1162 delete_share_file(fs_p->cnum, fname);
1163 return False;
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));
1173 if(buf)
1174 free(buf);
1175 delete_share_file(fs_p->cnum, fname);
1176 return False;
1180 else
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"));
1186 return False;
1188 SIVAL(buf,0,LOCKING_VERSION);
1189 SIVAL(buf,4,0);
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);
1200 SIVAL(p,12,pid);
1202 num_entries++;
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)));
1210 if(buf)
1211 free(buf);
1212 return False;
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);
1220 if(buf)
1221 free(buf);
1222 return False;
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)));
1230 if(buf)
1231 free(buf);
1232 return False;
1235 if(buf)
1236 free(buf);
1238 DEBUG(3,("set_share_mode: Created share file %s with \
1239 mode 0x%X pid=%d\n",fname,fs_p->share_mode,pid));
1241 return True;
1243 #endif /* FAST_SHARE_MODES */