mirror of
https://github.com/RsyncProject/rsync.git
synced 2026-05-25 15:25:30 -04:00
Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e9d736a7e8 | ||
|
|
e9ace0c77a | ||
|
|
1c31ffa9af | ||
|
|
d186eb1a56 | ||
|
|
18baf523dc | ||
|
|
7b372642ec | ||
|
|
4f189177dc | ||
|
|
f72399f867 | ||
|
|
d64488e169 | ||
|
|
29110570f8 | ||
|
|
3e607d2354 | ||
|
|
a6801c3977 | ||
|
|
3ef56fee8f | ||
|
|
f9e940efc7 | ||
|
|
1a016bfdec | ||
|
|
e42c9458c2 | ||
|
|
087bf010d2 | ||
|
|
f240c06902 | ||
|
|
a87b3b2ac2 | ||
|
|
ed0992b888 | ||
|
|
d6dead6bb1 | ||
|
|
344fb1276b | ||
|
|
e095b568d0 | ||
|
|
4c3d16be50 |
10
Makefile.in
10
Makefile.in
@@ -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
14
README
@@ -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:
|
||||
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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,15 +102,16 @@ 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;
|
||||
char *request=NULL;
|
||||
extern int am_sender;
|
||||
|
||||
if (!allow_access(addr, host, lp_hosts_allow(i), lp_hosts_deny(i))) {
|
||||
rprintf(FERROR,"rsync denied on module %s from %s (%s)\n",
|
||||
@@ -134,8 +135,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;
|
||||
|
||||
@@ -168,22 +167,28 @@ static int rsync_module(int fd, int i)
|
||||
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;
|
||||
}
|
||||
@@ -201,18 +206,17 @@ 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) {
|
||||
request = strdup(p);
|
||||
start_glob++;
|
||||
}
|
||||
glob_expand(name, argv, &argc, MAX_ARGS);
|
||||
} else {
|
||||
argc++;
|
||||
}
|
||||
@@ -228,6 +232,13 @@ static int rsync_module(int fd, int i)
|
||||
|
||||
parse_arguments(argc, argv);
|
||||
|
||||
if (request) {
|
||||
rprintf(FINFO,"rsync %s %s from %s (%s)\n",
|
||||
am_sender?"on":"to",
|
||||
request, host, addr);
|
||||
free(request);
|
||||
}
|
||||
|
||||
/* don't allow the logs to be flooded too fast */
|
||||
if (verbose > 1) verbose = 1;
|
||||
|
||||
@@ -263,11 +274,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);
|
||||
|
||||
@@ -324,6 +337,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);
|
||||
@@ -331,6 +346,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;
|
||||
}
|
||||
|
||||
@@ -205,8 +205,8 @@ 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);
|
||||
}
|
||||
|
||||
add_exclude_line(getenv("CVSIGNORE"));
|
||||
|
||||
18
flist.c
18
flist.c
@@ -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
65
io.c
@@ -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);
|
||||
|
||||
31
loadparm.c
31
loadparm.c
@@ -101,6 +101,7 @@ typedef struct
|
||||
char *lock_file;
|
||||
int syslog_facility;
|
||||
int max_connections;
|
||||
char *socket_options;
|
||||
} global;
|
||||
|
||||
static global Globals;
|
||||
@@ -230,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},
|
||||
@@ -253,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
|
||||
@@ -293,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)
|
||||
@@ -583,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:
|
||||
@@ -664,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
44
log.c
@@ -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;
|
||||
}
|
||||
|
||||
44
main.c
44
main.c
@@ -34,14 +34,15 @@ static void report(int f)
|
||||
extern int am_sender;
|
||||
extern int am_daemon;
|
||||
|
||||
if (!verbose) return;
|
||||
|
||||
if (am_daemon) {
|
||||
rprintf(FINFO, "wrote %.0f bytes read %.0f bytes total size %.0f\n",
|
||||
(double)write_total(),(double)read_total(),
|
||||
(double)total_size);
|
||||
if (f == -1 || !am_sender) return;
|
||||
}
|
||||
|
||||
if (!verbose) return;
|
||||
|
||||
if (am_server && am_sender) {
|
||||
write_longint(f,read_total());
|
||||
write_longint(f,write_total());
|
||||
@@ -190,7 +191,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)
|
||||
@@ -226,32 +226,32 @@ static void do_server_sender(int f_in, int f_out, int argc,char *argv[])
|
||||
|
||||
static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
|
||||
{
|
||||
int pid;
|
||||
int status=0;
|
||||
int recv_pipe[2];
|
||||
extern int preserve_hard_links;
|
||||
int pid;
|
||||
int status=0;
|
||||
int recv_pipe[2];
|
||||
extern int preserve_hard_links;
|
||||
extern int am_daemon;
|
||||
|
||||
if (preserve_hard_links)
|
||||
init_hard_links(flist);
|
||||
if (preserve_hard_links)
|
||||
init_hard_links(flist);
|
||||
|
||||
if (pipe(recv_pipe) < 0) {
|
||||
rprintf(FERROR,"pipe failed in do_recv\n");
|
||||
exit(1);
|
||||
}
|
||||
if (pipe(recv_pipe) < 0) {
|
||||
rprintf(FERROR,"pipe failed in do_recv\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
if ((pid=do_fork()) == 0) {
|
||||
recv_files(f_in,flist,local_name,recv_pipe[1]);
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"receiver read %ld\n",(long)read_total());
|
||||
exit_cleanup(0);
|
||||
}
|
||||
if ((pid=do_fork()) == 0) {
|
||||
recv_files(f_in,flist,local_name,recv_pipe[1]);
|
||||
if (am_daemon) report(-1);
|
||||
exit_cleanup(0);
|
||||
}
|
||||
|
||||
generate_files(f_out,flist,local_name,recv_pipe[0]);
|
||||
generate_files(f_out,flist,local_name,recv_pipe[0]);
|
||||
|
||||
waitpid(pid, &status, 0);
|
||||
waitpid(pid, &status, 0);
|
||||
|
||||
return status;
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
|
||||
79
packaging/redhat/5.0/rsync.spec
Normal file
79
packaging/redhat/5.0/rsync.spec
Normal file
@@ -0,0 +1,79 @@
|
||||
Summary: Program for efficient remote updates of files.
|
||||
Name: rsync
|
||||
Version: 2.0.7
|
||||
Release: 1
|
||||
Copyright: GPL
|
||||
Group: Applications/Networking
|
||||
Source: ftp://samba.anu.edu.au/pub/rsync/
|
||||
URL: http://samba.anu.edu.au/rsync/
|
||||
Packager: John H Terpstra <jht@samba.anu.edu.au>
|
||||
BuildRoot: /tmp/rsync
|
||||
|
||||
%description
|
||||
rsync is a replacement for rcp that has many more features.
|
||||
|
||||
rsync uses the "rsync algorithm" which provides a very fast method for
|
||||
bringing remote files into sync. It does this by sending just the
|
||||
differences in the files across the link, without requiring that both
|
||||
sets of files are present at one of the ends of the link beforehand.
|
||||
|
||||
A technical report describing the rsync algorithm is included with
|
||||
this package.
|
||||
|
||||
%changelog
|
||||
* Sat May 16 1998 John H Terpstra <jht@aquasoft.com.au>
|
||||
Upgraded to Rsync 2.0.6
|
||||
-new feature anonymous rsync
|
||||
|
||||
* Mon Apr 6 1998 Douglas N. Arnold <dna@math.psu.edu>
|
||||
|
||||
Upgrade to rsync version 1.7.2.
|
||||
|
||||
* Sun Mar 1 1998 Douglas N. Arnold <dna@math.psu.edu>
|
||||
|
||||
Built 1.6.9-1 based on the 1.6.3-2 spec file of John A. Martin.
|
||||
Changes from 1.6.3-2 packaging: added latex and dvips commands
|
||||
to create tech_report.ps.
|
||||
|
||||
* Mon Aug 25 1997 John A. Martin <jam@jamux.com>
|
||||
|
||||
Built 1.6.3-2 after finding no rsync-1.6.3-1.src.rpm although there
|
||||
was an ftp://ftp.redhat.com/pub/contrib/alpha/rsync-1.6.3-1.alpha.rpm
|
||||
showing no packager nor signature but giving
|
||||
"Source RPM: rsync-1.6.3-1.src.rpm".
|
||||
|
||||
Changes from 1.6.2-1 packaging: added '$RPM_OPT_FLAGS' to make, strip
|
||||
to '%build', removed '%prefix'.
|
||||
|
||||
* Thu Apr 10 1997 Michael De La Rue <miked@ed.ac.uk>
|
||||
|
||||
rsync-1.6.2-1 packaged. (This entry by jam to credit Michael for the
|
||||
previous package(s).)
|
||||
|
||||
%prep
|
||||
%setup
|
||||
|
||||
%build
|
||||
./configure --prefix=/usr
|
||||
make CFLAGS=$RPM_OPT_FLAGS
|
||||
strip rsync
|
||||
latex tech_report
|
||||
dvips tech_report -o
|
||||
|
||||
%install
|
||||
mkdir -p $RPM_BUILD_ROOT/usr/{bin,man/{man1,man5}}
|
||||
install -m755 rsync $RPM_BUILD_ROOT/usr/bin
|
||||
install -m644 rsync.1 $RPM_BUILD_ROOT/usr/man/man1
|
||||
install -m644 rsyncd.conf.5 $RPM_BUILD_ROOT/usr/man/man5
|
||||
|
||||
%clean
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
%files
|
||||
%attr(-,root,root) /usr/bin/rsync
|
||||
%attr(-,root,root) /usr/man/man1/rsync.1
|
||||
%attr(-,root,root) /usr/man/man5/rsyncd.conf.5
|
||||
%attr(-,root,root) %doc tech_report.ps
|
||||
%attr(-,root,root) %doc tech_report.tex
|
||||
%attr(-,root,root) %doc README
|
||||
%attr(-,root,root) %doc COPYING
|
||||
79
packaging/redhat/5.0/rsync.spec.tmpl
Normal file
79
packaging/redhat/5.0/rsync.spec.tmpl
Normal file
@@ -0,0 +1,79 @@
|
||||
Summary: Program for efficient remote updates of files.
|
||||
Name: rsync
|
||||
Version: PVERSION
|
||||
Release: PRELEASE
|
||||
Copyright: GPL
|
||||
Group: Applications/Networking
|
||||
Source: ftp://samba.anu.edu.au/pub/rsync/
|
||||
URL: http://samba.anu.edu.au/rsync/
|
||||
Packager: John H Terpstra <jht@samba.anu.edu.au>
|
||||
BuildRoot: /tmp/rsync
|
||||
|
||||
%description
|
||||
rsync is a replacement for rcp that has many more features.
|
||||
|
||||
rsync uses the "rsync algorithm" which provides a very fast method for
|
||||
bringing remote files into sync. It does this by sending just the
|
||||
differences in the files across the link, without requiring that both
|
||||
sets of files are present at one of the ends of the link beforehand.
|
||||
|
||||
A technical report describing the rsync algorithm is included with
|
||||
this package.
|
||||
|
||||
%changelog
|
||||
* Sat May 16 1998 John H Terpstra <jht@aquasoft.com.au>
|
||||
Upgraded to Rsync 2.0.6
|
||||
-new feature anonymous rsync
|
||||
|
||||
* Mon Apr 6 1998 Douglas N. Arnold <dna@math.psu.edu>
|
||||
|
||||
Upgrade to rsync version 1.7.2.
|
||||
|
||||
* Sun Mar 1 1998 Douglas N. Arnold <dna@math.psu.edu>
|
||||
|
||||
Built 1.6.9-1 based on the 1.6.3-2 spec file of John A. Martin.
|
||||
Changes from 1.6.3-2 packaging: added latex and dvips commands
|
||||
to create tech_report.ps.
|
||||
|
||||
* Mon Aug 25 1997 John A. Martin <jam@jamux.com>
|
||||
|
||||
Built 1.6.3-2 after finding no rsync-1.6.3-1.src.rpm although there
|
||||
was an ftp://ftp.redhat.com/pub/contrib/alpha/rsync-1.6.3-1.alpha.rpm
|
||||
showing no packager nor signature but giving
|
||||
"Source RPM: rsync-1.6.3-1.src.rpm".
|
||||
|
||||
Changes from 1.6.2-1 packaging: added '$RPM_OPT_FLAGS' to make, strip
|
||||
to '%build', removed '%prefix'.
|
||||
|
||||
* Thu Apr 10 1997 Michael De La Rue <miked@ed.ac.uk>
|
||||
|
||||
rsync-1.6.2-1 packaged. (This entry by jam to credit Michael for the
|
||||
previous package(s).)
|
||||
|
||||
%prep
|
||||
%setup
|
||||
|
||||
%build
|
||||
./configure --prefix=/usr
|
||||
make CFLAGS=$RPM_OPT_FLAGS
|
||||
strip rsync
|
||||
latex tech_report
|
||||
dvips tech_report -o
|
||||
|
||||
%install
|
||||
mkdir -p $RPM_BUILD_ROOT/usr/{bin,man/{man1,man5}}
|
||||
install -m755 rsync $RPM_BUILD_ROOT/usr/bin
|
||||
install -m644 rsync.1 $RPM_BUILD_ROOT/usr/man/man1
|
||||
install -m644 rsyncd.conf.5 $RPM_BUILD_ROOT/usr/man/man5
|
||||
|
||||
%clean
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
%files
|
||||
%attr(-,root,root) /usr/bin/rsync
|
||||
%attr(-,root,root) /usr/man/man1/rsync.1
|
||||
%attr(-,root,root) /usr/man/man5/rsyncd.conf.5
|
||||
%attr(-,root,root) %doc tech_report.ps
|
||||
%attr(-,root,root) %doc tech_report.tex
|
||||
%attr(-,root,root) %doc README
|
||||
%attr(-,root,root) %doc COPYING
|
||||
10
params.c
10
params.c
@@ -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
17
rsync.c
@@ -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);
|
||||
|
||||
1
rsync.h
1
rsync.h
@@ -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
|
||||
|
||||
|
||||
7
rsync.yo
7
rsync.yo
@@ -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/)
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -227,6 +234,23 @@ 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
|
||||
|
||||
2
socket.c
2
socket.c
@@ -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
180
util.c
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user