added two new options "max connections" and "lock file"
[rsync/rsync.git] / connection.c
1 /* 
2    Copyright (C) Andrew Tridgell 1998
3    
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 2 of the License, or
7    (at your option) any later version.
8    
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13    
14    You should have received a copy of the GNU General Public License
15    along with this program; if not, write to the Free Software
16    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 */
18
19 /* support the max connections option */
20 #include "rsync.h"
21
22 int yield_connection(char *fname, int max_connections)
23 {
24         int fd, i;
25         pid_t mypid=getpid(), pid=0;
26
27         if (max_connections <= 0)
28                 return 1;
29
30         fd = open(fname,O_RDWR);
31         if (fd == -1) {
32                 rprintf(FERROR,"Couldn't open lock file %s (%s)\n",fname,strerror(errno));
33                 return 0;
34         }
35
36         if (!lock_file(fd)) {
37                 rprintf(FERROR,"failed to lock %s\n", fname);
38                 close(fd);
39                 return 0;
40         }
41
42         /* find the right spot */
43         for (i=0;i<max_connections;i++) {
44                 if (read(fd, &pid, sizeof(pid)) != sizeof(pid)) {
45                         unlock_file(fd);
46                         close(fd);
47                         return 0;
48                 }
49                 if (pid == mypid) break;
50         }
51
52         if (i == max_connections) {
53                 rprintf(FERROR,"Entry not found in lock file %s\n",fname);
54                 unlock_file(fd);
55                 close(fd);
56                 return 0;
57         }
58
59         pid = 0;
60   
61         /* remove our mark */
62         if (lseek(fd,i*sizeof(pid),SEEK_SET) != i*sizeof(pid) ||
63             write(fd, &pid,sizeof(pid)) != sizeof(pid)) {
64                 rprintf(FERROR,"Couldn't update lock file %s (%s)\n",fname,strerror(errno));
65                 unlock_file(fd);
66                 close(fd);
67                 return 0;
68         }
69
70         unlock_file(fd);
71         close(fd);
72         return 1;
73 }
74
75
76 /****************************************************************************
77 simple routine to do connection counting
78 ****************************************************************************/
79 int claim_connection(char *fname,int max_connections)
80 {
81         int fd, i;
82         pid_t pid;
83
84         if (max_connections <= 0)
85                 return 1;
86         
87         fd = open(fname,O_RDWR|O_CREAT, 0600);
88
89         if (fd == -1) {
90                 return 0;
91         }
92
93         if (!lock_file(fd)) {
94                 rprintf(FERROR,"failed to lock %s\n", fname);
95                 close(fd);
96                 return 0;
97         }
98
99         /* find a free spot */
100         for (i=0;i<max_connections;i++) {
101                 if (read(fd,&pid,sizeof(pid)) != sizeof(pid)) break;
102                 if (pid == 0 || !process_exists(pid)) break;
103         }               
104
105         if (i == max_connections) {
106                 unlock_file(fd);
107                 close(fd);
108                 return 0;
109         }
110
111         pid = getpid();
112
113         if (lseek(fd,i*sizeof(pid),SEEK_SET) != i*sizeof(pid) ||
114             write(fd, &pid,sizeof(pid)) != sizeof(pid)) {
115                 unlock_file(fd);
116                 close(fd);
117                 return 0;
118         }
119
120         unlock_file(fd);
121         close(fd);
122         return 1;
123 }