2 Unix SMB/Netbios implementation.
5 Copyright (C) Andrew Tridgell 1992-1996
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
28 extern int DEBUGLEVEL
;
29 extern connection_struct Connections
[];
30 extern files_struct Files
[];
32 pstring share_del_pending
="";
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 */
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
, 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();
131 /* SHARE MODE LOCKS USING SLOW DESCRIPTION FILES */
133 /*******************************************************************
135 ******************************************************************/
136 static BOOL
share_name(int cnum
,struct stat
*st
,char *name
)
138 strcpy(name
,lp_lockdir());
139 standard_sub(cnum
,name
);
140 trim_string(name
,"","/");
141 if (!*name
) return(False
);
142 name
+= strlen(name
);
144 sprintf(name
,"/share.%d.%d",(int)st
->st_dev
,(int)st
->st_ino
);
148 /*******************************************************************
149 use the fnum to get the share file name
150 ******************************************************************/
151 static BOOL
share_name_fnum(int fnum
,char *name
)
154 if (fstat(Files
[fnum
].fd_ptr
->fd
,&st
) != 0) return(False
);
155 return(share_name(Files
[fnum
].cnum
,&st
,name
));
160 /*******************************************************************
161 get the share mode of a file using the fnum
162 ******************************************************************/
163 int get_share_mode_by_fnum(int cnum
,int fnum
,int *pid
)
166 if (fstat(Files
[fnum
].fd_ptr
->fd
,&sbuf
) == -1) return(0);
167 return(get_share_mode(cnum
,&sbuf
,pid
));
170 /*******************************************************************
171 get the share mode of a file using the files name
172 ******************************************************************/
173 int get_share_mode_byname(int cnum
,char *fname
,int *pid
)
176 if (stat(fname
,&sbuf
) == -1) return(0);
177 return(get_share_mode(cnum
,&sbuf
,pid
));
181 /*******************************************************************
182 get the share mode of a file
183 ********************************************************************/
184 int get_share_mode(int cnum
,struct stat
*sbuf
,int *pid
)
187 share_mode_record
*scanner_p
;
188 share_mode_record
*prev_p
;
194 if(!smb_shm_lock()) return (0);
196 scanner_p
= (share_mode_record
*)smb_shm_offset2addr(smb_shm_get_userdef_off());
200 if( (scanner_p
->st_dev
== sbuf
->st_dev
) && (scanner_p
->st_ino
== sbuf
->st_ino
) )
208 scanner_p
= (share_mode_record
*)smb_shm_offset2addr(scanner_p
->next_offset
);
218 if(scanner_p
->locking_version
!= LOCKING_VERSION
)
220 DEBUG(2,("Deleting old share mode record due to old locking version %d",scanner_p
->locking_version
));
221 if(prev_p
== scanner_p
)
222 smb_shm_set_userdef_off(scanner_p
->next_offset
);
224 prev_p
->next_offset
= scanner_p
->next_offset
;
225 smb_shm_free(smb_shm_addr2offset(scanner_p
));
232 *pid
= scanner_p
->pid
;
233 ret
= scanner_p
->share_mode
;
235 if (*pid
&& !process_exists(*pid
))
243 if(prev_p
== scanner_p
)
244 smb_shm_set_userdef_off(scanner_p
->next_offset
);
246 prev_p
->next_offset
= scanner_p
->next_offset
;
247 smb_shm_free(smb_shm_addr2offset(scanner_p
));
251 DEBUG(5,("Read share mode record mode 0x%X pid=%d\n",ret
,*pid
));
253 if(!smb_shm_unlock()) return (0);
266 if (!share_name(cnum
,sbuf
,fname
)) return(0);
268 fd2
= open(fname
,O_RDONLY
,0);
269 if (fd2
< 0) return(0);
271 if (read(fd2
,buf
,20) != 20) {
272 DEBUG(2,("Failed to read share file %s\n",fname
));
279 t
.tv_sec
= IVAL(buf
,4);
280 t
.tv_usec
= IVAL(buf
,8);
284 if (IVAL(buf
,0) != LOCKING_VERSION
) {
285 if (!unlink(fname
)) DEBUG(2,("Deleted old locking file %s",fname
));
290 if (*pid
&& !process_exists(*pid
)) {
295 if (! *pid
) unlink(fname
); /* XXXXX race, race */
298 DEBUG(5,("Read share file %s mode 0x%X pid=%d\n",fname
,ret
,*pid
));
305 /*******************************************************************
306 del the share mode of a file, if we set it last
307 ********************************************************************/
308 void del_share_mode(int fnum
)
315 share_mode_record
*scanner_p
;
316 share_mode_record
*prev_p
;
319 t
.tv_sec
= t
.tv_usec
= 0;
321 if (fstat(Files
[fnum
].fd_ptr
->fd
,&st
) != 0) return;
323 if (!smb_shm_lock()) return;
325 scanner_p
= (share_mode_record
*)smb_shm_offset2addr(smb_shm_get_userdef_off());
329 if( (scanner_p
->st_dev
== st
.st_dev
) && (scanner_p
->st_ino
== st
.st_ino
) )
337 scanner_p
= (share_mode_record
*)smb_shm_offset2addr(scanner_p
->next_offset
);
347 t
.tv_sec
= scanner_p
->time
.tv_sec
;
348 t
.tv_usec
= scanner_p
->time
.tv_usec
;
349 pid
= scanner_p
->pid
;
351 if( (scanner_p
->locking_version
!= LOCKING_VERSION
) || !pid
|| !process_exists(pid
))
354 if (!del
&& (memcmp(&t
,&Files
[fnum
].open_time
,sizeof(t
)) == 0)
355 && pid
==(int)getpid())
360 DEBUG(2,("Deleting share mode record\n"));
361 if(prev_p
== scanner_p
)
362 smb_shm_set_userdef_off(scanner_p
->next_offset
);
364 prev_p
->next_offset
= scanner_p
->next_offset
;
365 smb_shm_free(smb_shm_addr2offset(scanner_p
));
380 t
.tv_sec
= t
.tv_usec
= 0;
381 if (!share_name_fnum(fnum
,fname
)) return;
383 fd2
= open(fname
,O_RDONLY
,0);
385 if (read(fd2
,buf
,20) != 20)
390 t
.tv_sec
= IVAL(buf
,4);
391 t
.tv_usec
= IVAL(buf
,8);
396 if (IVAL(buf
,0) != LOCKING_VERSION
|| !pid
|| !process_exists(pid
))
399 if (!del
&& (memcmp(&t
,&Files
[fnum
].open_time
,sizeof(t
)) == 0) && (pid
==(int)getpid()))
404 DEBUG(2,("Deleted share file %s\n",fname
));
406 DEBUG(3,("Pending delete share file %s\n",fname
));
407 if (*share_del_pending
) DEBUG(0,("Share del clash!\n"));
408 strcpy(share_del_pending
,fname
);
415 /*******************************************************************
416 set the share mode of a file
417 ********************************************************************/
418 BOOL
set_share_mode(int fnum
,int mode
)
421 int pid
= (int)getpid();
423 smb_shm_offset_t new_off
;
424 share_mode_record
*new_p
;
427 if (fstat(Files
[fnum
].fd_ptr
->fd
,&st
) != 0) return(False
);
429 if (!smb_shm_lock()) return (False
);
430 new_off
= smb_shm_alloc(sizeof(share_mode_record
) + strlen(Files
[fnum
].name
) );
431 if (new_off
== NULL_OFFSET
) return (False
);
432 new_p
= (share_mode_record
*)smb_shm_offset2addr(new_off
);
433 new_p
->locking_version
= LOCKING_VERSION
;
434 new_p
->share_mode
= mode
;
435 new_p
->time
.tv_sec
= Files
[fnum
].open_time
.tv_sec
;
436 new_p
->time
.tv_usec
= Files
[fnum
].open_time
.tv_usec
;
438 new_p
->st_dev
= st
.st_dev
;
439 new_p
->st_ino
= st
.st_ino
;
440 strcpy(new_p
->file_name
,Files
[fnum
].name
);
441 new_p
->next_offset
= smb_shm_get_userdef_off();
442 smb_shm_set_userdef_off(new_off
);
445 DEBUG(3,("Created share record for %s with mode 0x%X pid=%d\n",Files
[fnum
].name
,mode
,pid
));
447 if (!smb_shm_unlock()) return (False
);
454 int pid
= (int)getpid();
456 if (!share_name_fnum(fnum
,fname
)) return(False
);
459 int old_umask
= umask(0);
460 fd2
= open(fname
,O_WRONLY
|O_CREAT
|O_TRUNC
,0644);
464 DEBUG(2,("Failed to create share file %s\n",fname
));
468 SIVAL(buf
,0,LOCKING_VERSION
);
469 SIVAL(buf
,4,Files
[fnum
].open_time
.tv_sec
);
470 SIVAL(buf
,8,Files
[fnum
].open_time
.tv_usec
);
474 if (write(fd2
,buf
,20) != 20) {
475 DEBUG(2,("Failed to write share file %s\n",fname
));
481 write(fd2
,Files
[fnum
].name
,strlen(Files
[fnum
].name
)+1);
485 DEBUG(3,("Created share file %s with mode 0x%X pid=%d\n",fname
,mode
,pid
));
492 /*******************************************************************
493 cleanup any stale share files
494 ********************************************************************/
495 void clean_share_modes(void)
498 share_mode_record
*scanner_p
;
499 share_mode_record
*prev_p
;
502 if (!smb_shm_lock()) return;
504 scanner_p
= (share_mode_record
*)smb_shm_offset2addr(smb_shm_get_userdef_off());
508 pid
= scanner_p
->pid
;
510 if( (scanner_p
->locking_version
!= LOCKING_VERSION
) || !process_exists(pid
))
512 DEBUG(2,("Deleting stale share mode record"));
513 if(prev_p
== scanner_p
)
515 smb_shm_set_userdef_off(scanner_p
->next_offset
);
516 smb_shm_free(smb_shm_addr2offset(scanner_p
));
517 scanner_p
= (share_mode_record
*)smb_shm_offset2addr(smb_shm_get_userdef_off());
522 prev_p
->next_offset
= scanner_p
->next_offset
;
523 smb_shm_free(smb_shm_addr2offset(scanner_p
));
524 scanner_p
= (share_mode_record
*)smb_shm_offset2addr(prev_p
->next_offset
);
531 scanner_p
= (share_mode_record
*)smb_shm_offset2addr(scanner_p
->next_offset
);
540 char *lockdir
= lp_lockdir();
544 if (!*lockdir
) return;
546 dir
= opendir(lockdir
);
549 while ((s
=readdirname(dir
))) {
556 if (sscanf(s
,"share.%d.%d",&dev
,&inode
)!=2) continue;
558 strcpy(lname
,lp_lockdir());
559 trim_string(lname
,NULL
,"/");
563 fd
= open(lname
,O_RDONLY
,0);
564 if (fd
< 0) continue;
566 if (read(fd
,buf
,20) != 20) {
569 printf("Deleted corrupt share file %s\n",s
);
576 if (IVAL(buf
,0) != LOCKING_VERSION
|| !process_exists(pid
)) {
578 printf("Deleted stale share file %s\n",s
);