Compare commits

...

22 Commits

Author SHA1 Message Date
rsync-bugs
4f189177dc preparing for release of 2.0.6 1998-05-16 00:57:37 +00:00
Andrew Tridgell
f72399f867 fixed handling of vsprintf on SunOS 1998-05-16 00:46:16 +00:00
rsync-bugs
d64488e169 preparing for release of 2.0.5 1998-05-15 14:12:06 +00:00
Andrew Tridgell
29110570f8 removed some debug code 1998-05-15 14:01:04 +00:00
Andrew Tridgell
3e607d2354 got rid of "EOF in map_ptr" problem. If a file shrinks mid transfer
then we supply a zero filled buffer at the end and rely on the
checksum to cause a retry. This is really the best we can do as there
is no correct semantics for copying a changing file!
1998-05-15 14:00:12 +00:00
Andrew Tridgell
a6801c3977 added a "socket options" option to rsyncd.conf. This option will
provide hours of fun for those people who like to tune their systems
to the utmost degree.
1998-05-15 13:25:19 +00:00
rsync-bugs
3ef56fee8f preparing for release of 2.0.4 1998-05-15 10:58:03 +00:00
Andrew Tridgell
f9e940efc7 load just the globals section of the config file when the daemon
starts so we know the syslog facility for the "starting" message
1998-05-15 10:52:54 +00:00
Andrew Tridgell
1a016bfdec - changed the log messages to show the requested path
- some more paranoid buffer size checks
- separate open syslog call
- handle systems without LOG_NDELAY
1998-05-15 10:34:07 +00:00
Andrew Tridgell
e42c9458c2 use strlcat() strlcpy() and slprintf() whenever possible to avoid any
chance of a buffer overflow
1998-05-15 09:26:01 +00:00
Andrew Tridgell
087bf010d2 allow the specification of multiple filenames (with or without
wildcards) to a rsync server. For example you can do:

rsync -avz samba::'ftp/pub/samba/README ftp/pub/samba/*.gz' .
1998-05-15 08:43:11 +00:00
rsync-bugs
f240c06902 preparing for release of 2.0.3 1998-05-15 07:55:05 +00:00
Andrew Tridgell
a87b3b2ac2 use a separate "make man" target so people don't need yodl 1998-05-15 07:53:41 +00:00
rsync-bugs
ed0992b888 preparing for release of 2.0.2 1998-05-15 07:37:00 +00:00
Andrew Tridgell
d6dead6bb1 added write buffering during the file list sending. This makes things
a bit more efficient (less system calls)
1998-05-15 07:34:19 +00:00
Andrew Tridgell
344fb1276b fixed a select bug which caused rsync to use far more cpu time than
necessary on the server
1998-05-15 07:11:29 +00:00
Andrew Tridgell
e095b568d0 updated the README a bit 1998-05-15 05:42:56 +00:00
Andrew Tridgell
4c3d16be50 - added some notes about encryption and authentication to the man
pages

- documented the RSYNC_PASSWORD environment variable
1998-05-15 05:37:34 +00:00
rsync-bugs
715e727784 preparing for release of 2.0.1 1998-05-15 01:19:42 +00:00
Andrew Tridgell
5805327b28 fixed typo in rsyncd exclude handling 1998-05-15 01:14:48 +00:00
Andrew Tridgell
8f3a2d54a6 added "exclude" and "exclude from" options to rsyncd.conf.
This is useful for mirroring a web site when you don't want users to
mirror everything.
1998-05-15 01:02:49 +00:00
Andrew Tridgell
e22de16264 fixed SIGCLD -> SIGCHLD
fixed formatting of man page (thanks to Karsten)
1998-05-15 00:29:45 +00:00
18 changed files with 433 additions and 155 deletions

View File

@@ -30,7 +30,9 @@ OBJS=$(OBJS1) $(OBJS2) $(DAEMON_OBJ) $(LIBOBJ)
.c.o:
$(CC) -I. -I$(srcdir) $(CFLAGS) -c $< -o $@
all: rsync rsync.1 rsyncd.conf.5
all: rsync
man: rsync.1 rsyncd.conf.5
install: all
-mkdir -p ${INSTALL_BIN}
@@ -44,12 +46,10 @@ rsync: $(OBJS)
$(CC) $(CFLAGS) -o rsync $(OBJS) $(LIBS)
rsync.1: rsync.yo
yodl2man rsync.yo
mv rsync.man rsync.1
yodl2man -o rsync.1 rsync.yo
rsyncd.conf.5: rsyncd.conf.yo
yodl2man rsyncd.conf.yo
mv rsyncd.conf.man rsyncd.conf.5
yodl2man -o rsyncd.conf.5 rsyncd.conf.yo
proto:
cat *.c | awk -f mkproto.awk > proto.h

14
README
View File

