added two new options "max connections" and "lock file"
authorAndrew Tridgell <tridge@samba.org>
Wed, 13 May 1998 08:52:12 +0000 (08:52 +0000)
committerAndrew Tridgell <tridge@samba.org>
Wed, 13 May 1998 08:52:12 +0000 (08:52 +0000)
Makefile.in
clientserver.c
connection.c [new file with mode: 0644]
loadparm.c
util.c

index 4378515..a222a81 100644 (file)
@@ -23,7 +23,7 @@ SHELL=/bin/sh
 LIBOBJ=lib/getopt.o lib/fnmatch.o lib/zlib.o lib/compat.o
 OBJS1=rsync.o exclude.o util.o md4.o main.o checksum.o match.o syscall.o log.o
 OBJS2=options.o flist.o io.o compat.o hlink.o token.o uidlist.o socket.o 
-DAEMON_OBJ = params.o loadparm.o clientserver.o access.o
+DAEMON_OBJ = params.o loadparm.o clientserver.o access.o connection.o
 OBJS=$(OBJS1) $(OBJS2) $(DAEMON_OBJ) $(LIBOBJ)
 
 # note that the -I. is needed to handle config.h when using VPATH
index 32deee7..18d9494 100644 (file)
@@ -108,6 +108,11 @@ static int rsync_module(int fd, int i)
                return -1;
        }
 
+       if (!claim_connection(lp_lock_file(), lp_max_connections())) {
+               rprintf(FERROR,"ERROR: max connections reached\n");
+               return -1;
+       }
+
        rprintf(FINFO,"rsync on module %s from %s (%s)\n",
                lp_name(i), host, addr);
 
diff --git a/connection.c b/connection.c
new file mode 100644 (file)
index 0000000..fc7c666
--- /dev/null
@@ -0,0 +1,123 @@
+/* 
+   Copyright (C) Andrew Tridgell 1998
+   
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/* support the max connections option */
+#include "rsync.h"
+
+int yield_connection(char *fname, int max_connections)
+{
+       int fd, i;
+       pid_t mypid=getpid(), pid=0;
+
+       if (max_connections <= 0)
+               return 1;
+
+       fd = open(fname,O_RDWR);
+       if (fd == -1) {
+               rprintf(FERROR,"Couldn't open lock file %s (%s)\n",fname,strerror(errno));
+               return 0;
+       }
+
+       if (!lock_file(fd)) {
+               rprintf(FERROR,"failed to lock %s\n", fname);
+               close(fd);
+               return 0;
+       }
+
+       /* find the right spot */
+       for (i=0;i<max_connections;i++) {
+               if (read(fd, &pid, sizeof(pid)) != sizeof(pid)) {
+                       unlock_file(fd);
+                       close(fd);
+                       return 0;
+               }
+               if (pid == mypid) break;
+       }
+
+       if (i == max_connections) {
+               rprintf(FERROR,"Entry not found in lock file %s\n",fname);
+               unlock_file(fd);
+               close(fd);
+               return 0;
+       }
+
+       pid = 0;
+  
+       /* remove our mark */
+       if (lseek(fd,i*sizeof(pid),SEEK_SET) != i*sizeof(pid) ||
+           write(fd, &pid,sizeof(pid)) != sizeof(pid)) {
+               rprintf(FERROR,"Couldn't update lock file %s (%s)\n",fname,strerror(errno));
+               unlock_file(fd);
+               close(fd);
+               return 0;
+       }
+
+       unlock_file(fd);
+       close(fd);
+       return 1;
+}
+
+
+/****************************************************************************
+simple routine to do connection counting
+****************************************************************************/
+int claim_connection(char *fname,int max_connections)
+{
+       int fd, i;
+       pid_t pid;
+
+       if (max_connections <= 0)
+               return 1;
+       
+       fd = open(fname,O_RDWR|O_CREAT, 0600);
+
+       if (fd == -1) {
+               return 0;
+       }
+
+       if (!lock_file(fd)) {
+               rprintf(FERROR,"failed to lock %s\n", fname);
+               close(fd);
+               return 0;
+       }
+
+       /* find a free spot */
+       for (i=0;i<max_connections;i++) {
+               if (read(fd,&pid,sizeof(pid)) != sizeof(pid)) break;
+               if (pid == 0 || !process_exists(pid)) break;
+       }               
+
+       if (i == max_connections) {
+               unlock_file(fd);
+               close(fd);
+               return 0;
+       }
+
+       pid = getpid();
+
+       if (lseek(fd,i*sizeof(pid),SEEK_SET) != i*sizeof(pid) ||
+           write(fd, &pid,sizeof(pid)) != sizeof(pid)) {
+               unlock_file(fd);
+               close(fd);
+               return 0;
+       }
+
+       unlock_file(fd);
+       close(fd);
+       return 1;
+}
index 3afa9f4..da2e227 100644 (file)
@@ -98,7 +98,9 @@ static BOOL bLoaded = False;
 typedef struct
 {
        char *motd_file;
+       char *lock_file;
        int syslog_facility;
+       int max_connections;
 } global;
 
 static global Globals;
@@ -150,7 +152,9 @@ static BOOL bInGlobalSection = True;
 /* note that we do not initialise the defaults union - it is not allowed in ANSI C */
 static struct parm_struct parm_table[] =
 {
+  {"max connections",  P_INTEGER, P_GLOBAL, &Globals.max_connections,NULL, 0},
   {"motd file",        P_STRING,  P_GLOBAL, &Globals.motd_file,    NULL,   0},
+  {"lock file",        P_STRING,  P_GLOBAL, &Globals.lock_file,    NULL,   0},
   {"syslog facility",  P_INTEGER, P_GLOBAL, &Globals.syslog_facility, NULL,0},
   {"name",             P_STRING,  P_LOCAL,  &sDefault.name,        NULL,   0},
   {"comment",          P_STRING,  P_LOCAL,  &sDefault.comment,     NULL,   0},
@@ -173,6 +177,7 @@ static void init_globals(void)
 #ifdef LOG_DAEMON
        Globals.syslog_facility = LOG_DAEMON;
 #endif
+       Globals.lock_file = "/var/run/rsyncd.lock";
 }
 
 /***************************************************************************
@@ -208,6 +213,8 @@ static void init_locals(void)
 
 
 FN_GLOBAL_STRING(lp_motd_file, &Globals.motd_file)
+FN_GLOBAL_STRING(lp_lock_file, &Globals.lock_file)
+FN_GLOBAL_INTEGER(lp_max_connections, &Globals.max_connections)
 FN_GLOBAL_INTEGER(lp_syslog_facility, &Globals.syslog_facility)
 FN_LOCAL_STRING(lp_name, name)
 FN_LOCAL_STRING(lp_comment, comment)
diff --git a/util.c b/util.c
index 346d58a..bcbd8c1 100644 (file)
--- a/util.c
+++ b/util.c
@@ -483,3 +483,20 @@ int name_to_gid(char *name, gid_t *gid)
 }
 
 
+/****************************************************************************
+check if a process exists. 
+****************************************************************************/
+int process_exists(int pid)
+{
+       return(kill(pid,0) == 0 || errno != ESRCH);
+}
+
+int lock_file(int fd)
+{
+       return flock(fd, LOCK_EX) == 0;
+}
+
+int unlock_file(int fd)
+{
+       return flock(fd, LOCK_UN) == 0;
+}