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,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,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,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 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)
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,&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,&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(!shm_lock()) return (0);
196 scanner_p = (share_mode_record *)shm_offset2addr(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 *)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 shm_set_userdef_off(scanner_p->next_offset);
224 prev_p->next_offset = scanner_p->next_offset;
225 shm_free(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 shm_set_userdef_off(scanner_p->next_offset);
246 prev_p->next_offset = scanner_p->next_offset;
247 shm_free(shm_addr2offset(scanner_p));
251 DEBUG(5,("Read share mode record mode 0x%X pid=%d\n",ret,*pid));
253 if(!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,16) != 16) {
282 if (IVAL(buf,12) != LOCKING_VERSION) {
283 if (!unlink(fname)) DEBUG(2,("Deleted old locking file %s",fname));
288 if (*pid && !process_exists(*pid)) {
293 if (! *pid) unlink(fname); /* XXXXX race, race */
296 DEBUG(5,("Read share file %s mode 0x%X pid=%d\n",fname,ret,*pid));
303 /*******************************************************************
304 del the share mode of a file, if we set it last
305 ********************************************************************/
306 void del_share_mode(int fnum)
313 share_mode_record *scanner_p;
314 share_mode_record *prev_p;
319 if (fstat(Files[fnum].fd,&st) != 0) return;
321 if (!shm_lock()) return;
323 scanner_p = (share_mode_record *)shm_offset2addr(shm_get_userdef_off());
327 if( (scanner_p->st_dev == st.st_dev) && (scanner_p->st_ino == st.st_ino) )
335 scanner_p = (share_mode_record *)shm_offset2addr(scanner_p->next_offset);
346 pid = scanner_p->pid;
348 if( (scanner_p->locking_version != LOCKING_VERSION) || !pid || !process_exists(pid))
351 if (!del && t == Files[fnum].open_time && pid==(int)getpid())
356 DEBUG(2,("Deleting share mode record\n"));
357 if(prev_p == scanner_p)
358 shm_set_userdef_off(scanner_p->next_offset);
360 prev_p->next_offset = scanner_p->next_offset;
361 shm_free(shm_addr2offset(scanner_p));
376 if (!share_name_fnum(fnum,fname)) return;
378 fd2 = open(fname,O_RDONLY,0);
380 if (read(fd2,buf,16) != 16)
390 if (IVAL(buf,12) != LOCKING_VERSION || !pid || !process_exists(pid))
393 if (!del && t == Files[fnum].open_time && pid==(int)getpid())
398 DEBUG(2,("Deleted share file %s\n",fname));
400 DEBUG(3,("Pending delete share file %s\n",fname));
401 if (*share_del_pending) DEBUG(0,("Share del clash!\n"));
402 strcpy(share_del_pending,fname);
409 /*******************************************************************
410 set the share mode of a file
411 ********************************************************************/
412 BOOL set_share_mode(int fnum,int mode)
415 int pid = (int)getpid();
417 shm_offset_t new_off;
418 share_mode_record *new_p;
421 if (fstat(Files[fnum].fd,&st) != 0) return(False);
423 if (!shm_lock()) return (False);
424 new_off = shm_alloc(sizeof(share_mode_record) + strlen(Files[fnum].name) );
425 if (new_off == NULL_OFFSET) return (False);
426 new_p = (share_mode_record *)shm_offset2addr(new_off);
427 new_p->locking_version = LOCKING_VERSION;
428 new_p->share_mode = mode;
429 new_p->time = Files[fnum].open_time;
431 new_p->st_dev = st.st_dev;
432 new_p->st_ino = st.st_ino;
433 strcpy(new_p->file_name,Files[fnum].name);
434 new_p->next_offset = shm_get_userdef_off();
435 shm_set_userdef_off(new_off);
438 DEBUG(3,("Created share record for %s with mode 0x%X pid=%d\n",Files[fnum].name,mode,pid));
440 if (!shm_unlock()) return (False);
447 int pid = (int)getpid();
449 if (!share_name_fnum(fnum,fname)) return(False);
452 int old_umask = umask(0);
453 fd2 = open(fname,O_WRONLY|O_CREAT|O_TRUNC,0644);
457 DEBUG(2,("Failed to create share file %s\n",fname));
461 SIVAL(buf,0,Files[fnum].open_time);
464 SIVAL(buf,12,LOCKING_VERSION);
466 if (write(fd2,buf,16) != 16) {
472 write(fd2,Files[fnum].name,strlen(Files[fnum].name)+1);
476 DEBUG(3,("Created share file %s with mode 0x%X pid=%d\n",fname,mode,pid));
483 /*******************************************************************
484 cleanup any stale share files
485 ********************************************************************/
486 void clean_share_modes(void)
489 share_mode_record *scanner_p;
490 share_mode_record *prev_p;
493 if (!shm_lock()) return;
495 scanner_p = (share_mode_record *)shm_offset2addr(shm_get_userdef_off());
499 pid = scanner_p->pid;
501 if( (scanner_p->locking_version != LOCKING_VERSION) || !process_exists(pid))
503 DEBUG(2,("Deleting stale share mode record"));
504 if(prev_p == scanner_p)
506 shm_set_userdef_off(scanner_p->next_offset);
507 shm_free(shm_addr2offset(scanner_p));
508 scanner_p = (share_mode_record *)shm_offset2addr(shm_get_userdef_off());
513 prev_p->next_offset = scanner_p->next_offset;
514 shm_free(shm_addr2offset(scanner_p));
515 scanner_p = (share_mode_record *)shm_offset2addr(prev_p->next_offset);
522 scanner_p = (share_mode_record *)shm_offset2addr(scanner_p->next_offset);
531 char *lockdir = lp_lockdir();
535 if (!*lockdir) return;
537 dir = opendir(lockdir);
540 while ((s=readdirname(dir))) {
547 if (sscanf(s,"share.%d.%d",&dev,&inode)!=2) continue;
549 strcpy(lname,lp_lockdir());
550 trim_string(lname,NULL,"/");
554 fd = open(lname,O_RDONLY,0);
555 if (fd < 0) continue;
557 if (read(fd,buf,16) != 16) {
560 printf("Deleted corrupt share file %s\n",s);
567 if (IVAL(buf,12) != LOCKING_VERSION || !process_exists(pid)) {
569 printf("Deleted stale share file %s\n",s);