@@ -57,6 +57,9 @@ Options:
--exclude-from FILE exclude files listed in FILE
--suffix SUFFIX override backup suffix
--version print version number
--daemon run as a rsync daemon
--config FILE specify alternate rsyncd.conf file
--port PORT specify alternate rsyncd port number
SETUP
@@ -81,6 +84,14 @@ case.
Once built put a copy of rsync in your search path on the local and
remote systems (or use "make install"). That's it!
RSYNC SERVERS
-------------
rsync can also talk to "rsync servers" which can provide anonymous or
authenticated rsync. See the rsync.conf(5) man page for details on how
to setup a rsync server. See the rsync(1) man page for info on how to
connect to a rsync server.
MAILING LIST
------------
@@ -138,7 +149,8 @@ paulus@cs.anu.edu.au
AVAILABILITY
------------
The main ftp site for rsync is ftp://samba.anu.edu.au/pub/rsync
The main ftp site for rsync is ftp://samba.anu.edu.au/pub/rsync
This is also available as rsync://samba.anu.edu.au/rsyncftp/
Mirrors are available at:

View File

@@ -28,7 +28,6 @@ static void base64_encode(char *buf, int len, char *out)
char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
int bit_offset, byte_offset, idx, i;
unsigned char *d = (unsigned char *)buf;
char *p;
int bytes = (len*8 + 5)/6;
memset(out, 0, bytes+1);
@@ -56,7 +55,7 @@ static void gen_challenge(char *addr, char *challenge)
memset(input, 0, sizeof(input));
strncpy((char *)input, addr, 16);
strlcpy((char *)input, addr, 16);
gettimeofday(&tv, NULL);
SIVAL(input, 16, tv.tv_sec);
SIVAL(input, 20, tv.tv_usec);
@@ -74,8 +73,8 @@ static int get_secret(int module, char *user, char *secret, int len)
{
char *fname = lp_secrets_file(module);
int fd, found=0;
char line[1024];
char *p, *pass;
char line[MAXPATHLEN];
char *p, *pass=NULL;
if (!fname || !*fname) return 0;
@@ -108,12 +107,7 @@ static int get_secret(int module, char *user, char *secret, int len)
close(fd);
if (!found) return 0;
if (strlen(pass) > len-1) {
memset(line, 0, sizeof(line));
return 0;
}
strcpy(secret, pass);
strlcpy(secret, pass, len);
return 1;
}
@@ -137,7 +131,7 @@ int auth_server(int fd, int module, char *addr, char *leader)
char *users = lp_auth_users(module);
char challenge[16];
char b64_challenge[30];
char line[1024];
char line[MAXPATHLEN];
char user[100];
char secret[100];
char pass[30];

View File

