2 Unix SMB/Netbios implementation.
5 Copyright (C) Andrew Tridgell 1992-1995
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.
24 extern int DEBUGLEVEL;
25 extern connection_struct Connections[];
26 extern files_struct Files[];
28 pstring share_del_pending="";
31 /****************************************************************************
32 routine to do file locking
33 ****************************************************************************/
34 BOOL fcntl_lock(int fd,int op,uint32 offset,uint32 count,int type)
41 uint32 mask = 0xC0000000;
43 /* make sure the count is reasonable, we might kill the lockd otherwise */
46 /* the offset is often strange - remove 2 of its bits if either of
47 the top two bits are set. Shift the top ones by two bits. This
48 still allows OLE2 apps to operate, but should stop lockd from
50 if ((offset & mask) != 0)
51 offset = (offset & ~mask) | ((offset & mask) >> 2);
53 unsigned long mask = ((unsigned)1<<31);
55 /* interpret negative counts as large numbers */
59 /* no negative offsets */
62 /* count + offset must be in range */
63 while ((offset < 0 || (offset + count < 0)) && mask)
71 DEBUG(5,("fcntl_lock %d %d %d %d %d\n",fd,op,(int)offset,(int)count,type));
74 lock.l_whence = SEEK_SET;
75 lock.l_start = (int)offset;
76 lock.l_len = (int)count;
81 ret = fcntl(fd,op,&lock);
84 DEBUG(3,("fcntl lock gave errno %d (%s)\n",errno,strerror(errno)));
90 (lock.l_type != F_UNLCK) &&
92 (lock.l_pid != getpid()))
94 DEBUG(3,("fd %d is locked by pid %d\n",fd,lock.l_pid));
98 /* it must be not locked or locked by me */
102 /* a lock set or unset */
105 DEBUG(3,("lock failed at offset %d count %d op %d type %d (%s)\n",
106 offset,count,op,type,strerror(errno)));
108 /* perhaps it doesn't support this sort of locking?? */
111 DEBUG(3,("locking not supported? returning True\n"));
118 /* everything went OK */
119 DEBUG(5,("Lock call successful\n"));
127 /*******************************************************************
128 lock a file - returning a open file descriptor or -1 on failure
129 The timeout is in seconds. 0 means no timeout
130 ********************************************************************/
131 int file_lock(char *name,int timeout)
133 int fd = open(name,O_RDWR|O_CREAT,0666);
135 if (fd < 0) return(-1);
138 if (timeout) t = time(NULL);
139 while (!timeout || (time(NULL)-t < timeout)) {
140 if (fcntl_lock(fd,F_SETLK,0,1,F_WRLCK)) return(fd);
141 msleep(LOCK_RETRY_TIMEOUT);
149 /*******************************************************************
150 unlock a file locked by file_lock
151 ********************************************************************/
152 void file_unlock(int fd)
156 fcntl_lock(fd,F_SETLK,0,1,F_UNLCK);
162 /****************************************************************************
163 utility function called to see if a file region is locked
164 ****************************************************************************/
165 BOOL is_locked(int fnum,int cnum,uint32 count,uint32 offset)
167 int snum = SNUM(cnum);
172 if (!lp_locking(snum) || !lp_strict_locking(snum))
175 return(fcntl_lock(Files[fnum].fd,F_GETLK,offset,count,
176 (Files[fnum].can_write?F_WRLCK:F_RDLCK)));
180 /****************************************************************************
181 utility function called by locking requests
182 ****************************************************************************/
183 BOOL do_lock(int fnum,int cnum,uint32 count,uint32 offset,int *eclass,uint32 *ecode)
187 if (!lp_locking(SNUM(cnum)))
192 *ecode = ERRnoaccess;
196 if (Files[fnum].can_lock && OPEN_FNUM(fnum) && (Files[fnum].cnum == cnum))
197 ok = fcntl_lock(Files[fnum].fd,F_SETLK,offset,count,
198 (Files[fnum].can_write?F_WRLCK:F_RDLCK));
205 return True; /* Got lock */
209 /****************************************************************************
210 utility function called by unlocking requests
211 ****************************************************************************/
212 BOOL do_unlock(int fnum,int cnum,uint32 count,uint32 offset,int *eclass,uint32 *ecode)
216 if (!lp_locking(SNUM(cnum)))
219 if (Files[fnum].can_lock && OPEN_FNUM(fnum) && (Files[fnum].cnum == cnum))
220 ok = fcntl_lock(Files[fnum].fd,F_SETLK,offset,count,F_UNLCK);
227 return True; /* Did unlock */
230 /*******************************************************************
232 ******************************************************************/
233 static BOOL share_name(int cnum,struct stat *st,char *name)
235 strcpy(name,lp_lockdir());
236 standard_sub(cnum,name);
237 trim_string(name,"","/");
238 if (!*name) return(False);
239 name += strlen(name);
241 sprintf(name,"/share.%d.%d",(int)st->st_dev,(int)st->st_ino);
245 /*******************************************************************
246 use the fnum to get the share file name
247 ******************************************************************/
248 static BOOL share_name_fnum(int fnum,char *name)
251 if (fstat(Files[fnum].fd,&st) != 0) return(False);
252 return(share_name(Files[fnum].cnum,&st,name));
256 /*******************************************************************
257 get the share mode of a file using the fnum
258 ******************************************************************/
259 int get_share_mode_by_fnum(int cnum,int fnum,int *pid)
262 if (fstat(Files[fnum].fd,&sbuf) == -1) return(0);
263 return(get_share_mode(cnum,&sbuf,pid));
266 /*******************************************************************
267 get the share mode of a file using the files name
268 ******************************************************************/
269 int get_share_mode_byname(int cnum,char *fname,int *pid)
272 if (stat(fname,&sbuf) == -1) return(0);
273 return(get_share_mode(cnum,&sbuf,pid));
277 /*******************************************************************
278 get the share mode of a file
279 ********************************************************************/
280 int get_share_mode(int cnum,struct stat *sbuf,int *pid)
290 if (!share_name(cnum,sbuf,fname)) return(0);
292 fd2 = open(fname,O_RDONLY,0);
293 if (fd2 < 0) return(0);
295 if (read(fd2,buf,16) != 16) {
306 if (IVAL(buf,12) != LOCKING_VERSION) {
307 if (!unlink(fname)) DEBUG(2,("Deleted old locking file %s",fname));
312 if (*pid && !process_exists(*pid)) {
317 if (! *pid) unlink(fname); /* XXXXX race, race */
320 DEBUG(5,("Read share file %s mode 0x%X pid=%d\n",fname,ret,*pid));
326 /*******************************************************************
327 del the share mode of a file, if we set it last
328 ********************************************************************/
329 void del_share_mode(int fnum)
338 if (!share_name_fnum(fnum,fname)) return;
340 fd2 = open(fname,O_RDONLY,0);
342 if (read(fd2,buf,16) != 16)
352 if (IVAL(buf,12) != LOCKING_VERSION || !pid || !process_exists(pid))
355 if (!del && t == Files[fnum].open_time && pid==(int)getpid())
360 DEBUG(2,("Deleted share file %s\n",fname));
362 DEBUG(3,("Pending delete share file %s\n",fname));
363 if (*share_del_pending) DEBUG(0,("Share del clash!\n"));
364 strcpy(share_del_pending,fname);
370 /*******************************************************************
371 set the share mode of a file
372 ********************************************************************/
373 BOOL set_share_mode(int fnum,int mode)
378 int pid = (int)getpid();
380 if (!share_name_fnum(fnum,fname)) return(False);
383 int old_umask = umask(0);
384 fd2 = open(fname,O_WRONLY|O_CREAT|O_TRUNC,0644);
388 DEBUG(2,("Failed to create share file %s\n",fname));
392 SIVAL(buf,0,Files[fnum].open_time);
395 SIVAL(buf,12,LOCKING_VERSION);
397 if (write(fd2,buf,16) != 16) {
403 write(fd2,Files[fnum].name,strlen(Files[fnum].name)+1);
407 DEBUG(3,("Created share file %s with mode 0x%X pid=%d\n",fname,mode,pid));
413 /*******************************************************************
414 cleanup any stale share files
415 ********************************************************************/
416 void clean_share_files(void)
418 char *lockdir = lp_lockdir();
422 if (!*lockdir) return;
424 dir = opendir(lockdir);
427 while ((s=readdirname(dir))) {
434 if (sscanf(s,"share.%d.%d",&dev,&inode)!=2) continue;
436 strcpy(lname,lp_lockdir());
437 trim_string(lname,NULL,"/");
441 fd = open(lname,O_RDONLY,0);
442 if (fd < 0) continue;
444 if (read(fd,buf,16) != 16) {
447 printf("Deleted corrupt share file %s\n",s);
454 if (IVAL(buf,12) != LOCKING_VERSION || !process_exists(pid)) {
456 printf("Deleted stale share file %s\n",s);