mirror of
https://github.com/RsyncProject/rsync.git
synced 2026-02-07 05:31:01 -05:00
first vesrion of working socket based rsync. It still needs a lot of
work, but at least it works :-)
This commit is contained in:
@@ -21,8 +21,9 @@ SHELL=/bin/sh
|
||||
.SUFFIXES: .c .o
|
||||
|
||||
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
|
||||
OBJS=$(OBJS1) flist.o io.o compat.o hlink.o token.o uidlist.o socket.o $(LIBOBJ)
|
||||
OBJS1=rsync.o exclude.o util.o md4.o main.o checksum.o match.o syscall.o log.o
|
||||
DAEMON_OBJ = params.o loadparm.o
|
||||
OBJS=$(OBJS1) $(DAEMON_OBJ) flist.o io.o compat.o hlink.o token.o uidlist.o socket.o $(LIBOBJ)
|
||||
|
||||
# note that the -I. is needed to handle config.h when using VPATH
|
||||
.c.o:
|
||||
|
||||
@@ -42,7 +42,7 @@ AC_FUNC_MMAP
|
||||
AC_FUNC_UTIME_NULL
|
||||
AC_CHECK_FUNCS(waitpid strtok pipe getcwd mkdir strdup strerror chown chmod mknod)
|
||||
AC_CHECK_FUNCS(fchmod fstat strchr bcopy bzero readlink link utime utimes)
|
||||
AC_CHECK_FUNCS(memmove getopt_long lchown setlinebuf vsnprintf)
|
||||
AC_CHECK_FUNCS(memmove getopt_long lchown setlinebuf vsnprintf setsid)
|
||||
|
||||
echo $ac_n "checking for working fnmatch... $ac_c"
|
||||
AC_TRY_RUN([#include <fnmatch.h>
|
||||
|
||||
48
io.c
48
io.c
@@ -423,10 +423,16 @@ void write_buf(int f,char *buf,int len)
|
||||
total_written += len;
|
||||
}
|
||||
|
||||
/* write a string to the connection */
|
||||
void write_sbuf(int f,char *buf)
|
||||
{
|
||||
write_buf(f, buf, strlen(buf));
|
||||
}
|
||||
|
||||
|
||||
void write_byte(int f,unsigned char c)
|
||||
{
|
||||
write_buf(f,(char *)&c,1);
|
||||
write_buf(f,(char *)&c,1);
|
||||
}
|
||||
|
||||
void write_flush(int f)
|
||||
@@ -434,3 +440,43 @@ void write_flush(int f)
|
||||
}
|
||||
|
||||
|
||||
int read_line(int f, char *buf, int maxlen)
|
||||
{
|
||||
while (maxlen) {
|
||||
read_buf(f, buf, 1);
|
||||
if (buf[0] == '\n') {
|
||||
buf[0] = 0;
|
||||
break;
|
||||
}
|
||||
if (buf[0] != '\r') {
|
||||
buf++;
|
||||
maxlen--;
|
||||
}
|
||||
}
|
||||
if (maxlen == 0) {
|
||||
*buf = 0;
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void io_printf(int fd, const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char buf[1024];
|
||||
int len;
|
||||
|
||||
va_start(ap, format);
|
||||
|
||||
#if HAVE_VSNPRINTF
|
||||
len = vsnprintf(buf, sizeof(buf)-1, format, ap);
|
||||
#else
|
||||
len = vsprintf(buf, format, ap);
|
||||
#endif
|
||||
va_end(ap);
|
||||
|
||||
if (len < 0) exit_cleanup(1);
|
||||
|
||||
write_sbuf(fd, buf);
|
||||
}
|
||||
|
||||
249
main.c
249
main.c
@@ -21,7 +21,7 @@
|
||||
|
||||
int verbose = 0;
|
||||
int always_checksum = 0;
|
||||
time_t starttime;
|
||||
time_t starttime = 0;
|
||||
int64 total_size = 0;
|
||||
int block_size=BLOCK_SIZE;
|
||||
|
||||
@@ -57,6 +57,9 @@ int numeric_ids = 0;
|
||||
int force_delete = 0;
|
||||
int io_timeout = 0;
|
||||
int io_error = 0;
|
||||
int read_only = 0;
|
||||
static int module_id;
|
||||
|
||||
static int port = RSYNC_PORT;
|
||||
|
||||
static char *shell_cmd;
|
||||
@@ -64,9 +67,9 @@ static char *shell_cmd;
|
||||
extern int csum_length;
|
||||
|
||||
int am_server = 0;
|
||||
int am_sender;
|
||||
int am_sender=0;
|
||||
int recurse = 0;
|
||||
int am_daemon;
|
||||
int am_daemon=0;
|
||||
|
||||
static void usage(int fd);
|
||||
|
||||
@@ -335,12 +338,24 @@ static void do_server_sender(int f_in, int f_out, int argc,char *argv[])
|
||||
argv[i] += l+1;
|
||||
}
|
||||
|
||||
if (am_daemon) {
|
||||
char *name = lp_name(module_id);
|
||||
int l = strlen(name);
|
||||
for (i=0;i<argc;i++) {
|
||||
if (strncmp(argv[i], name, l) == 0) {
|
||||
argv[i] += l;
|
||||
if (!*argv[i]) argv[i] = ".";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (argc == 0 && recurse) {
|
||||
argc=1;
|
||||
argv--;
|
||||
argv[0] = ".";
|
||||
}
|
||||
|
||||
|
||||
rprintf(FINFO,"sending file list\n");
|
||||
|
||||
flist = send_file_list(f_out,argc,argv);
|
||||
send_files(flist,f_out,f_in);
|
||||
@@ -389,11 +404,23 @@ static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"server_recv(%d) starting pid=%d\n",argc,(int)getpid());
|
||||
|
||||
if (am_daemon) {
|
||||
char *name = lp_name(module_id);
|
||||
int i, l = strlen(name);
|
||||
for (i=0;i<argc;i++) {
|
||||
if (strncmp(argv[i], name, l) == 0) {
|
||||
argv[i] += l;
|
||||
if (!*argv[i]) argv[i] = ".";
|
||||
}
|
||||
rprintf(FINFO,"argv[%d]=%s\n", i, argv[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (argc > 0) {
|
||||
dir = argv[0];
|
||||
argc--;
|
||||
argv++;
|
||||
if (chdir(dir) != 0) {
|
||||
if (!am_daemon && chdir(dir) != 0) {
|
||||
rprintf(FERROR,"chdir %s : %s (4)\n",
|
||||
dir,strerror(errno));
|
||||
exit_cleanup(1);
|
||||
@@ -487,13 +514,15 @@ static int client_run(int f_in, int f_out, int pid, int argc, char *argv[])
|
||||
|
||||
int start_socket_client(char *host, char *path, int argc, char *argv[])
|
||||
{
|
||||
int fd;
|
||||
char *sargs[100];
|
||||
int fd, i;
|
||||
char *sargs[MAX_ARGS];
|
||||
int sargc=0;
|
||||
|
||||
char line[1024];
|
||||
char *p;
|
||||
int version;
|
||||
|
||||
fd = open_socket_out(host, port);
|
||||
if (fd == -1) {
|
||||
rprintf(FERROR,"failed to connect to %s - %s\n", host, strerror(errno));
|
||||
exit_cleanup(1);
|
||||
}
|
||||
|
||||
@@ -506,6 +535,41 @@ int start_socket_client(char *host, char *path, int argc, char *argv[])
|
||||
|
||||
sargs[sargc] = NULL;
|
||||
|
||||
p = strchr(path,'/');
|
||||
if (p) *p = 0;
|
||||
io_printf(fd,"%s\n",path);
|
||||
if (p) *p = '/';
|
||||
|
||||
if (!read_line(fd, line, sizeof(line)-1)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sscanf(line,"RSYNCD %d", &version) != 1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
if (!read_line(fd, line, sizeof(line)-1)) {
|
||||
return -1;
|
||||
}
|
||||
if (strcmp(line,"RSYNCD: OK") == 0) break;
|
||||
rprintf(FINFO,"%s\n", line);
|
||||
}
|
||||
|
||||
for (i=0;i<sargc;i++) {
|
||||
io_printf(fd,"%s\n", sargs[i]);
|
||||
}
|
||||
io_printf(fd,"\n");
|
||||
|
||||
#if 0
|
||||
while (1) {
|
||||
if (!read_line(fd, line, sizeof(line)-1)) {
|
||||
return -1;
|
||||
}
|
||||
rprintf(FINFO,"%s\n", line);
|
||||
}
|
||||
#endif
|
||||
|
||||
return client_run(fd, fd, -1, argc, argv);
|
||||
}
|
||||
|
||||
@@ -874,6 +938,161 @@ static void parse_arguments(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
static int rsync_module(int fd, int i)
|
||||
{
|
||||
int argc=0;
|
||||
char *argv[MAX_ARGS];
|
||||
char **argp;
|
||||
char line[1024];
|
||||
|
||||
module_id = i;
|
||||
|
||||
if (lp_read_only(i))
|
||||
read_only = 1;
|
||||
|
||||
rprintf(FERROR,"rsyncd starting\n");
|
||||
|
||||
if (chroot(lp_path(i))) {
|
||||
io_printf(fd,"ERROR: chroot failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (chdir("/")) {
|
||||
io_printf(fd,"ERROR: chdir failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (setgid(lp_gid(i))) {
|
||||
io_printf(fd,"ERROR: setgid failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (setuid(lp_uid(i))) {
|
||||
io_printf(fd,"ERROR: setuid failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
io_printf(fd,"RSYNCD: OK\n");
|
||||
|
||||
argv[argc++] = "rsyncd";
|
||||
|
||||
while (1) {
|
||||
if (!read_line(fd, line, sizeof(line)-1)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!*line) break;
|
||||
|
||||
argv[argc] = strdup(line);
|
||||
if (!argv[argc]) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
argc++;
|
||||
if (argc == MAX_ARGS) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
parse_arguments(argc, argv);
|
||||
|
||||
/* don't allow the logs to be flooded too fast */
|
||||
if (verbose > 1) verbose = 1;
|
||||
|
||||
argc -= optind;
|
||||
argp = argv + optind;
|
||||
optind = 0;
|
||||
|
||||
start_server(fd, fd, argc, argp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void send_listing(int fd)
|
||||
{
|
||||
int n = lp_numservices();
|
||||
int i;
|
||||
|
||||
for (i=0;i<n;i++)
|
||||
if (lp_list(i))
|
||||
io_printf(fd, "%-15s\t%s\n", lp_name(i), lp_comment(i));
|
||||
}
|
||||
|
||||
/* this is called when a socket connection is established to a client
|
||||
and we want to start talking. The setup of the system is done from
|
||||
here */
|
||||
static int start_daemon(int fd)
|
||||
{
|
||||
char line[1024];
|
||||
char *motd;
|
||||
|
||||
set_socket_options(fd,"SO_KEEPALIVE");
|
||||
|
||||
io_printf(fd,"RSYNCD %d\n", PROTOCOL_VERSION);
|
||||
|
||||
motd = lp_motd_file();
|
||||
if (*motd) {
|
||||
FILE *f = fopen(motd,"r");
|
||||
while (f && !feof(f)) {
|
||||
int len = fread(line, 1, sizeof(line)-1, f);
|
||||
if (len > 0) {
|
||||
line[len] = 0;
|
||||
io_printf(fd,"%s", line);
|
||||
}
|
||||
}
|
||||
if (f) fclose(f);
|
||||
io_printf(fd,"\n");
|
||||
}
|
||||
|
||||
/* read a single line indicating the resource that is wanted */
|
||||
while (1) {
|
||||
int i;
|
||||
|
||||
line[0] = 0;
|
||||
if (!read_line(fd, line, sizeof(line)-1)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!*line || strcmp(line,"#list")==0) {
|
||||
send_listing(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (*line == '#') {
|
||||
/* it's some sort of command that I don't understand */
|
||||
io_printf(fd,"ERROR: Unknown command '%s'\n", line);
|
||||
return -1;
|
||||
}
|
||||
|
||||
i = lp_number(line);
|
||||
if (i == -1) {
|
||||
io_printf(fd,"ERROR: Unknown module '%s'\n", line);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return rsync_module(fd, i);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int daemon_main(void)
|
||||
{
|
||||
if (!lp_load(RSYNCD_CONF)) {
|
||||
exit_cleanup(1);
|
||||
}
|
||||
|
||||
if (is_a_socket(STDIN_FILENO)) {
|
||||
/* we are running via inetd */
|
||||
return start_daemon(STDIN_FILENO);
|
||||
}
|
||||
|
||||
become_daemon();
|
||||
|
||||
return start_accept_loop(port, start_daemon);
|
||||
}
|
||||
|
||||
int main(int argc,char *argv[])
|
||||
{
|
||||
|
||||
@@ -888,17 +1107,19 @@ int main(int argc,char *argv[])
|
||||
|
||||
parse_arguments(argc, argv);
|
||||
|
||||
while (optind) {
|
||||
argc--;
|
||||
argv++;
|
||||
optind--;
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
optind = 0;
|
||||
|
||||
signal(SIGCHLD,SIG_IGN);
|
||||
signal(SIGINT,SIGNAL_CAST sig_int);
|
||||
signal(SIGPIPE,SIGNAL_CAST sig_int);
|
||||
signal(SIGHUP,SIGNAL_CAST sig_int);
|
||||
|
||||
if (am_daemon) {
|
||||
return daemon_main();
|
||||
}
|
||||
|
||||
if (dry_run)
|
||||
verbose = MAX(verbose,1);
|
||||
|
||||
|
||||
35
mkproto.awk
35
mkproto.awk
@@ -19,6 +19,41 @@ BEGIN {
|
||||
}
|
||||
}
|
||||
|
||||
/^FN_LOCAL_BOOL/ {
|
||||
split($0,a,"[,()]")
|
||||
printf "BOOL %s(int );\n", a[2]
|
||||
}
|
||||
|
||||
/^FN_LOCAL_STRING/ {
|
||||
split($0,a,"[,()]")
|
||||
printf "char *%s(int );\n", a[2]
|
||||
}
|
||||
|
||||
/^FN_LOCAL_INT/ {
|
||||
split($0,a,"[,()]")
|
||||
printf "int %s(int );\n", a[2]
|
||||
}
|
||||
|
||||
/^FN_LOCAL_CHAR/ {
|
||||
split($0,a,"[,()]")
|
||||
printf "char %s(int );\n", a[2]
|
||||
}
|
||||
|
||||
/^FN_GLOBAL_BOOL/ {
|
||||
split($0,a,"[,()]")
|
||||
printf "BOOL %s(void);\n", a[2]
|
||||
}
|
||||
|
||||
/^FN_GLOBAL_STRING/ {
|
||||
split($0,a,"[,()]")
|
||||
printf "char *%s(void);\n", a[2]
|
||||
}
|
||||
|
||||
/^FN_GLOBAL_INT/ {
|
||||
split($0,a,"[,()]")
|
||||
printf "int %s(void);\n", a[2]
|
||||
}
|
||||
|
||||
/^static|^extern/ || !/^[a-zA-Z]/ || /[;]/ {
|
||||
next;
|
||||
}
|
||||
|
||||
10
rsync.h
10
rsync.h
@@ -21,6 +21,9 @@
|
||||
#define RSYNC_RSH_ENV "RSYNC_RSH"
|
||||
|
||||
#define RSYNC_NAME "rsync"
|
||||
#define RSYNCD_CONF "/etc/rsyncd.conf"
|
||||
#define RSYNCD_LOG "/var/adm/rsyncd.log"
|
||||
|
||||
#define BACKUP_SUFFIX "~"
|
||||
|
||||
/* a non-zero CHAR_OFFSET makes the rolling sum stronger, but is
|
||||
@@ -50,6 +53,8 @@
|
||||
#define CHUNK_SIZE (32*1024)
|
||||
#define MAX_MAP_SIZE (4*1024*1024)
|
||||
|
||||
#define MAX_ARGS 100
|
||||
|
||||
#define BLOCKING_TIMEOUT 10
|
||||
|
||||
#define FERROR 1
|
||||
@@ -170,6 +175,9 @@
|
||||
#include <grp.h>
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#ifndef S_IFLNK
|
||||
#define S_IFLNK 0120000
|
||||
@@ -179,6 +187,8 @@
|
||||
#define S_ISLNK(mode) (((mode) & S_IFLNK) == S_IFLNK)
|
||||
#endif
|
||||
|
||||
#define BOOL int
|
||||
|
||||
#ifndef uchar
|
||||
#define uchar unsigned char
|
||||
#endif
|
||||
|
||||
272
socket.c
272
socket.c
@@ -21,7 +21,277 @@
|
||||
|
||||
*/
|
||||
|
||||
#include "rsync.h"
|
||||
|
||||
/* open a socket to a tcp remote host with the specified port
|
||||
based on code from Warren */
|
||||
int open_socket_out(char *host, int port)
|
||||
{
|
||||
return -1;
|
||||
int type = SOCK_STREAM;
|
||||
struct sockaddr_in sock_out;
|
||||
int res;
|
||||
struct hostent *hp;
|
||||
|
||||
|
||||
res = socket(PF_INET, type, 0);
|
||||
if (res == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
hp = gethostbyname(host);
|
||||
if (!hp) {
|
||||
rprintf(FERROR,"unknown host: %s\n", host);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(&sock_out.sin_addr, hp->h_addr, hp->h_length);
|
||||
sock_out.sin_port = htons(port);
|
||||
sock_out.sin_family = PF_INET;
|
||||
|
||||
if (connect(res,(struct sockaddr *)&sock_out,sizeof(sock_out))) {
|
||||
close(res);
|
||||
rprintf(FERROR,"failed to connect to %s - %s\n", host, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
open a socket of the specified type, port and address for incoming data
|
||||
****************************************************************************/
|
||||
static int open_socket_in(int type, int port)
|
||||
{
|
||||
struct hostent *hp;
|
||||
struct sockaddr_in sock;
|
||||
char host_name[200];
|
||||
int res;
|
||||
int one=1;
|
||||
|
||||
/* get my host name */
|
||||
if (gethostname(host_name, sizeof(host_name)) == -1) {
|
||||
rprintf(FERROR,"gethostname failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* get host info */
|
||||
if ((hp = gethostbyname(host_name)) == 0) {
|
||||
rprintf(FERROR,"gethostbyname: Unknown host %s\n",host_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
bzero((char *)&sock,sizeof(sock));
|
||||
memcpy((char *)&sock.sin_addr,(char *)hp->h_addr, hp->h_length);
|
||||
sock.sin_port = htons(port);
|
||||
sock.sin_family = hp->h_addrtype;
|
||||
sock.sin_addr.s_addr = INADDR_ANY;
|
||||
res = socket(hp->h_addrtype, type, 0);
|
||||
if (res == -1) {
|
||||
rprintf(FERROR,"socket failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
setsockopt(res,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one));
|
||||
|
||||
/* now we've got a socket - we need to bind it */
|
||||
if (bind(res, (struct sockaddr * ) &sock,sizeof(sock)) == -1) {
|
||||
rprintf(FERROR,"bind failed on port %d\n", port);
|
||||
close(res);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
determine if a file descriptor is in fact a socket
|
||||
****************************************************************************/
|
||||
int is_a_socket(int fd)
|
||||
{
|
||||
int v,l;
|
||||
l = sizeof(int);
|
||||
return(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&v, &l) == 0);
|
||||
}
|
||||
|
||||
|
||||
int start_accept_loop(int port, int (*fn)(int ))
|
||||
{
|
||||
int s;
|
||||
|
||||
signal(SIGCLD, SIG_IGN);
|
||||
|
||||
/* open an incoming socket */
|
||||
s = open_socket_in(SOCK_STREAM, port);
|
||||
if (s == -1)
|
||||
return(-1);
|
||||
|
||||
/* ready to listen */
|
||||
if (listen(s, 5) == -1) {
|
||||
close(s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* now accept incoming connections - forking a new process
|
||||
for each incoming connection */
|
||||
while (1) {
|
||||
fd_set fds;
|
||||
int fd;
|
||||
struct sockaddr addr;
|
||||
int in_addrlen = sizeof(addr);
|
||||
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(s, &fds);
|
||||
|
||||
if (select(s+1, &fds, NULL, NULL, NULL) != 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!FD_ISSET(s, &fds)) continue;
|
||||
|
||||
fd = accept(s,&addr,&in_addrlen);
|
||||
|
||||
if (fd == -1) continue;
|
||||
|
||||
if (fork()==0) {
|
||||
close(s);
|
||||
|
||||
_exit(fn(fd));
|
||||
}
|
||||
|
||||
close(fd);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
enum SOCK_OPT_TYPES {OPT_BOOL,OPT_INT,OPT_ON};
|
||||
|
||||
struct
|
||||
{
|
||||
char *name;
|
||||
int level;
|
||||
int option;
|
||||
int value;
|
||||
int opttype;
|
||||
} socket_options[] = {
|
||||
{"SO_KEEPALIVE", SOL_SOCKET, SO_KEEPALIVE, 0, OPT_BOOL},
|
||||
{"SO_REUSEADDR", SOL_SOCKET, SO_REUSEADDR, 0, OPT_BOOL},
|
||||
{"SO_BROADCAST", SOL_SOCKET, SO_BROADCAST, 0, OPT_BOOL},
|
||||
#ifdef TCP_NODELAY
|
||||
{"TCP_NODELAY", IPPROTO_TCP, TCP_NODELAY, 0, OPT_BOOL},
|
||||
#endif
|
||||
#ifdef IPTOS_LOWDELAY
|
||||
{"IPTOS_LOWDELAY", IPPROTO_IP, IP_TOS, IPTOS_LOWDELAY, OPT_ON},
|
||||
#endif
|
||||
#ifdef IPTOS_THROUGHPUT
|
||||
{"IPTOS_THROUGHPUT", IPPROTO_IP, IP_TOS, IPTOS_THROUGHPUT, OPT_ON},
|
||||
#endif
|
||||
#ifdef SO_SNDBUF
|
||||
{"SO_SNDBUF", SOL_SOCKET, SO_SNDBUF, 0, OPT_INT},
|
||||
#endif
|
||||
#ifdef SO_RCVBUF
|
||||
{"SO_RCVBUF", SOL_SOCKET, SO_RCVBUF, 0, OPT_INT},
|
||||
#endif
|
||||
#ifdef SO_SNDLOWAT
|
||||
{"SO_SNDLOWAT", SOL_SOCKET, SO_SNDLOWAT, 0, OPT_INT},
|
||||
#endif
|
||||
#ifdef SO_RCVLOWAT
|
||||
{"SO_RCVLOWAT", SOL_SOCKET, SO_RCVLOWAT, 0, OPT_INT},
|
||||
#endif
|
||||
#ifdef SO_SNDTIMEO
|
||||
{"SO_SNDTIMEO", SOL_SOCKET, SO_SNDTIMEO, 0, OPT_INT},
|
||||
#endif
|
||||
#ifdef SO_RCVTIMEO
|
||||
{"SO_RCVTIMEO", SOL_SOCKET, SO_RCVTIMEO, 0, OPT_INT},
|
||||
#endif
|
||||
{NULL,0,0,0,0}};
|
||||
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
set user socket options
|
||||
****************************************************************************/
|
||||
void set_socket_options(int fd, char *options)
|
||||
{
|
||||
char *tok;
|
||||
options = strdup(options);
|
||||
|
||||
if (!options) out_of_memory("set_socket_options");
|
||||
|
||||
for (tok=strtok(options, " \t,"); tok; tok=strtok(NULL," \t,")) {
|
||||
int ret=0,i;
|
||||
int value = 1;
|
||||
char *p;
|
||||
int got_value = 0;
|
||||
|
||||
if ((p = strchr(tok,'='))) {
|
||||
*p = 0;
|
||||
value = atoi(p+1);
|
||||
got_value = 1;
|
||||
}
|
||||
|
||||
for (i=0;socket_options[i].name;i++)
|
||||
if (strcmp(socket_options[i].name,tok)==0)
|
||||
break;
|
||||
|
||||
if (!socket_options[i].name) {
|
||||
rprintf(FERROR,"Unknown socket option %s\n",tok);
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (socket_options[i].opttype) {
|
||||
case OPT_BOOL:
|
||||
case OPT_INT:
|
||||
ret = setsockopt(fd,socket_options[i].level,
|
||||
socket_options[i].option,(char *)&value,sizeof(int));
|
||||
break;
|
||||
|
||||
case OPT_ON:
|
||||
if (got_value)
|
||||
rprintf(FERROR,"syntax error - %s does not take a value\n",tok);
|
||||
|
||||
{
|
||||
int on = socket_options[i].value;
|
||||
ret = setsockopt(fd,socket_options[i].level,
|
||||
socket_options[i].option,(char *)&on,sizeof(int));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret != 0)
|
||||
rprintf(FERROR,"Failed to set socket option %s\n",tok);
|
||||
}
|
||||
|
||||
free(options);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
become a daemon, discarding the controlling terminal
|
||||
****************************************************************************/
|
||||
void become_daemon(void)
|
||||
{
|
||||
if (fork())
|
||||
_exit(0);
|
||||
|
||||
/* detach from the terminal */
|
||||
#ifdef HAVE_SETSID
|
||||
setsid();
|
||||
#else
|
||||
#ifdef TIOCNOTTY
|
||||
{
|
||||
int i = open("/dev/tty", O_RDWR);
|
||||
if (i >= 0)
|
||||
{
|
||||
ioctl(i, (int) TIOCNOTTY, (char *)0);
|
||||
close(i);
|
||||
}
|
||||
}
|
||||
#endif /* TIOCNOTTY */
|
||||
#endif
|
||||
close(0);
|
||||
close(1);
|
||||
close(2);
|
||||
}
|
||||
|
||||
14
syscall.c
14
syscall.c
@@ -23,16 +23,21 @@
|
||||
#include "rsync.h"
|
||||
|
||||
extern int dry_run;
|
||||
extern int read_only;
|
||||
|
||||
#define CHECK_RO if (read_only) {errno = EROFS; return -1;}
|
||||
|
||||
int do_unlink(char *fname)
|
||||
{
|
||||
if (dry_run) return 0;
|
||||
CHECK_RO
|
||||
return unlink(fname);
|
||||
}
|
||||
|
||||
int do_symlink(char *fname1, char *fname2)
|
||||
{
|
||||
if (dry_run) return 0;
|
||||
CHECK_RO
|
||||
return symlink(fname1, fname2);
|
||||
}
|
||||
|
||||
@@ -40,6 +45,7 @@ int do_symlink(char *fname1, char *fname2)
|
||||
int do_link(char *fname1, char *fname2)
|
||||
{
|
||||
if (dry_run) return 0;
|
||||
CHECK_RO
|
||||
return link(fname1, fname2);
|
||||
}
|
||||
#endif
|
||||
@@ -47,6 +53,7 @@ int do_link(char *fname1, char *fname2)
|
||||
int do_lchown(const char *path, uid_t owner, gid_t group)
|
||||
{
|
||||
if (dry_run) return 0;
|
||||
CHECK_RO
|
||||
return lchown(path, owner, group);
|
||||
}
|
||||
|
||||
@@ -54,6 +61,7 @@ int do_lchown(const char *path, uid_t owner, gid_t group)
|
||||
int do_mknod(char *pathname, mode_t mode, dev_t dev)
|
||||
{
|
||||
if (dry_run) return 0;
|
||||
CHECK_RO
|
||||
return mknod(pathname, mode, dev);
|
||||
}
|
||||
#endif
|
||||
@@ -61,12 +69,14 @@ int do_mknod(char *pathname, mode_t mode, dev_t dev)
|
||||
int do_rmdir(char *pathname)
|
||||
{
|
||||
if (dry_run) return 0;
|
||||
CHECK_RO
|
||||
return rmdir(pathname);
|
||||
}
|
||||
|
||||
int do_open(char *pathname, int flags, mode_t mode)
|
||||
{
|
||||
if (dry_run) return -1;
|
||||
CHECK_RO
|
||||
return open(pathname, flags, mode);
|
||||
}
|
||||
|
||||
@@ -74,6 +84,7 @@ int do_open(char *pathname, int flags, mode_t mode)
|
||||
int do_chmod(const char *path, mode_t mode)
|
||||
{
|
||||
if (dry_run) return 0;
|
||||
CHECK_RO
|
||||
return chmod(path, mode);
|
||||
}
|
||||
#endif
|
||||
@@ -81,18 +92,21 @@ int do_chmod(const char *path, mode_t mode)
|
||||
int do_rename(char *fname1, char *fname2)
|
||||
{
|
||||
if (dry_run) return 0;
|
||||
CHECK_RO
|
||||
return rename(fname1, fname2);
|
||||
}
|
||||
|
||||
int do_mkdir(char *fname, mode_t mode)
|
||||
{
|
||||
if (dry_run) return 0;
|
||||
CHECK_RO
|
||||
return mkdir(fname, mode);
|
||||
}
|
||||
|
||||
char *do_mktemp(char *template)
|
||||
{
|
||||
if (dry_run) return NULL;
|
||||
if (read_only) {errno = EROFS; return NULL;}
|
||||
return mktemp(template);
|
||||
}
|
||||
|
||||
|
||||
55
util.c
55
util.c
@@ -446,58 +446,3 @@ void kill_all(int sig)
|
||||
}
|
||||
}
|
||||
|
||||
/* this is the rsync debugging function. Call it with FINFO or FERROR */
|
||||
void rprintf(int fd, const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char buf[1024];
|
||||
int len;
|
||||
FILE *f=NULL;
|
||||
|
||||
va_start(ap, format);
|
||||
|
||||
#if HAVE_VSNPRINTF
|
||||
len = vsnprintf(buf, sizeof(buf)-1, format, ap);
|
||||
#else
|
||||
len = vsprintf(buf, format, ap);
|
||||
#endif
|
||||
va_end(ap);
|
||||
|
||||
if (len < 0) exit_cleanup(1);
|
||||
|
||||
if (fd == FERROR) {
|
||||
f = stderr;
|
||||
}
|
||||
|
||||
if (fd == FINFO) {
|
||||
extern int am_server;
|
||||
if (am_server)
|
||||
f = stderr;
|
||||
else
|
||||
f = stdout;
|
||||
}
|
||||
|
||||
if (!f) exit_cleanup(1);
|
||||
|
||||
if (fwrite(buf, len, 1, f) != 1) exit_cleanup(1);
|
||||
}
|
||||
|
||||
void rflush(int fd)
|
||||
{
|
||||
FILE *f = NULL;
|
||||
|
||||
if (fd == FERROR) {
|
||||
f = stderr;
|
||||
}
|
||||
|
||||
if (fd == FINFO) {
|
||||
extern int am_server;
|
||||
if (am_server)
|
||||
f = stderr;
|
||||
else
|
||||
f = stdout;
|
||||
}
|
||||
|
||||
if (!f) exit_cleanup(1);
|
||||
fflush(f);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user