@@ -30,7 +30,7 @@ int start_socket_client(char *host, char *path, int argc, char *argv[])
int fd, i;
char *sargs[MAX_ARGS];
int sargc=0;
char line[1024];
char line[MAXPATHLEN];
char *p, *user=NULL;
extern int remote_version;
@@ -102,13 +102,12 @@ static int rsync_module(int fd, int i)
int argc=0;
char *argv[MAX_ARGS];
char **argp;
char line[1024];
uid_t uid;
gid_t gid;
char line[MAXPATHLEN];
uid_t uid = (uid_t)-2;
gid_t gid = (gid_t)-2;
char *p;
char *addr = client_addr(fd);
char *host = client_name(fd);
char *auth;
char *name = lp_name(i);
int start_glob=0;
@@ -134,8 +133,6 @@ static int rsync_module(int fd, int i)
return -1;
}
rprintf(FINFO,"rsync on module %s from %s (%s)\n",
name, host, addr);
module_id = i;
@@ -162,22 +159,34 @@ static int rsync_module(int fd, int i)
gid = atoi(p);
}
p = lp_exclude_from(i);
add_exclude_file(p, 1);
p = lp_exclude(i);
add_exclude_line(p);
log_open();
if (chroot(lp_path(i))) {
rprintf(FERROR,"chroot %s failed\n", lp_path(i));
io_printf(fd,"@ERROR: chroot failed\n");
return -1;
}
if (chdir("/")) {
rprintf(FERROR,"chdir %s failed\n", lp_path(i));
io_printf(fd,"@ERROR: chdir failed\n");
return -1;
}
if (setgid(gid)) {
if (setgid(gid) || getgid() != gid) {
rprintf(FERROR,"setgid %d failed\n", gid);
io_printf(fd,"@ERROR: setgid failed\n");
return -1;
}
if (setuid(uid)) {
if (setuid(uid) || getuid() != uid) {
rprintf(FERROR,"setuid %d failed\n", uid);
io_printf(fd,"@ERROR: setuid failed\n");
return -1;
}
@@ -195,18 +204,18 @@ static int rsync_module(int fd, int i)
p = line;
if (start_glob && strncmp(p, name, strlen(name)) == 0) {
p += strlen(name);
if (!*p) p = ".";
}
argv[argc] = strdup(p);
if (!argv[argc]) {
return -1;
}
if (start_glob) {
glob_expand(argv, &argc, MAX_ARGS);
if (start_glob == 1) {
rprintf(FINFO,"rsync on %s from %s (%s)\n",
p, host, addr);
start_glob++;
}
glob_expand(name, argv, &argc, MAX_ARGS);
} else {
argc++;
}
@@ -257,11 +266,13 @@ static int start_daemon(int fd)
extern char *config_file;
extern int remote_version;
if (!lp_load(config_file)) {
if (!lp_load(config_file, 0)) {
exit_cleanup(1);
}
set_socket_options(fd,"SO_KEEPALIVE");
set_socket_options(fd,lp_socket_options());
io_printf(fd,"@RSYNCD: %d\n", PROTOCOL_VERSION);
@@ -318,6 +329,8 @@ static int start_daemon(int fd)
int daemon_main(void)
{
extern char *config_file;
if (is_a_socket(STDIN_FILENO)) {
/* we are running via inetd */
return start_daemon(STDIN_FILENO);
@@ -325,6 +338,15 @@ int daemon_main(void)
become_daemon();
if (!lp_load(config_file, 1)) {
fprintf(stderr,"failed to load config file %s\n", config_file);
exit_cleanup(1);
}
log_open();
rprintf(FINFO,"rsyncd version %s starting\n",VERSION);
start_accept_loop(rsync_port, start_daemon);
return -1;
}

View File

@@ -142,7 +142,9 @@ char **make_exclude_list(char *fname,char **list1,int fatal)
void add_exclude_file(char *fname,int fatal)
{
exclude_list = make_exclude_list(fname,exclude_list,fatal);
if (!fname || !*fname) return;
exclude_list = make_exclude_list(fname,exclude_list,fatal);
}
@@ -172,6 +174,18 @@ void recv_exclude_list(int f)
}
void add_exclude_line(char *p)
{
char *tok;
if (!p || !*p) return;
p = strdup(p);
if (!p) out_of_memory("add_exclude_line");
for (tok=strtok(p," "); tok; tok=strtok(NULL," "))
add_exclude(tok);
free(p);
}
static char *cvs_ignore_list[] = {
"RCS","SCCS","CVS","CVS.adm","RCSLOG","cvslog.*",
"tags","TAGS",".make.state",".nse_depinfo",
@@ -191,13 +205,9 @@ void add_cvs_excludes(void)
add_exclude(cvs_ignore_list[i]);
if ((p=getenv("HOME")) && strlen(p) < (MAXPATHLEN-12)) {
sprintf(fname,"%s/.cvsignore",p);
add_exclude_file(fname,0);
slprintf(fname,sizeof(fname)-1, "%s/.cvsignore",p);
add_exclude_file(fname,0);
}
if ((p=getenv("CVSIGNORE"))) {
char *tok;
for (tok=strtok(p," "); tok; tok=strtok(NULL," "))
add_exclude(tok);
}
add_exclude_line(getenv("CVSIGNORE"));
}

18
flist.c
View File

@@ -521,7 +521,7 @@ static void send_directory(int f,struct file_list *flist,char *dir)
closedir(d);
return;
}
strcat(fname,"/");
strlcat(fname,"/", MAXPATHLEN-1);
l++;
}
p = fname + strlen(fname);
@@ -573,6 +573,10 @@ struct file_list *send_file_list(int f,int argc,char *argv[])
flist->malloced);
if (!flist->files) out_of_memory("send_file_list");
if (f != -1) {
io_start_buffering(f);
}
for (i=0;i<argc;i++) {
char fname2[MAXPATHLEN];
char *fname = fname2;
@@ -581,7 +585,7 @@ struct file_list *send_file_list(int f,int argc,char *argv[])
l = strlen(fname);
if (l != 1 && fname[l-1] == '/') {
strcat(fname,".");
strlcat(fname,".",MAXPATHLEN-1);
}
if (link_stat(fname,&st) != 0) {
@@ -612,7 +616,7 @@ struct file_list *send_file_list(int f,int argc,char *argv[])
thus getting their permissions right */
*p = 0;
if (strcmp(lastpath,fname)) {
strcpy(lastpath, fname);
strlcpy(lastpath, fname, sizeof(lastpath)-1);
*p = '/';
for (p=fname+1; (p=strchr(p,'/')); p++) {
*p = 0;
@@ -658,7 +662,6 @@ struct file_list *send_file_list(int f,int argc,char *argv[])
if (f != -1) {
send_file_entry(NULL,f,0);
write_flush(f);
}
if (verbose && recurse && !am_server && f != -1)
@@ -677,6 +680,11 @@ struct file_list *send_file_list(int f,int argc,char *argv[])
write_int(f, io_error);
}
if (f != -1) {
io_end_buffering(f);
write_flush(f);
}
if (verbose > 2)
rprintf(FINFO,"send_file_list done\n");
@@ -870,7 +878,7 @@ char *f_name(struct file_struct *f)
n = (n+1)%10;
if (f->dirname) {
sprintf(p, "%s/%s", f->dirname, f->basename);
slprintf(p, MAXPATHLEN-1, "%s/%s", f->dirname, f->basename);
} else {
strlcpy(p, f->basename, MAXPATHLEN-1);
}

65
io.c
View File

@@ -148,7 +148,8 @@ static int readfd(int fd,char *buffer,int N)
tv.tv_sec = io_timeout;
tv.tv_usec = 0;
if (select(fd+1, &fds, NULL, NULL, &tv) != 1) {
if (select(fd+1, &fds, NULL, NULL,
io_timeout?&tv:NULL) != 1) {
check_timeout();
}
}
@@ -300,7 +301,7 @@ int write_file(int f,char *buf,int len)
}
static int writefd(int fd,char *buf,int len)
static int writefd_unbuffered(int fd,char *buf,int len)
{
int total = 0;
fd_set w_fds, r_fds;
@@ -374,6 +375,58 @@ static int writefd(int fd,char *buf,int len)
return total;
}
static char *io_buffer;
static int io_buffer_count;
void io_start_buffering(int fd)
{
io_buffer = (char *)malloc(IO_BUFFER_SIZE);
if (!io_buffer) out_of_memory("writefd");
io_buffer_count = 0;
}
void io_end_buffering(int fd)
{
if (io_buffer_count) {
if (writefd_unbuffered(fd, io_buffer,
io_buffer_count) !=
io_buffer_count) {
rprintf(FERROR,"write failed\n");
exit_cleanup(1);
}
io_buffer_count = 0;
}
free(io_buffer);
io_buffer = NULL;
}
static int writefd(int fd,char *buf,int len1)
{
int len = len1;
if (!io_buffer) return writefd_unbuffered(fd, buf, len);
while (len) {
int n = MIN(len, IO_BUFFER_SIZE-io_buffer_count);
if (n > 0) {
memcpy(io_buffer+io_buffer_count, buf, n);
buf += n;
len -= n;
io_buffer_count += n;
}
if (io_buffer_count == IO_BUFFER_SIZE) {
if (writefd_unbuffered(fd, io_buffer,
io_buffer_count) !=
io_buffer_count) {
return -1;
}
io_buffer_count = 0;
}
}
return len1;
}
void write_int(int f,int32 x)
@@ -468,13 +521,7 @@ void io_printf(int fd, const char *format, ...)
int len;
va_start(ap, format);
#if HAVE_VSNPRINTF
len = vsnprintf(buf, sizeof(buf)-1, format, ap);
#else
vsprintf(buf, format, ap);
len = strlen(buf);
#endif
len = vslprintf(buf, sizeof(buf)-1, format, ap);
va_end(ap);
if (len < 0) exit_cleanup(1);

View File

@@ -101,6 +101,7 @@ typedef struct
char *lock_file;
int syslog_facility;
int max_connections;
char *socket_options;
} global;
static global Globals;
@@ -123,6 +124,8 @@ typedef struct
char *hosts_deny;
char *auth_users;
char *secrets_file;
char *exclude;
char *exclude_from;
} service;
@@ -140,6 +143,8 @@ static service sDefault =
NULL, /* hosts deny */
NULL, /* auth users */
NULL, /* secrets file */
NULL, /* exclude */
NULL, /* exclude from */
};
@@ -226,6 +231,7 @@ static struct parm_struct parm_table[] =
{"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_ENUM, P_GLOBAL, &Globals.syslog_facility, enum_facilities,0},
{"socket options", P_STRING, P_GLOBAL, &Globals.socket_options,NULL, 0},
{"name", P_STRING, P_LOCAL, &sDefault.name, NULL, 0},
{"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL, 0},
@@ -238,6 +244,8 @@ static struct parm_struct parm_table[] =
{"hosts deny", P_STRING, P_LOCAL, &sDefault.hosts_deny, NULL, 0},
{"auth users", P_STRING, P_LOCAL, &sDefault.auth_users, NULL, 0},
{"secrets file", P_STRING, P_LOCAL, &sDefault.secrets_file,NULL, 0},
{"exclude", P_STRING, P_LOCAL, &sDefault.exclude, NULL, 0},
{"exclude from", P_STRING, P_LOCAL, &sDefault.exclude_from,NULL, 0},
{NULL, P_BOOL, P_NONE, NULL, NULL, 0}
};
@@ -247,6 +255,7 @@ Initialise the global parameter structure.
***************************************************************************/
static void init_globals(void)
{
memset(&Globals, 0, sizeof(Globals));
#ifdef LOG_DAEMON
Globals.syslog_facility = LOG_DAEMON;
#endif
@@ -287,8 +296,10 @@ 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_STRING(lp_socket_options, &Globals.socket_options)
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)
FN_LOCAL_STRING(lp_path, path)
@@ -300,6 +311,8 @@ FN_LOCAL_STRING(lp_hosts_allow, hosts_allow)
FN_LOCAL_STRING(lp_hosts_deny, hosts_deny)
FN_LOCAL_STRING(lp_auth_users, auth_users)
FN_LOCAL_STRING(lp_secrets_file, secrets_file)
FN_LOCAL_STRING(lp_exclude, exclude)
FN_LOCAL_STRING(lp_exclude_from, exclude_from)
/* local prototypes */
static int strwicmp( char *psz1, char *psz2 );
@@ -575,7 +588,7 @@ static BOOL lp_do_parameter(int snum, char *parmname, char *parmvalue)
break;
case P_GSTRING:
strcpy((char *)parm_ptr,parmvalue);
strlcpy((char *)parm_ptr,parmvalue,sizeof(pstring)-1);
break;
case P_ENUM:
@@ -656,26 +669,26 @@ static BOOL do_section(char *sectionname)
Load the services array from the services file. Return True on success,
False on failure.
***************************************************************************/
BOOL lp_load(char *pszFname)
BOOL lp_load(char *pszFname, int globals_only)
{
pstring n2;
BOOL bRetval;
pstring n2;
BOOL bRetval;
bRetval = False;
bRetval = False;
bInGlobalSection = True;
bInGlobalSection = True;
init_globals();
init_globals();
pstrcpy(n2,pszFname);
pstrcpy(n2,pszFname);
/* We get sections first, so have to start 'behind' to make up */
iServiceIndex = -1;
bRetval = pm_process(n2, do_section, do_parameter);
/* We get sections first, so have to start 'behind' to make up */
iServiceIndex = -1;
bRetval = pm_process(n2, globals_only?NULL:do_section, do_parameter);
bLoaded = True;
bLoaded = True;
return (bRetval);
return (bRetval);
}

44
log.c
View File

@@ -23,6 +23,31 @@
*/
#include "rsync.h"
void log_open(void)
{
static int initialised;
int options = LOG_PID;
if (initialised) return;
initialised = 1;
#ifdef LOG_NDELAY
options |= LOG_NDELAY;
#endif
#ifdef LOG_DAEMON
openlog("rsyncd", options, lp_syslog_facility());
#else
openlog("rsyncd", options);
#endif
#ifndef LOG_NDELAY
syslog(LOG_INFO,"rsyncd started\n");
#endif
}
/* this is the rsync debugging function. Call it with FINFO or FERROR */
void rprintf(int fd, const char *format, ...)
{
@@ -33,13 +58,7 @@ void rprintf(int fd, const char *format, ...)
extern int am_daemon;
va_start(ap, format);
#if HAVE_VSNPRINTF
len = vsnprintf(buf, sizeof(buf)-1, format, ap);
#else
vsprintf(buf, format, ap);
len = strlen(buf);
#endif
len = vslprintf(buf, sizeof(buf)-1, format, ap);
va_end(ap);
if (len < 0) exit_cleanup(1);
@@ -49,19 +68,10 @@ void rprintf(int fd, const char *format, ...)
buf[len] = 0;
if (am_daemon) {
static int initialised;
int priority = LOG_INFO;
if (fd == FERROR) priority = LOG_WARNING;
if (!initialised) {
initialised = 1;
#ifdef LOG_DAEMON
openlog("rsyncd", LOG_PID, lp_syslog_facility());
#else
openlog("rsyncd", LOG_PID);
#endif
}
log_open();
syslog(priority, "%s", buf);
return;
}

1
main.c
View File

@@ -190,7 +190,6 @@ static void do_server_sender(int f_in, int f_out, int argc,char *argv[])
struct file_list *flist;
char *dir = argv[0];
extern int relative_paths;
extern int am_daemon;
extern int recurse;
if (verbose > 2)

View File

@@ -451,10 +451,11 @@ static BOOL Parse( FILE *InFile,
break;
case '[': /* Section Header. */
if( !Section( InFile, sfunc ) )
return( False );
c = EatWhitespace( InFile );
break;
if (!sfunc) return True;
if( !Section( InFile, sfunc ) )
return( False );
c = EatWhitespace( InFile );
break;
case '\\': /* Bogus backslash. */
c = EatWhitespace( InFile );
@@ -558,3 +559,4 @@ BOOL pm_process( char *FileName,
} /* pm_process */
/* -------------------------------------------------------------------------- */

17
rsync.c
View File

@@ -111,10 +111,7 @@ static int delete_file(char *fname)
if (strcmp(dname,".")==0 ||
strcmp(dname,"..")==0)
continue;
strlcpy(buf, fname, (MAXPATHLEN-strlen(dname))-2);
strcat(buf, "/");
strcat(buf, dname);
buf[MAXPATHLEN-1] = 0;
slprintf(buf, sizeof(buf)-1, "%s/%s", fname, dname);
if (verbose > 0)
rprintf(FINFO,"deleting %s\n", buf);
if (delete_file(buf) != 0) {
@@ -831,7 +828,7 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
close(fd1);
continue;
}
sprintf(fnametmp,"%s/.%s.XXXXXX",tmpdir,f);
slprintf(fnametmp,sizeof(fnametmp)-1, "%s/.%s.XXXXXX",tmpdir,f);
} else {
char *f = strrchr(fname,'/');
@@ -844,10 +841,10 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
if (f) {
*f = 0;
sprintf(fnametmp,"%s/.%s.XXXXXX",fname,f+1);
slprintf(fnametmp,sizeof(fnametmp)-1,"%s/.%s.XXXXXX",fname,f+1);
*f = '/';
} else {
sprintf(fnametmp,".%s.XXXXXX",fname);
slprintf(fnametmp,sizeof(fnametmp)-1,".%s.XXXXXX",fname);
}
}
if (NULL == do_mktemp(fnametmp)) {
@@ -893,7 +890,7 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
rprintf(FERROR,"backup filename too long\n");
continue;
}
sprintf(fnamebak,"%s%s",fname,backup_suffix);
slprintf(fnamebak,sizeof(fnamebak)-1,"%s%s",fname,backup_suffix);
if (do_rename(fname,fnamebak) != 0 && errno != ENOENT) {
rprintf(FERROR,"rename %s %s : %s\n",fname,fnamebak,strerror(errno));
continue;
@@ -998,10 +995,10 @@ void send_files(struct file_list *flist,int f_out,int f_in)
fname);
return;
}
strcat(fname,"/");
strlcat(fname,"/",MAXPATHLEN-1);
offset = strlen(file->basedir)+1;
}
strncat(fname,f_name(file),MAXPATHLEN-strlen(fname));
strlcat(fname,f_name(file),MAXPATHLEN-strlen(fname));
if (verbose > 2)
rprintf(FINFO,"send_files(%d,%s)\n",i,fname);

