this is the bug change to using connection_struct* instead of cnum.
[Samba/gbeck.git] / source / smbd / connection.c
blob342a5f43bc8898cf573fd974d51e8dcb00a9d1cd
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 connection claim routines
5 Copyright (C) Andrew Tridgell 1998
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.
22 #include "includes.h"
25 extern fstring remote_machine;
27 extern int DEBUGLEVEL;
29 /****************************************************************************
30 simple routines to do connection counting
31 ****************************************************************************/
32 BOOL yield_connection(connection_struct *conn,char *name,int max_connections)
34 struct connect_record crec;
35 pstring fname;
36 int fd;
37 int mypid = getpid();
38 int i;
40 DEBUG(3,("Yielding connection to %s\n",name));
42 if (max_connections <= 0)
43 return(True);
45 bzero(&crec,sizeof(crec));
47 pstrcpy(fname,lp_lockdir());
48 trim_string(fname,"","/");
50 pstrcat(fname,"/");
51 pstrcat(fname,name);
52 pstrcat(fname,".LCK");
54 fd = open(fname,O_RDWR);
55 if (fd == -1) {
56 DEBUG(2,("Couldn't open lock file %s (%s)\n",fname,strerror(errno)));
57 return(False);
60 if (fcntl_lock(fd,F_SETLKW,0,1,F_WRLCK)==False) {
61 DEBUG(0,("ERROR: can't get lock on %s\n", fname));
62 return False;
65 /* find the right spot */
66 for (i=0;i<max_connections;i++) {
67 if (read(fd, &crec,sizeof(crec)) != sizeof(crec)) {
68 DEBUG(2,("Entry not found in lock file %s\n",fname));
69 if (fcntl_lock(fd,F_SETLKW,0,1,F_UNLCK)==False) {
70 DEBUG(0,("ERROR: can't release lock on %s\n", fname));
72 close(fd);
73 return(False);
75 if (crec.pid == mypid && crec.cnum == conn->cnum)
76 break;
79 if (crec.pid != mypid || crec.cnum != conn->cnum) {
80 if (fcntl_lock(fd,F_SETLKW,0,1,F_UNLCK)==False) {
81 DEBUG(0,("ERROR: can't release lock on %s\n", fname));
83 close(fd);
84 DEBUG(2,("Entry not found in lock file %s\n",fname));
85 return(False);
88 bzero((void *)&crec,sizeof(crec));
90 /* remove our mark */
91 if (lseek(fd,i*sizeof(crec),SEEK_SET) != i*sizeof(crec) ||
92 write(fd, &crec,sizeof(crec)) != sizeof(crec)) {
93 DEBUG(2,("Couldn't update lock file %s (%s)\n",fname,strerror(errno)));
94 if (fcntl_lock(fd,F_SETLKW,0,1,F_UNLCK)==False) {
95 DEBUG(0,("ERROR: can't release lock on %s\n", fname));
97 close(fd);
98 return(False);
101 if (fcntl_lock(fd,F_SETLKW,0,1,F_UNLCK)==False) {
102 DEBUG(0,("ERROR: can't release lock on %s\n", fname));
105 DEBUG(3,("Yield successful\n"));
107 close(fd);
108 return(True);
112 /****************************************************************************
113 simple routines to do connection counting
114 ****************************************************************************/
115 BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOOL Clear)
117 extern int Client;
118 struct connect_record crec;
119 pstring fname;
120 int fd=-1;
121 int i,foundi= -1;
122 int total_recs;
124 if (max_connections <= 0)
125 return(True);
127 DEBUG(5,("trying claim %s %s %d\n",lp_lockdir(),name,max_connections));
129 pstrcpy(fname,lp_lockdir());
130 trim_string(fname,"","/");
132 if (!directory_exist(fname,NULL))
133 mkdir(fname,0755);
135 pstrcat(fname,"/");
136 pstrcat(fname,name);
137 pstrcat(fname,".LCK");
139 if (!file_exist(fname,NULL)) {
140 fd = open(fname,O_RDWR|O_CREAT|O_EXCL, 0644);
143 if (fd == -1) {
144 fd = open(fname,O_RDWR);
147 if (fd == -1) {
148 DEBUG(1,("couldn't open lock file %s\n",fname));
149 return(False);
152 if (fcntl_lock(fd,F_SETLKW,0,1,F_WRLCK)==False) {
153 DEBUG(0,("ERROR: can't get lock on %s\n", fname));
154 return False;
157 total_recs = file_size(fname) / sizeof(crec);
159 /* find a free spot */
160 for (i=0;i<max_connections;i++) {
161 if (i>=total_recs ||
162 lseek(fd,i*sizeof(crec),SEEK_SET) != i*sizeof(crec) ||
163 read(fd,&crec,sizeof(crec)) != sizeof(crec)) {
164 if (foundi < 0) foundi = i;
165 break;
168 if (Clear && crec.pid && !process_exists(crec.pid)) {
169 lseek(fd,i*sizeof(crec),SEEK_SET);
170 bzero((void *)&crec,sizeof(crec));
171 write(fd, &crec,sizeof(crec));
172 if (foundi < 0) foundi = i;
173 continue;
175 if (foundi < 0 && (!crec.pid || !process_exists(crec.pid))) {
176 foundi=i;
177 if (!Clear) break;
181 if (foundi < 0) {
182 DEBUG(3,("no free locks in %s\n",fname));
183 if (fcntl_lock(fd,F_SETLKW,0,1,F_UNLCK)==False) {
184 DEBUG(0,("ERROR: can't release lock on %s\n", fname));
186 close(fd);
187 return(False);
190 /* fill in the crec */
191 bzero((void *)&crec,sizeof(crec));
192 crec.magic = 0x280267;
193 crec.pid = getpid();
194 if (conn) {
195 crec.cnum = conn->cnum;
196 crec.uid = conn->uid;
197 crec.gid = conn->gid;
198 StrnCpy(crec.name,
199 lp_servicename(SNUM(conn)),sizeof(crec.name)-1);
200 } else {
201 crec.cnum = -1;
203 crec.start = time(NULL);
205 StrnCpy(crec.machine,remote_machine,sizeof(crec.machine)-1);
206 StrnCpy(crec.addr,client_addr(Client),sizeof(crec.addr)-1);
208 /* make our mark */
209 if (lseek(fd,foundi*sizeof(crec),SEEK_SET) != foundi*sizeof(crec) ||
210 write(fd, &crec,sizeof(crec)) != sizeof(crec)) {
211 if (fcntl_lock(fd,F_SETLKW,0,1,F_UNLCK)==False) {
212 DEBUG(0,("ERROR: can't release lock on %s\n", fname));
214 close(fd);
215 return(False);
218 if (fcntl_lock(fd,F_SETLKW,0,1,F_UNLCK)==False) {
219 DEBUG(0,("ERROR: can't release lock on %s\n", fname));
222 close(fd);
223 return(True);