View File

@@ -51,6 +51,7 @@
#define WRITE_SIZE (32*1024)
#define CHUNK_SIZE (32*1024)
#define MAX_MAP_SIZE (4*1024*1024)
#define IO_BUFFER_SIZE (4096)
#define MAX_ARGS 1000

View File

@@ -139,6 +139,11 @@ itemize(
list of accessible paths on the server will be shown.
)
Some paths on the remote server may require authentication. If so then
you will receive a password prompt when you connect. You can avoid the
password prompt by setting the environment variable RSYNC_PASSWORD to
the password you want to use. This may be useful when scripting rsync.
manpagesection(RUNNING AN RSYNC SERVER)
An rsync server is configured using a config file which by default is
@@ -445,7 +450,7 @@ times are transferred as unix time_t values
file permissions, devices etc are transferred as native numerical
values
see also the comments on the -delete option
see also the comments on the --delete option
Please report bugs! The rsync bug tracking system is online at
url(http://samba.anu.edu.au/rsync/)(http://samba.anu.edu.au/rsync/)

View File

@@ -8,7 +8,7 @@ rsyncd.conf
manpagedescription()
The rsyncd.conf file is the runtime configuration file for rsync when
run with the -daemon option. When run in this way rsync becomes a
run with the --daemon option. When run in this way rsync becomes a
rsync server listening on TCP port 873. Connections from rsync clients
are accepted for either anonymous or authenticated rsync sessions.
@@ -33,7 +33,7 @@ within a parameter value is retained verbatim.
Any line beginning with a hash (#) is ignored, as are lines containing
only whitespace.
Any line ending in a \e is "continued" on the next line in the
Any line ending in a \ is "continued" on the next line in the
customary UNIX fashion.
The values following the equals sign in parameters are all either a string
@@ -47,22 +47,22 @@ The rsync daemon is launched by specifying the --daemon option to
rsync. The daemon must run with root privileges.
You can launch it either via inetd or as a standalone daemon. If run
as a daemon then just run the command "rsync -daemon" from a suitable
as a daemon then just run the command "rsync --daemon" from a suitable
startup script.
When run via inetd you should add a line like this to /etc/services:
rsync 873/tcp
quote(rsync 873/tcp)
and a line something like this to /etc/inetd.conf:
and a single line something like this to /etc/inetd.conf:
rsync stream tcp nowait root /usr/bin/rsync rsyncd --daemon
quote(rsync stream tcp nowait root /usr/bin/rsync rsyncd --daemon)
You will then need to send inetd a HUP signal to tell it to reread its
config file.
Note that you should not send the rsync server a HUP signal to force
it to reread the /etc/rsyncd.conf. The file is re-read on each client
it to reread the tt(/etc/rsyncd.conf). The file is re-read on each client
connection.
manpagesection(GLOBAL OPTIONS)
@@ -89,7 +89,7 @@ The default is 0 which means no limit.
dit(bf(lock file)) The "lock file" option specifies the file to use to
support the "max connections" option. The rsync server uses record
locking on this file to ensure that the max connections limit is not
exceeded. The default is /var/run/rsyncd.lock
exceeded. The default is tt(/var/run/rsyncd.lock).
dit(bf(syslog facility)) The "syslog facility" option allows you to
specify the syslog facility name to use when logging messages from the
@@ -99,6 +99,13 @@ ftp, kern, lpr, mail, news, security, syslog, user, uucp, local0,
local1, local2, local3, local4, local5, local6 and local7. The default
is daemon.
dit(bf(socket options)) This option can provide endless fun for people
who like to tune their systems to the utmost degree. You can set all
sorts of socket options which may make transfers faster (or
slower!). Read the man page for the setsockopt() system call for
details on some of the options you may be able to set. By default no
special socket options are set.
enddit()
@@ -118,7 +125,7 @@ of available modules. The default is no comment.
dit(bf(path)) The "path" option specifies the directory in the servers
filesystem to make available in this module. The rsync server will
chroot to this path before starting the file transfer with the
client. You must specify this option for each module in /etc/rsyncd.conf.
client. You must specify this option for each module in tt(/etc/rsyncd.conf).
dit(bf(read only)) The "read only" option determines whether clients
will be able to upload files or not. If "read only" is true then any
@@ -140,6 +147,21 @@ dit(bf(gid)) The "gid" option specifies the group name or group id that
file transfers to and from that module should take place as. This
complements the "uid" option. The default is the group "nobody".
dit(bf(exclude)) The "exclude" option allows you to specify a space
separated list of patterns to add to the exclude list. This is
equivalent to the client specifying these patterns with the --exclude
option. Note that this option is not designed with strong security in
mind, it is quite possible that a client may find a way to bypass this
exclude list. If you want to absolutely ensure that certain files
cannot be accessed then use the uid/gid options in combination with
file permissions.
dit(bf(exclude from)) The "exclude from" option specifies a filename
on the server that contains exclude patterns, one per line. This is
equivalent to the client specifying the --exclude-from option with a
equivalent file. See also the note about security for the exclude
option above.
dit(bf(auth users)) The "auth users" option specifies a comma
and space separated list of usernames that will be allowed to connect
to this module. The usernames do not need to exist on the local
@@ -163,7 +185,7 @@ you may find that passwords longer than 8 characters don't work.
bf(You should make sure that the secrets file is not readable by anyone
other than the system administrator.) There is no default for the
"secrets file" option, you must choose a name (such as
/etc/rsyncd.secrets).
tt(/etc/rsyncd.secrets)).
dit(bf(hosts allow)) The "hosts allow" option allows you to specify a
list of patterns that are matched against a connecting clients
@@ -212,27 +234,43 @@ The default is no "hosts deny" option, which means all hosts can connect.
enddit()
manpagesection(AUTHENTICATION STRENGTH)
The authentication protocol used in rsync is a 128 bit MD4 based
challenge response system. Although I believe that no one has ever
demonstrated a brute-force break of this sort of system you should
realise that this is not a "military strength" authentication system.
It should be good enough for most purposes but if you want really top
quality security then I recommend that you run rsync over ssh.
Also note that the rsync server protocol does not currently provide any
encryption of the data that is transferred over the link. Only
authentication is provided. Use ssh as the transport if you want
encryption.
Future versions of rsync may support SSL for better authentication and
encryption, but that is still being investigated.
manpagesection(EXAMPLES)
A simple rsyncd.conf file that allow anonymous rsync to a ftp area at
/home/ftp would be:
tt(/home/ftp) would be:
verb(
[ftp]
path = /home/ftp
comment = ftp export area
path = /home/ftp
comment = ftp export area
)
A more sophisticated example would be:
verb(
uid = nobody
gid = nobody
max connections = 4
syslog facility = local5
uid = nobody nl()
gid = nobody nl()
max connections = 4 nl()
syslog facility = local5 nl()
[ftp]
verb([ftp]
path = /var/ftp/pub
comment = whole ftp area (approx 6.1 GB)
@@ -257,10 +295,8 @@ syslog facility = local5
The /etc/rsyncd.secrets file would look something like this:
verb(
tridge:mypass
tridge:mypass nl()
susan:herpass
)
manpagefiles()

View File

@@ -120,7 +120,7 @@ void start_accept_loop(int port, int (*fn)(int ))
{
int s;
signal(SIGCLD, SIG_IGN);
signal(SIGCHLD, SIG_IGN);
/* open an incoming socket */
s = open_socket_in(SOCK_STREAM, port);
@@ -216,6 +216,8 @@ set user socket options
void set_socket_options(int fd, char *options)
{
char *tok;
if (!options || !*options) return;
options = strdup(options);
if (!options) out_of_memory("set_socket_options");

180
util.c
View File

@@ -60,44 +60,49 @@ struct map_struct *map_file(int fd,OFF_T len)
char *map_ptr(struct map_struct *map,OFF_T offset,int len)
{
int nread = -2;
int nread;
if (map->map)
return map->map+offset;
if (map->map)
return map->map+offset;
if (len == 0)
return NULL;
if (len == 0)
return NULL;
if (len > (map->size-offset))
len = map->size-offset;
if (len > (map->size-offset))
len = map->size-offset;
if (offset >= map->p_offset &&
offset+len <= map->p_offset+map->p_len) {
return (map->p + (offset - map->p_offset));
}
if (offset >= map->p_offset &&
offset+len <= map->p_offset+map->p_len) {
return (map->p + (offset - map->p_offset));
}
len = MAX(len,CHUNK_SIZE);
if (len > (map->size-offset))
len = map->size-offset;
len = MAX(len,CHUNK_SIZE);
if (len > (map->size-offset))
len = map->size-offset;
if (len > map->p_size) {
if (map->p) free(map->p);
map->p = (char *)malloc(len);
if (!map->p) out_of_memory("map_ptr");
map->p_size = len;
}
if (len > map->p_size) {
if (map->p) free(map->p);
map->p = (char *)malloc(len);
if (!map->p) out_of_memory("map_ptr");
map->p_size = len;
}
if (do_lseek(map->fd,offset,SEEK_SET) != offset ||
(nread=read(map->fd,map->p,len)) != len) {
rprintf(FERROR,"EOF in map_ptr! (offset=%d len=%d nread=%d errno=%d)\n",
(int)offset, len, nread, errno);
exit_cleanup(1);
}
map->p_offset = offset;
map->p_len = len;
map->p_offset = offset;
map->p_len = len;
if (do_lseek(map->fd,offset,SEEK_SET) != offset) {
rprintf(FERROR,"lseek failed in map_ptr\n");
exit_cleanup(1);
}
return map->p;
if ((nread=read(map->fd,map->p,len)) != len) {
if (nread < 0) nread = 0;
/* the best we can do is zero the buffer - the file
has changed mid transfer! */
memset(map->p+nread, 0, len - nread);
}
return map->p;
}
@@ -456,6 +461,21 @@ void strlcpy(char *d, char *s, int maxlen)
d[len] = 0;
}
/* like strncat but does not 0 fill the buffer and always null
terminates (thus it can use maxlen+1 space in d) */
void strlcat(char *d, char *s, int maxlen)
{
int len1 = strlen(d);
int len2 = strlen(s);
if (len1+len2 > maxlen) {
len2 = maxlen-len1;
}
if (len2 > 0) {
memcpy(d+len1, s, len2);
d[len1+len2] = 0;
}
}
/* turn a user name into a uid */
int name_to_uid(char *name, uid_t *uid)
{
@@ -506,15 +526,21 @@ int lock_range(int fd, int offset, int len)
}
void glob_expand(char **argv, int *argc, int maxargs)
static void glob_expand_one(char *s, char **argv, int *argc, int maxargs)
{
#ifndef HAVE_GLOB
if (!*s) s = ".";
argv[*argc] = strdup(s);
(*argc)++;
return;
#else
glob_t globbuf;
int i;
if (!*s) s = ".";
argv[*argc] = strdup(s);
memset(&globbuf, 0, sizeof(globbuf));
glob(argv[*argc], 0, NULL, &globbuf);
if (globbuf.gl_pathc == 0) {
@@ -532,6 +558,36 @@ void glob_expand(char **argv, int *argc, int maxargs)
#endif
}
void glob_expand(char *base, char **argv, int *argc, int maxargs)
{
char *s = argv[*argc];
char *p, *q;
if (!s || !*s) return;
if (strncmp(s, base, strlen(base)) == 0) {
s += strlen(base);
}
s = strdup(s);
if (!s) out_of_memory("glob_expand");
q = s;
while ((p = strstr(q,base)) && ((*argc) < maxargs)) {
if (p != q && *(p-1) == ' ' && p[strlen(base)] == '/') {
/* split it at this point */
*(p-1) = 0;
glob_expand_one(q, argv, argc, maxargs);
q = p+strlen(base)+1;
} else {
q++;
}
}
if (*q && (*argc < maxargs)) glob_expand_one(q, argv, argc, maxargs);
free(s);
}
/*******************************************************************
convert a string to lower case
@@ -543,3 +599,67 @@ void strlower(char *s)
s++;
}
}
/* this is like vsnprintf but the 'n' limit does not include
the terminating null. So if you have a 1024 byte buffer then
pass 1023 for n */
int vslprintf(char *str, int n, const char *format, va_list ap)
{
#ifdef HAVE_VSNPRINTF
int ret = vsnprintf(str, n, format, ap);
if (ret > n || ret < 0) {
str[n] = 0;
return -1;
}
str[ret] = 0;
return ret;
#else
static char *buf;
static int len=MAXPATHLEN*8;
int ret;
/* this code is NOT a proper vsnprintf() implementation. It
relies on the fact that all calls to slprintf() in rsync
pass strings which have already been checked to be less
than MAXPATHLEN in length and never more than 2 strings are
concatenated. This means the above buffer is absolutely
ample and can never be overflowed.
In the future we would like to replace this with a proper
vsnprintf() implementation but right now we need a solution
that is secure and portable. This is it. */
if (!buf) {
buf = malloc(len);
if (!buf) {
/* can't call debug or we would recurse */
exit(1);
}
}
vsprintf(buf, format, ap);
ret = strlen(buf);
if (ret > n) {
/* yikes! */
exit(1);
}
buf[ret] = 0;
memcpy(str, buf, ret+1);
return ret;
#endif
}
/* like snprintf but always null terminates */
int slprintf(char *str, int n, char *format, ...)
{
va_list ap;
int ret;
va_start(ap, format);
ret = vslprintf(str,n,format,ap);
va_end(ap);
return ret;
}

View File

@@ -1 +1 @@
#define VERSION "2.0.0"
#define VERSION "2.0.6"