-rsync 2.5.2 (???)
+rsync 2.4.7 (???)
SECURITY FIXES:
* Signedness security patch from Sebastian Krahmer
<krahmer@suse.de> -- in some cases we were not sufficiently
careful about reading integers from the network.
-
- BUG FIXES:
-
- * Fix possible string mangling in log files.
-
- * Fix for setting local address of outgoing sockets.
-
- * Better handling of hardlinks and devices on platforms with
- 64-bit dev_t or ino_t.
-
- * Name resolution on machines supporting IPv6 is improved.
-
- ENHANCEMENTS:
-
- * With -v, rsync now shows the command used to initiate an ssh/rsh
- connection.
-
- * --statistics now shows memory heap usage on platforms that
- support mallinfo().
-
- * "The Ted T'so school of program optimization": make progress
- visible and people will think it's faster. (With --progress,
- rsync will show you how many files it has seen as it builds the
- file_list, giving some indication that it has not hung.)
-
- * Improvements to batch mode support. This is still experimental
- but testing would be welcome. (Jos Backus)
-/* -*- c-file-style: "linux" -*-
-
- Copyright (C) 1996-2001 by Andrew Tridgell <tridge@samba.org>
- Copyright (C) 1996 by Paul Mackerras
+/*
+ Copyright (C) Andrew Tridgell 1996
+ Copyright (C) Paul Mackerras 1996
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
/* a lot of this stuff was originally derived from GNU tar, although
it has now changed so much that it is hard to tell :) */
-/* include/exclude cluestick added by Martin Pool <mbp@samba.org> */
-
#include "rsync.h"
extern int verbose;
static struct exclude_struct **exclude_list;
/* build an exclude structure given a exclude pattern */
-static struct exclude_struct *make_exclude(const char *pattern, int include)
+static struct exclude_struct *make_exclude(char *pattern, int include)
{
struct exclude_struct *ret;
free(ex);
}
-static int check_one_exclude(char *name, struct exclude_struct *ex,
- STRUCT_STAT *st)
+static int check_one_exclude(char *name,struct exclude_struct *ex,
+ STRUCT_STAT *st)
{
char *p;
int match_start=0;
}
-static void report_exclude_result(char const *name,
- struct exclude_struct const *ent,
- STRUCT_STAT const *st)
-{
- /* If a trailing slash is present to match only directories,
- * then it is stripped out by make_exclude. So as a special
- * case we add it back in here. */
-
- if (verbose >= 2)
- rprintf(FINFO, "%s %s %s because of pattern %s%s\n",
- ent->include ? "including" : "excluding",
- S_ISDIR(st->st_mode) ? "directory" : "file",
- name, ent->pattern,
- ent->directory ? "/" : "");
-}
-
-
-/*
- * Return true if file NAME is defined to be excluded by either
- * LOCAL_EXCLUDE_LIST or the globals EXCLUDE_LIST.
- */
-int check_exclude(char *name, struct exclude_struct **local_exclude_list,
+int check_exclude(char *name,struct exclude_struct **local_exclude_list,
STRUCT_STAT *st)
{
int n;
- struct exclude_struct *ent;
if (name && (name[0] == '.') && !name[1])
/* never exclude '.', even if somebody does --exclude '*' */
return 0;
if (exclude_list) {
- for (n=0; exclude_list[n]; n++) {
- ent = exclude_list[n];
- if (check_one_exclude(name, ent, st)) {
- report_exclude_result(name, ent, st);
- return !ent->include;
- }
- }
+ for (n=0; exclude_list[n]; n++)
+ if (check_one_exclude(name,exclude_list[n],st))
+ return !exclude_list[n]->include;
}
if (local_exclude_list) {
- for (n=0; local_exclude_list[n]; n++) {
- ent = local_exclude_list[n];
- if (check_one_exclude(name, ent, st)) {
- report_exclude_result(name, ent, st);
- return !ent->include;
- }
- }
+ for (n=0; local_exclude_list[n]; n++)
+ if (check_one_exclude(name,local_exclude_list[n],st))
+ return !local_exclude_list[n]->include;
}
return 0;
}
-void add_exclude_list(const char *pattern, struct exclude_struct ***list, int include)
+void add_exclude_list(char *pattern,struct exclude_struct ***list, int include)
{
int len=0;
if (list && *list)
(*list)[len+1] = NULL;
}
-void add_exclude(const char *pattern, int include)
+void add_exclude(char *pattern, int include)
{
add_exclude_list(pattern,&exclude_list, include);
}
-struct exclude_struct **make_exclude_list(const char *fname,
+struct exclude_struct **make_exclude_list(char *fname,
struct exclude_struct **list1,
int fatal, int include)
{
char line[MAXPATHLEN];
if (!f) {
if (fatal) {
- rsyserr(FERROR, errno,
- "failed to open %s file %s",
- include ? "include" : "exclude",
- fname);
+ rprintf(FERROR,"%s : %s\n",fname,strerror(errno));
exit_cleanup(RERR_FILEIO);
}
return list;
}
-void add_exclude_file(const char *fname, int fatal, int include)
+void add_exclude_file(char *fname,int fatal,int include)
{
if (!fname || !*fname) return;
add_exclude(cvs_ignore_list[i], 0);
if ((p=getenv("HOME")) && strlen(p) < (MAXPATHLEN-12)) {
- snprintf(fname,sizeof(fname), "%s/.cvsignore",p);
+ slprintf(fname,sizeof(fname), "%s/.cvsignore",p);
add_exclude_file(fname,0,0);
}
/*
Copyright (C) Andrew Tridgell 1996
Copyright (C) Paul Mackerras 1996
- Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-/** @file flist.c
- * Generate and receive file lists
- *
- * @todo Get rid of the string_area optimization. Efficiently
- * allocating blocks is the responsibility of the system's malloc
- * library, not of rsync.
- *
- **/
+/* generate and receive file lists */
#include "rsync.h"
extern int io_error;
extern int sanitize_paths;
-extern int read_batch;
-extern int write_batch;
-
static char topsrcname[MAXPATHLEN];
static struct exclude_struct **local_exclude_list;
static void clean_flist(struct file_list *flist, int strip_root);
-
-static int show_build_progress_p(void)
-{
- extern int do_progress;
-
- return do_progress && verbose && recurse && !am_server;
-}
-
-/**
- * True if we're local, etc, and should emit progress emssages.
- **/
-static void emit_build_progress(const struct file_list *flist)
-{
- rprintf(FINFO,
- " %d files...\r",
- flist->count);
-}
-
-
-static void finish_build_progress(const struct file_list *flist)
-{
- if (verbose && recurse && !am_server) {
- /* This overwrites the progress line, if any. */
- rprintf(FINFO, RSYNC_NAME ": %d files to consider.\n",
- flist->count);
- }
-}
-
-
static struct string_area *string_area_new(int size)
{
struct string_area *a;
static void list_file_entry(struct file_struct *f)
{
- char perms[11];
+ char perms[11] = "----------";
+ char *perm_map = "rwxrwxrwx";
+ int i;
if (!f->basename)
/* this can happen if duplicate names were removed */
return;
- permstring(perms, f->mode);
-
+ for (i=0;i<9;i++) {
+ if (f->mode & (1<<i)) perms[9-i] = perm_map[8-i];
+ }
+ if (S_ISLNK(f->mode)) perms[0] = 'l';
+ if (S_ISDIR(f->mode)) perms[0] = 'd';
+ if (S_ISBLK(f->mode)) perms[0] = 'b';
+ if (S_ISCHR(f->mode)) perms[0] = 'c';
+ if (S_ISSOCK(f->mode)) perms[0] = 's';
+ if (S_ISFIFO(f->mode)) perms[0] = 'p';
+
if (preserve_links && S_ISLNK(f->mode)) {
rprintf(FINFO,"%s %11.0f %s %s -> %s\n",
perms,
}
if (S_ISLNK(Buffer->st_mode)) {
int l;
- if ((l = readlink((char *) Path, Linkbuf, MAXPATHLEN-1))== -1) {
+ if ((l = readlink(Path,Linkbuf,MAXPATHLEN-1)) == -1) {
return -1;
}
Linkbuf[l] = 0;
This function is used to check if a file should be included/excluded
from the list of files based on its name and type etc
*/
-static int check_exclude_file(int f,char *fname,STRUCT_STAT *st)
+static int match_file_name(char *fname,STRUCT_STAT *st)
{
- extern int delete_excluded;
-
- /* f is set to -1 when calculating deletion file list */
- if ((f == -1) && delete_excluded) {
- return 0;
- }
- if (check_exclude(fname,local_exclude_list,st)) {
- return 1;
- }
- return 0;
+ if (check_exclude(fname,local_exclude_list,st)) {
+ if (verbose > 2)
+ rprintf(FINFO,"excluding file %s\n",fname);
+ return 0;
+ }
+ return 1;
}
/* used by the one_file_system code */
static int to_wire_mode(mode_t mode)
{
- if (S_ISLNK(mode) && (_S_IFLNK != 0120000)) {
+ if (S_ISLNK(mode) && (S_IFLNK != 0120000)) {
return (mode & ~(_S_IFMT)) | 0120000;
}
return (int)mode;
static mode_t from_wire_mode(int mode)
{
- if ((mode & (_S_IFMT)) == 0120000 && (_S_IFLNK != 0120000)) {
- return (mode & ~(_S_IFMT)) | _S_IFLNK;
+ if ((mode & (_S_IFMT)) == 0120000 && (S_IFLNK != 0120000)) {
+ return (mode & ~(_S_IFMT)) | S_IFLNK;
}
return (mode_t)mode;
}
#if SUPPORT_HARD_LINKS
if (preserve_hard_links && S_ISREG(file->mode)) {
- if (remote_version < 26) {
- /* 32-bit dev_t and ino_t */
- write_int(f,(int)file->dev);
- write_int(f,(int)file->inode);
- } else {
- /* 64-bit dev_t and ino_t */
- write_longint(f, file->dev);
- write_longint(f, file->inode);
- }
+ write_int(f,(int)file->dev);
+ write_int(f,(int)file->inode);
}
#endif
#if SUPPORT_HARD_LINKS
if (preserve_hard_links && S_ISREG(file->mode)) {
- if (remote_version < 26) {
- file->dev = read_int(f);
- file->inode = read_int(f);
- } else {
- file->dev = read_longint(f);
- file->inode = read_longint(f);
- }
+ file->dev = read_int(f);
+ file->inode = read_int(f);
}
#endif
}
#define STRDUP(ap, p) (ap ? string_area_strdup(ap, p) : strdup(p))
-/* IRIX cc cares that the operands to the ternary have the same type. */
-#define MALLOC(ap, i) (ap ? (void*) string_area_malloc(ap, i) : malloc(i))
+#define MALLOC(ap, i) (ap ? string_area_malloc(ap, i) : malloc(i))
/* create a file_struct for a named file */
struct file_struct *make_file(int f, char *fname, struct string_area **ap,
char *p;
char cleaned_name[MAXPATHLEN];
char linkbuf[MAXPATHLEN];
+ extern int delete_excluded;
extern int module_id;
strlcpy(cleaned_name, fname, MAXPATHLEN);
memset(sum,0,SUM_LENGTH);
if (readlink_stat(fname,&st,linkbuf) != 0) {
- int save_errno = errno;
- if ((errno == ENOENT) && copy_links && !noexcludes) {
- /* symlink pointing nowhere, see if excluded */
- memset((char *)&st, 0, sizeof(st));
- if (check_exclude_file(f,fname,&st)) {
- /* file is excluded anyway, ignore silently */
- return NULL;
- }
- }
io_error = 1;
rprintf(FERROR,"readlink %s: %s\n",
- fname,strerror(save_errno));
+ fname,strerror(errno));
return NULL;
}
return NULL;
}
- if (check_exclude_file(f,fname,&st))
+ /* f is set to -1 when calculating deletion file list */
+ if (((f != -1) || !delete_excluded) && !match_file_name(fname,&st))
return NULL;
file = make_file(f,fname, &flist->string_area, 0);
- if (!file) return;
-
- if (show_build_progress_p() & !(flist->count % 100))
- emit_build_progress(flist);
+ if (!file) return;
if (flist->count >= flist->malloced) {
if (flist->malloced < 1000)
out_of_memory("send_file_name");
}
- if (write_batch) /* dw */
- file->flags = FLAG_DELETE;
-
if (strcmp(file->basename,"")) {
flist->files[flist->count++] = file;
send_file_entry(file,f,base_flags);
}
-/*
- *
- * I *think* f==-1 means that the list should just be built in memory
- * and not transmitted. But who can tell? -- mbp
- */
struct file_list *send_file_list(int f,int argc,char *argv[])
{
int i,l;
int64 start_write;
if (verbose && recurse && !am_server && f != -1) {
- rprintf(FINFO, RSYNC_NAME ": building file list...\n");
- if (verbose > 1)
- rprintf(FINFO, "\n");
+ rprintf(FINFO,"building file list ... ");
rflush(FINFO);
}
send_file_entry(NULL,f,0);
}
- finish_build_progress(flist);
+ if (verbose && recurse && !am_server && f != -1)
+ rprintf(FINFO,"done\n");
clean_flist(flist, 0);
io_end_buffering(f);
stats.flist_size = stats.total_written - start_write;
stats.num_files = flist->count;
- if (write_batch) /* dw */
- write_batch_flist_info(flist->count, flist->files);
}
if (verbose > 2)
}
/* if protocol version is >= 17 then recv the io_error flag */
- if (f != -1 && remote_version >= 17 && !read_batch) { /* dw-added readbatch */
+ if (f != -1 && remote_version >= 17) {
extern int module_id;
extern int ignore_errors;
if (lp_ignore_errors(module_id) || ignore_errors) {
}
-/*
- * XXX: This is currently the hottest function while building the file
- * list, because building f_name()s every time is expensive.
- **/
int file_compare(struct file_struct **f1,struct file_struct **f2)
{
if (!(*f1)->basename && !(*f2)->basename) return 0;
}
}
- /* FIXME: There is a bug here when filenames are repeated more
- * than once, because we don't handle freed files when doing
- * the comparison. */
-
if (strip_root) {
/* we need to strip off the root directory in the case
of relative paths, but this must be done _after_
for (i=0;i<flist->count;i++) {
rprintf(FINFO,"[%d] i=%d %s %s mode=0%o len=%.0f\n",
- (int) getpid(), i,
+ getpid(), i,
NS(flist->files[i]->dirname),
NS(flist->files[i]->basename),
- (int) flist->files[i]->mode,
+ flist->files[i]->mode,
(double)flist->files[i]->length);
}
}
/*
* return the full filename of a flist entry
- *
- * This function is too expensive at the moment, because it copies
- * strings when often we only want to compare them. In any case,
- * using strlcat is silly because it will walk the string repeatedly.
*/
char *f_name(struct file_struct *f)
{
n = (n+1)%10;
if (f->dirname) {
- int off;
-
- off = strlcpy(p, f->dirname, MAXPATHLEN);
- off += strlcpy(p+off, "/", MAXPATHLEN-off);
- off += strlcpy(p+off, f->basename, MAXPATHLEN-off);
+ strlcpy(p, f->dirname, MAXPATHLEN);
+ strlcat(p, "/", MAXPATHLEN);
+ strlcat(p, f->basename, MAXPATHLEN);
} else {
strlcpy(p, f->basename, MAXPATHLEN);
}
-/* -*- c-file-style: "linux" -*-
-
- Copyright (C) 1996-2001 by Andrew Tridgell
+/*
+ Copyright (C) Andrew Tridgell 1996
Copyright (C) Paul Mackerras 1996
- Copyright (C) 2001 by Martin Pool <mbp@samba.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
/* if no timeout is specified then use a 60 second select timeout */
#define SELECT_TIMEOUT 60
+extern int bwlimit;
+
static int io_multiplexing_out;
static int io_multiplexing_in;
static int multiplex_in_fd;
static int multiplex_out_fd;
static time_t last_io;
-static int no_flush;
-
-extern int bwlimit;
+static int eof_error=1;
extern int verbose;
extern int io_timeout;
extern struct stats stats;
-
-/** Ignore EOF errors while reading a module listing if the remote
- version is 24 or less. */
-int kludge_around_eof = False;
-
-
static int io_error_fd = -1;
static void read_loop(int fd, char *buf, size_t len);
{
extern int am_server, am_daemon;
time_t t;
-
- err_list_push();
if (!io_timeout) return;
if (last_io && io_timeout && (t-last_io) >= io_timeout) {
if (!am_server && !am_daemon) {
- rprintf(FERROR,"io timeout after %d seconds - exiting\n",
+ rprintf(FERROR,"io timeout after %d second - exiting\n",
(int)(t-last_io));
}
exit_cleanup(RERR_TIMEOUT);
static void read_error_fd(void)
{
char buf[200];
- size_t n;
+ int n;
int fd = io_error_fd;
int tag, len;
- /* io_error_fd is temporarily disabled -- is this meant to
- * prevent indefinite recursion? */
io_error_fd = -1;
read_loop(fd, buf, 4);
while (len) {
n = len;
- if (n > (sizeof(buf)-1))
- n = sizeof(buf)-1;
+ if (n > (sizeof(buf)-1)) n = sizeof(buf)-1;
read_loop(fd, buf, n);
rwrite((enum logcode)tag, buf, n);
len -= n;
}
-static void whine_about_eof (void)
-{
- /**
- It's almost always an error to get an EOF when we're trying
- to read from the network, because the protocol is
- self-terminating.
-
- However, there is one unfortunate cases where it is not,
- which is rsync <2.4.6 sending a list of modules on a
- server, since the list is terminated by closing the socket.
- So, for the section of the program where that is a problem
- (start_socket_client), kludge_around_eof is True and we
- just exit.
- */
-
- if (kludge_around_eof)
- exit_cleanup (0);
- else {
- rprintf (FERROR,
- "%s: connection unexpectedly closed "
- "(%.0f bytes read so far)\n",
- RSYNC_NAME, (double)stats.total_read);
-
- exit_cleanup (RERR_STREAMIO);
- }
-}
-
-
-static void die_from_readerr (int err)
-{
- /* this prevents us trying to write errors on a dead socket */
- io_multiplexing_close();
-
- rprintf(FERROR, "%s: read error: %s\n",
- RSYNC_NAME, strerror (err));
- exit_cleanup(RERR_STREAMIO);
-}
-
+static int no_flush;
-/*!
- * Read from a socket with IO timeout. return the number of bytes
- * read. If no bytes can be read then exit, never return a number <= 0.
- *
- * TODO: If the remote shell connection fails, then current versions
- * actually report an "unexpected EOF" error here. Since it's a
- * fairly common mistake to try to use rsh when ssh is required, we
- * should trap that: if we fail to read any data at all, we should
- * give a better explanation. We can tell whether the connection has
- * started by looking e.g. at whether the remote version is known yet.
- */
-static int read_timeout (int fd, char *buf, size_t len)
+/* read from a socket with IO timeout. return the number of
+ bytes read. If no bytes can be read then exit, never return
+ a number <= 0 */
+static int read_timeout(int fd, char *buf, size_t len)
{
int n, ret=0;
io_flush();
while (ret == 0) {
- /* until we manage to read *something* */
fd_set fds;
struct timeval tv;
int fd_count = fd+1;
- int count;
FD_ZERO(&fds);
FD_SET(fd, &fds);
errno = 0;
- count = select(fd_count, &fds, NULL, NULL, &tv);
-
- if (count == 0) {
- check_timeout();
- }
-
- if (count <= 0) {
+ if (select(fd_count, &fds, NULL, NULL, &tv) < 1) {
if (errno == EBADF) {
exit_cleanup(RERR_SOCKETIO);
}
+ check_timeout();
continue;
}
if (io_timeout)
last_io = time(NULL);
continue;
- } else if (n == 0) {
- whine_about_eof ();
- return -1; /* doesn't return */
- } else if (n == -1) {
- if (errno == EINTR || errno == EWOULDBLOCK ||
- errno == EAGAIN)
- continue;
- else
- die_from_readerr (errno);
}
- }
- return ret;
-}
+ if (n == -1 && errno == EINTR) {
+ continue;
+ }
+
+ if (n == -1 &&
+ (errno == EWOULDBLOCK || errno == EAGAIN)) {
+ continue;
+ }
+ if (n == 0) {
+ if (eof_error) {
+ rprintf(FERROR,"unexpected EOF in read_timeout\n");
+ }
+ exit_cleanup(RERR_STREAMIO);
+ }
+ /* this prevents us trying to write errors on a dead socket */
+ io_multiplexing_close();
+
+ rprintf(FERROR,"read error: %s\n", strerror(errno));
+ exit_cleanup(RERR_STREAMIO);
+ }
-/*! Continue trying to read len bytes - don't return until len has
- been read. */
-static void read_loop (int fd, char *buf, size_t len)
+ return ret;
+}
+
+/* continue trying to read len bytes - don't return until len
+ has been read */
+static void read_loop(int fd, char *buf, size_t len)
{
while (len) {
int n = read_timeout(fd, buf, len);
}
}
-
-/**
- * Read from the file descriptor handling multiplexing - return number
- * of bytes read.
- *
- * Never returns <= 0.
- */
+/* read from the file descriptor handling multiplexing -
+ return number of bytes read
+ never return <= 0 */
static int read_unbuffered(int fd, char *buf, size_t len)
{
- static size_t remaining;
- int tag, ret = 0;
+ static int remaining;
+ int tag, ret=0;
char line[1024];
- if (!io_multiplexing_in || fd != multiplex_in_fd)
+ if (!io_multiplexing_in || fd != multiplex_in_fd)
return read_timeout(fd, buf, len);
while (ret == 0) {
remaining = tag & 0xFFFFFF;
tag = tag >> 24;
- if (tag == MPLEX_BASE)
- continue;
+ if (tag == MPLEX_BASE) continue;
tag -= MPLEX_BASE;
if (tag != FERROR && tag != FINFO) {
- rprintf(FERROR, "unexpected tag %d\n", tag);
+ rprintf(FERROR,"unexpected tag %d\n", tag);
exit_cleanup(RERR_STREAMIO);
}
- if (remaining > sizeof(line) - 1) {
- rprintf(FERROR, "multiplexing overflow %d\n\n",
+ if (remaining > sizeof(line)-1) {
+ rprintf(FERROR,"multiplexing overflow %d\n\n",
remaining);
exit_cleanup(RERR_STREAMIO);
}
read_loop(fd, line, remaining);
line[remaining] = 0;
- rprintf((enum logcode) tag, "%s", line);
+ rprintf((enum logcode)tag,"%s", line);
remaining = 0;
}
}
-
/* do a buffered read from fd. don't return until all N bytes
have been read. If all N can't be read then exit with an error */
-static void readfd (int fd, char *buffer, size_t N)
+static void readfd(int fd,char *buffer,size_t N)
{
int ret;
- size_t total=0;
+ int total=0;
while (total < N) {
io_flush();
- ret = read_unbuffered (fd, buffer + total, N-total);
+ ret = read_unbuffered(fd,buffer + total,N-total);
total += ret;
}
void read_sbuf(int f,char *buf,size_t len)
{
- read_buf (f,buf,len);
+ read_buf(f,buf,len);
buf[len] = 0;
}
unsigned char read_byte(int f)
{
unsigned char c;
- read_buf (f, (char *)&c, 1);
+ read_buf(f,(char *)&c,1);
return c;
}
/* write len bytes to fd */
static void writefd_unbuffered(int fd,char *buf,size_t len)
{
- size_t total = 0;
+ int total = 0;
fd_set w_fds, r_fds;
int fd_count, count;
struct timeval tv;
- err_list_push();
-
no_flush++;
while (total < len) {
&w_fds,NULL,
&tv);
- if (count == 0) {
- check_timeout();
- }
-
if (count <= 0) {
if (errno == EBADF) {
exit_cleanup(RERR_SOCKETIO);
}
+ check_timeout();
continue;
}
}
if (FD_ISSET(fd, &w_fds)) {
- int ret;
- size_t n = len-total;
+ int ret, n = len-total;
+
ret = write(fd,buf+total,n);
if (ret == -1 && errno == EINTR) {
}
if (ret <= 0) {
- rprintf(FERROR,
- "error writing %d unbuffered bytes"
- " - exiting: %s\n", len,
- strerror(errno));
+ rprintf(FERROR,"erroring writing %d bytes - exiting\n", len);
exit_cleanup(RERR_STREAMIO);
}
static void mplex_write(int fd, enum logcode code, char *buf, size_t len)
{
char buffer[4096];
- size_t n = len;
+ int n = len;
SIVAL(buffer, 0, ((MPLEX_BASE + (int)code)<<24) + len);
void io_flush(void)
{
int fd = multiplex_out_fd;
-
- err_list_push();
-
if (!io_buffer_count || no_flush) return;
if (io_multiplexing_out) {
io_buffer_count = 0;
}
-
-/* XXX: fd is ignored, which seems a little strange. */
void io_end_buffering(int fd)
{
io_flush();
}
}
+/* some OSes have a bug where an exit causes the pending writes on
+ a socket to be flushed. Do an explicit shutdown to try to prevent this */
+void io_shutdown(void)
+{
+ if (multiplex_out_fd != -1) close(multiplex_out_fd);
+ if (io_error_fd != -1) close(io_error_fd);
+ multiplex_out_fd = -1;
+ io_error_fd = -1;
+}
+
+
static void writefd(int fd,char *buf,size_t len)
{
stats.total_written += len;
- err_list_push();
-
if (!io_buffer || fd != multiplex_out_fd) {
writefd_unbuffered(fd, buf, len);
return;
writefd(f,b,4);
}
-
-/*
- * Note: int64 may actually be a 32-bit type if ./configure couldn't find any
- * 64-bit types on this platform.
- */
void write_longint(int f, int64 x)
{
extern int remote_version;
write_buf(f,(char *)&c,1);
}
-
-
int read_line(int f, char *buf, size_t maxlen)
{
+ eof_error = 0;
+
while (maxlen) {
buf[0] = 0;
read_buf(f, buf, 1);
return 0;
}
+ eof_error = 1;
+
return 1;
}
int len;
va_start(ap, format);
- len = vsnprintf(buf, sizeof(buf), format, ap);
+ len = vslprintf(buf, sizeof(buf), format, ap);
va_end(ap);
if (len < 0) exit_cleanup(RERR_STREAMIO);
return 1;
}
+/* write a message to the special error fd */
+int io_error_write(int f, enum logcode code, char *buf, size_t len)
+{
+ if (f == -1) return 0;
+ mplex_write(f, code, buf, len);
+ return 1;
+}
+
/* stop output multiplexing */
void io_multiplexing_close(void)
{
-/* -*- c-file-style: "linux"; -*-
-
- Copyright (C) 1998-2001 by Andrew Tridgell <tridge@samba.org>
- Copyright (C) 2000-2001 by Martin Pool <mbp@samba.org>
+/*
+ Copyright (C) Andrew Tridgell 1998
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
*/
/*
- Logging and utility functions.
- tridge, May 1998
+ logging and utility functions
- Mapping to human-readable messages added by Martin Pool
- <mbp@samba.org>, Oct 2000.
+ tridge, May 1998
*/
#include "rsync.h"
-static char *logfname;
static FILE *logfile;
static int log_error_fd = -1;
-int log_got_error=0;
-
-struct {
- int code;
- char const *name;
-} const rerr_names[] = {
- { RERR_SYNTAX , "syntax or usage error" },
- { RERR_PROTOCOL , "protocol incompatibility" },
- { RERR_FILESELECT , "errors selecting input/output files, dirs" },
- { RERR_UNSUPPORTED, "requested action not supported" },
- { RERR_SOCKETIO , "error in socket IO" },
- { RERR_FILEIO , "error in file IO" },
- { RERR_STREAMIO , "error in rsync protocol data stream" },
- { RERR_MESSAGEIO , "errors with program diagnostics" },
- { RERR_IPC , "error in IPC code" },
- { RERR_SIGNAL , "received SIGUSR1 or SIGINT" },
- { RERR_WAITCHILD , "some error returned by waitpid()" },
- { RERR_MALLOC , "error allocating core memory buffers" },
- { RERR_PARTIAL , "partial transfer" },
- { RERR_TIMEOUT , "timeout in data send/receive" },
- { RERR_CMD_FAILED , "remote shell failed" },
- { RERR_CMD_KILLED , "remote shell killed" },
- { RERR_CMD_RUN, "remote command could not be run" },
- { RERR_CMD_NOTFOUND, "remote command not found" },
- { 0, NULL }
-};
-
-
-
-/*
- * Map from rsync error code to name, or return NULL.
- */
-static char const *rerr_name(int code)
-{
- int i;
- for (i = 0; rerr_names[i].name; i++) {
- if (rerr_names[i].code == code)
- return rerr_names[i].name;
- }
- return NULL;
-}
-
-struct err_list {
- struct err_list *next;
- char *buf;
- int len;
- int written; /* how many bytes we have written so far */
-};
-
-static struct err_list *err_list_head;
-static struct err_list *err_list_tail;
-
-/* add an error message to the pending error list */
-static void err_list_add(int code, char *buf, int len)
-{
- struct err_list *el;
- el = (struct err_list *)malloc(sizeof(*el));
- if (!el) exit_cleanup(RERR_MALLOC);
- el->next = NULL;
- el->buf = malloc(len+4);
- if (!el->buf) exit_cleanup(RERR_MALLOC);
- memcpy(el->buf+4, buf, len);
- SIVAL(el->buf, 0, ((code+MPLEX_BASE)<<24) | len);
- el->len = len+4;
- el->written = 0;
- if (err_list_tail) {
- err_list_tail->next = el;
- } else {
- err_list_head = el;
- }
- err_list_tail = el;
-}
-
-
-/* try to push errors off the error list onto the wire */
-void err_list_push(void)
-{
- if (log_error_fd == -1) return;
-
- while (err_list_head) {
- struct err_list *el = err_list_head;
- int n = write(log_error_fd, el->buf+el->written, el->len - el->written);
- /* don't check for an error if the best way of handling the error is
- to ignore it */
- if (n == -1) break;
- if (n > 0) {
- el->written += n;
- }
- if (el->written == el->len) {
- free(el->buf);
- err_list_head = el->next;
- if (!err_list_head) err_list_tail = NULL;
- free(el);
- }
- }
-}
-
-
static void logit(int priority, char *buf)
{
- if (logfname) {
- if (!logfile)
- log_open();
+ if (logfile) {
fprintf(logfile,"%s [%d] %s",
timestring(time(NULL)), (int)getpid(), buf);
fflush(logfile);
}
}
-void log_init(void)
+void log_open(void)
{
static int initialised;
int options = LOG_PID;
time_t t;
+ char *logf;
if (initialised) return;
initialised = 1;
localtime(&t);
/* optionally use a log file instead of syslog */
- logfname = lp_log_file();
- if (logfname) {
- if (*logfname) {
- log_open();
- return;
- }
- logfname = NULL;
+ logf = lp_log_file();
+ if (logf && *logf) {
+ extern int orig_umask;
+ int old_umask = umask(022 | orig_umask);
+ logfile = fopen(logf, "a");
+ umask(old_umask);
+ return;
}
#ifdef LOG_NDELAY
#endif
}
-void log_open()
-{
- if (logfname && !logfile) {
- extern int orig_umask;
- int old_umask = umask(022 | orig_umask);
- logfile = fopen(logfname, "a");
- umask(old_umask);
- }
-}
-
-void log_close()
-{
- if (logfile) {
- fclose(logfile);
- logfile = NULL;
- }
-}
-
/* setup the error file descriptor - used when we are a server
that is receiving files */
void set_error_fd(int fd)
{
log_error_fd = fd;
- set_nonblocking(log_error_fd);
}
/* this is the underlying (unformatted) rsync debugging function. Call
return;
}
- /* first try to pass it off to our sibling */
- if (am_server && log_error_fd != -1) {
- err_list_add(code, buf, len);
- err_list_push();
+ /* first try to pass it off the our sibling */
+ if (am_server && io_error_write(log_error_fd, code, buf, len)) {
return;
}
- /* if that fails, try to pass it to the other end */
+ /* then try to pass it to the other end */
if (am_server && io_multiplex_write(code, buf, len)) {
return;
}
depth++;
- log_init();
+ log_open();
logit(priority, buf);
depth--;
}
if (code == FERROR) {
- log_got_error = 1;
f = stderr;
}
}
-/* This is the rsync debugging function. Call it with FINFO, FERROR or
- * FLOG. */
-void rprintf(enum logcode code, const char *format, ...)
-{
- va_list ap;
- char buf[1024];
- int len;
-
- va_start(ap, format);
- /* Note: might return -1 */
- len = vsnprintf(buf, sizeof(buf), format, ap);
- va_end(ap);
-
- /* Deal with buffer overruns. Instead of panicking, just
- * truncate the resulting string. Note that some vsnprintf()s
- * return -1 on truncation, e.g., glibc 2.0.6 and earlier. */
- if ((size_t) len > sizeof(buf)-1 || len < 0) {
- const char ellipsis[] = "[...]";
-
- /* Reset length, and zero-terminate the end of our buffer */
- len = sizeof(buf)-1;
- buf[len] = '\0';
-
- /* Copy the ellipsis to the end of the string, but give
- * us one extra character:
- *
- * v--- null byte at buf[sizeof(buf)-1]
- * abcdefghij0
- * -> abcd[...]00 <-- now two null bytes at end
- *
- * If the input format string has a trailing newline,
- * we copy it into that extra null; if it doesn't, well,
- * all we lose is one byte. */
- strncpy(buf+len-sizeof(ellipsis), ellipsis, sizeof(ellipsis));
- if (format[strlen(format)-1] == '\n') {
- buf[len-1] = '\n';
- }
- }
-
- rwrite(code, buf, len);
-}
-
-
-/* This is like rprintf, but it also tries to print some
- * representation of the error code. Normally errcode = errno.
- *
- * Unlike rprintf, this always adds a newline and there should not be
- * one in the format string.
- *
- * Note that since strerror might involve dynamically loading a
- * message catalog we need to call it once before chroot-ing. */
-void rsyserr(enum logcode code, int errcode, const char *format, ...)
+/* this is the rsync debugging function. Call it with FINFO, FERROR or FLOG */
+ void rprintf(enum logcode code, const char *format, ...)
{
va_list ap;
char buf[1024];
int len;
- size_t sys_len;
- char *sysmsg;
va_start(ap, format);
- /* Note: might return <0 */
- len = vsnprintf(buf, sizeof(buf), format, ap);
+ len = vslprintf(buf, sizeof(buf), format, ap);
va_end(ap);
- if ((size_t) len > sizeof(buf)-1)
- exit_cleanup(RERR_MESSAGEIO);
-
- sysmsg = strerror(errcode);
- sys_len = strlen(sysmsg);
- if ((size_t) len + 3 + sys_len > sizeof(buf) - 1)
- exit_cleanup(RERR_MESSAGEIO);
-
- strcpy(buf + len, ": ");
- len += 2;
- strcpy(buf + len, sysmsg);
- len += sys_len;
- strcpy(buf + len, "\n");
- len++;
+ if (len > sizeof(buf)-1) exit_cleanup(RERR_MESSAGEIO);
rwrite(code, buf, len);
}
-
-
void rflush(enum logcode code)
{
FILE *f = NULL;
char buf[1024];
char buf2[1024];
char *p, *s, *n;
- size_t l;
+ int l;
extern struct stats stats;
extern int am_sender;
extern int am_daemon;
int64 b;
- /* We expand % codes one by one in place in buf. We don't
- * copy in the terminating nul of the inserted strings, but
- * rather keep going until we reach the nul of the format.
- * Just to make sure we don't clobber that nul and therefore
- * accidentally keep going, we zero the buffer now. */
- memset(buf, 0, sizeof buf);
+ memset(buf,0,sizeof(buf));
+
strlcpy(buf, format, sizeof(buf));
for (s=&buf[0];
case 'h': if (am_daemon) n = client_name(0); break;
case 'a': if (am_daemon) n = client_addr(0); break;
case 'l':
- snprintf(buf2,sizeof(buf2),"%.0f",
+ slprintf(buf2,sizeof(buf2),"%.0f",
(double)file->length);
n = buf2;
break;
case 'p':
- snprintf(buf2,sizeof(buf2),"%d",
+ slprintf(buf2,sizeof(buf2),"%d",
(int)getpid());
n = buf2;
break;
case 'o': n = op; break;
case 'f':
- snprintf(buf2, sizeof(buf2), "%s/%s",
+ slprintf(buf2, sizeof(buf2), "%s/%s",
file->basedir?file->basedir:"",
f_name(file));
clean_fname(buf2);
b = stats.total_read -
initial_stats->total_read;
}
- snprintf(buf2,sizeof(buf2),"%.0f", (double)b);
+ slprintf(buf2,sizeof(buf2),"%.0f", (double)b);
n = buf2;
break;
case 'c':
b = stats.total_read -
initial_stats->total_read;
}
- snprintf(buf2,sizeof(buf2),"%.0f", (double)b);
+ slprintf(buf2,sizeof(buf2),"%.0f", (double)b);
n = buf2;
break;
}
- /* n is the string to be inserted in place of this %
- * code; l is its length not including the trailing
- * NUL */
- if (!n)
- continue;
+ if (!n) continue;
l = strlen(n);
- if (l + ((int)(s - &buf[0])) >= sizeof(buf)) {
+ if (l + ((int)(s - &buf[0])) > sizeof(buf)) {
rprintf(FERROR,"buffer overflow expanding %%%c - exiting\n",
p[0]);
exit_cleanup(RERR_MESSAGEIO);
}
- /* Shuffle the rest of the string along to make space for n */
if (l != 2) {
memmove(s+(l-1), s+1, strlen(s+1)+1);
}
-
- /* Copy in n but NOT its nul, because the format sting
- * probably continues after this. */
memcpy(p, n, l);
- /* Skip over inserted string; continue looking */
s = p+l;
}
}
}
-
-
-
-/*
- * Called when the transfer is interrupted for some reason.
- *
- * Code is one of the RERR_* codes from errcode.h, or terminating
- * successfully.
- */
+/* called when the transfer is interrupted for some reason */
void log_exit(int code, const char *file, int line)
{
if (code == 0) {
(double)stats.total_read,
(double)stats.total_size);
} else {
- const char *name;
-
- name = rerr_name(code);
- if (!name)
- name = "unexplained error";
-
- rprintf(FERROR,"rsync error: %s (code %d) at %s(%d)\n",
- name, code, file, line);
+ rprintf(FLOG,"transfer interrupted (code %d) at %s(%d)\n",
+ code, file, line);
}
}
-
-
-
/* log the incoming transfer of a file for interactive use, this
will be called at the end where the client was run
-/* -*- c-file-style: "linux" -*-
-
- Copyright (C) 1996-2000 by Andrew Tridgell
+/*
+ Copyright (C) Andrew Tridgell 1996
Copyright (C) Paul Mackerras 1996
This program is free software; you can redistribute it and/or modify
extern char *backup_suffix;
static struct delete_list {
- DEV64_T dev;
- INO64_T inode;
+ dev_t dev;
+ INO_T inode;
} *delete_list;
static int dlist_len, dlist_alloc_len;
{
if (!S_ISDIR(f->mode)) {
if (robust_unlink(f_name(f)) != 0) {
- rprintf(FERROR,"delete_one: unlink %s: %s\n",f_name(f),strerror(errno));
+ rprintf(FERROR,"unlink %s : %s\n",f_name(f),strerror(errno));
} else if (verbose) {
rprintf(FINFO,"deleting %s\n",f_name(f));
}
} else {
if (do_rmdir(f_name(f)) != 0) {
if (errno != ENOTEMPTY && errno != EEXIST)
- rprintf(FERROR,"delete_one: rmdir %s: %s\n",
- f_name(f), strerror(errno));
+ rprintf(FERROR,"rmdir %s : %s\n",f_name(f),strerror(errno));
} else if (verbose) {
rprintf(FINFO,"deleting directory %s\n",f_name(f));
}
rprintf(FERROR,"filename too long\n");
return 0;
}
- snprintf(fnametmp,MAXPATHLEN, "%s/.%s.XXXXXX",tmpdir,f);
+ slprintf(fnametmp,MAXPATHLEN, "%s/.%s.XXXXXX",tmpdir,f);
return 1;
}
if (f) {
*f = 0;
- snprintf(fnametmp,MAXPATHLEN,"%s/.%s.XXXXXX",
+ slprintf(fnametmp,MAXPATHLEN,"%s/.%s.XXXXXX",
fname,f+1);
*f = '/';
} else {
- snprintf(fnametmp,MAXPATHLEN,".%s.XXXXXX",fname);
+ slprintf(fnametmp,MAXPATHLEN,".%s.XXXXXX",fname);
}
return 1;
int fd1,fd2;
STRUCT_STAT st;
char *fname;
- char template[MAXPATHLEN];
char fnametmp[MAXPATHLEN];
char *fnamecmp;
char fnamecmpbuf[MAXPATHLEN];
if ((fd1 == -1) && (compare_dest != NULL)) {
/* try the file at compare_dest instead */
- snprintf(fnamecmpbuf,MAXPATHLEN,"%s/%s",
+ slprintf(fnamecmpbuf,MAXPATHLEN,"%s/%s",
compare_dest,fname);
fnamecmp = fnamecmpbuf;
fd1 = do_open(fnamecmp, O_RDONLY, 0);
continue;
}
- strlcpy(template, fnametmp, sizeof(template));
+ /* mktemp is deliberately used here instead of mkstemp.
+ because O_EXCL is used on the open, the race condition
+ is not a problem or a security hole, and we want to
+ control the access permissions on the created file. */
+ if (NULL == do_mktemp(fnametmp)) {
+ rprintf(FERROR,"mktemp %s failed\n",fnametmp);
+ receive_data(f_in,buf,-1,NULL,file->length);
+ if (buf) unmap_file(buf);
+ if (fd1 != -1) close(fd1);
+ continue;
+ }
/* we initially set the perms without the
setuid/setgid bits to ensure that there is no race
the lchown. Thanks to snabb@epipe.fi for pointing
this out. We also set it initially without group
access because of a similar race condition. */
- fd2 = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS);
- if (fd2 == -1) {
- rprintf(FERROR,"mkstemp %s failed\n",fnametmp);
- receive_data(f_in,buf,-1,NULL,file->length);
- if (buf) unmap_file(buf);
- continue;
- }
+ fd2 = do_open(fnametmp,O_WRONLY|O_CREAT|O_EXCL,
+ file->mode & INITACCESSPERMS);
/* in most cases parent directories will already exist
because their information should have been previously
transferred, but that may not be the case with -R */
if (fd2 == -1 && relative_paths && errno == ENOENT &&
create_directory_path(fnametmp) == 0) {
- strlcpy(fnametmp, template, sizeof(fnametmp));
- fd2 = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS);
+ fd2 = do_open(fnametmp,O_WRONLY|O_CREAT|O_EXCL,
+ file->mode & INITACCESSPERMS);
}
if (fd2 == -1) {
rprintf(FERROR,"cannot create %s : %s\n",fnametmp,strerror(errno));
}
if (preserve_hard_links)
- do_hard_links();
+ do_hard_links(flist);
/* now we need to fix any directory permissions that were
modified during the transfer */
/*
- Copyright (C) by Andrew Tridgell 1996, 2000
+ Copyright (C) Andrew Tridgell 1996
Copyright (C) Paul Mackerras 1996
- Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-
#define False 0
#define True 1
#define SAME_TIME (1<<7)
/* update this if you make incompatible changes */
-#define PROTOCOL_VERSION 26
-
-/* We refuse to interoperate with versions that are not in this range.
- * Note that we assume we'll work with later versions: the onus is on
- * people writing them to make sure that they don't send us anything
- * we won't understand.
- *
- * There are two possible explanations for the limit at thirty: either
- * to allow new major-rev versions that do not interoperate with us,
- * and (more likely) so that we can detect an attempt to connect rsync
- * to a non-rsync server, which is unlikely to begin by sending a byte
- * between 15 and 30. */
+#define PROTOCOL_VERSION 24
#define MIN_PROTOCOL_VERSION 15
#define MAX_PROTOCOL_VERSION 30
#define MPLEX_BASE 7
-/* Log values. I *think* what these mean is: FLOG goes to the server
- * logfile; FERROR and FINFO try to end up on the client, with
- * different levels of filtering. */
-enum logcode {FNONE=0, FERROR=1, FINFO=2, FLOG=3 };
+enum logcode {FNONE=0, FERROR=1, FINFO=2, FLOG=3};
#include "errcode.h"
#include <sys/types.h>
+#ifdef HAVE_GETOPT_LONG
+#include <getopt.h>
+#else
+#include "lib/getopt.h"
+#endif
+
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <glob.h>
#endif
-#ifdef HAVE_MALLOC_H
-# include <malloc.h>
-#endif
-
/* these are needed for the uid/gid mapping code */
#include <pwd.h>
#include <grp.h>
#elif HAVE_LONGLONG
#define int64 long long
#else
-/* As long as it gets... */
#define int64 off_t
#define NO_INT64
#endif
-/* Starting from protocol version 26, we always use 64-bit
- * ino_t and dev_t internally, even if this platform does not
- * allow files to have 64-bit inums. That's because the
- * receiver needs to find duplicate (dev,ino) tuples to detect
- * hardlinks, and it might have files coming from a platform
- * that has 64-bit inums.
- *
- * The only exception is if we're on a platform with no 64-bit type at
- * all.
- *
- * Because we use read_longint() to get these off the wire, if you
- * transfer devices or hardlinks with dev or inum > 2**32 to a machine
- * with no 64-bit types then you will get an overflow error. Probably
- * not many people have that combination of machines, and you can
- * avoid it by not preserving hardlinks or not transferring device
- * nodes. It's not clear that any other behaviour is better.
- *
- * Note that if you transfer devices from a 64-bit-devt machine (say,
- * Solaris) to a 32-bit-devt machine (say, Linux-2.2/x86) then the
- * device numbers will be truncated. But it's a kind of silly thing
- * to do anyhow.
- *
- * FIXME: In future, we should probable split the device number into
- * major/minor, and transfer the two parts as 32-bit ints. That gives
- * you somewhat more of a chance that they'll come from a big machine
- * to a little one in a useful way.
- *
- * FIXME: Really we need an unsigned type, and we perhaps ought to
- * cope with platforms on which this is an unsigned int or even a
- * struct. Later.
- */
-#define INO64_T int64
-#define DEV64_T int64
+#if HAVE_SHORT_INO_T
+#define INO_T uint32
+#else
+#define INO_T ino_t
+#endif
#ifndef MIN
#define MIN(a,b) ((a)<(b)?(a):(b))
time_t modtime;
OFF_T length;
mode_t mode;
-
- INO64_T inode;
- /** Device this file lives upon */
- DEV64_T dev;
-
- /** If this is a device node, the device number. */
- DEV64_T rdev;
+ INO_T inode;
+ dev_t dev;
+ dev_t rdev;
uid_t uid;
gid_t gid;
char *basename;
};
struct sum_struct {
- OFF_T flength; /* total file length */
- size_t count; /* how many chunks */
- size_t remainder; /* flength % block_length */
- size_t n; /* block_length */
- struct sum_buf *sums; /* points to info for each chunk */
+ OFF_T flength; /* total file length */
+ size_t count; /* how many chunks */
+ size_t remainder; /* flength % block_length */
+ size_t n; /* block_length */
+ struct sum_buf *sums; /* points to info for each chunk */
};
struct map_struct {
};
struct exclude_struct {
+ char *orig;
char *pattern;
int regular_exp;
int fnmatch_flags;
}
#include "byteorder.h"
-#include "lib/mdfour.h"
-#include "lib/permstring.h"
-#include "lib/addrinfo.h"
-
+#include "version.h"
#include "proto.h"
-
-/* We have replacement versions of these if they're missing. */
-#ifndef HAVE_ASPRINTF
-int asprintf(char **ptr, const char *format, ...);
-#endif
-
-#ifndef HAVE_VASPRINTF
-int vasprintf(char **ptr, const char *format, va_list ap);
-#endif
-
-#if !defined(HAVE_VSNPRINTF) && !defined(HAVE_C99_VSNPRINTF)
-int vsnprintf (char *str, size_t count, const char *fmt, va_list args);
-#endif
-
-#if !defined(HAVE_SNPRINTF) && !defined(HAVE_C99_VSNPRINTF)
-int snprintf(char *str,size_t count,const char *fmt,...);
-#endif
-
+#include "lib/mdfour.h"
#if !HAVE_STRERROR
extern char *sys_errlist[];
# define NONBLOCK_FLAG FNDELAY
#endif
-#ifndef INADDR_LOOPBACK
-#define INADDR_LOOPBACK 0x7f000001
-#endif
-
-#ifndef INADDR_NONE
-#define INADDR_NONE 0xffffffff
-#endif
#define IS_DEVICE(mode) (S_ISCHR(mode) || S_ISBLK(mode) || S_ISSOCK(mode) || S_ISFIFO(mode))
#endif
;
-/* This is just like rprintf, but it also tries to print some
- * representation of the error code. Normally errcode = errno. */
-void rsyserr(enum logcode, int, const char *, ...)
-#ifdef __GNUC__
- __attribute__ ((format (printf, 3, 4)))
-#endif
- ;
-
#ifdef REPLACE_INET_NTOA
#define inet_ntoa rep_inet_ntoa
#endif
#endif
#define exit_cleanup(code) _exit_cleanup(code, __FILE__, __LINE__)
-
-
-extern int verbose;
-
-#ifndef HAVE_INET_NTOP
-const char *
-inet_ntop(int af, const void *src, char *dst, size_t size);
-#endif /* !HAVE_INET_NTOP */
-
-#ifndef HAVE_INET_PTON
-int isc_net_pton(int af, const char *src, void *dst);
-#endif
-/* -*- c-file-style: "linux" -*-
-
- Copyright (C) 1996-2000 by Andrew Tridgell
- Copyright (C) Paul Mackerras 1996
- Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
+/*
+ Copyright (C) Andrew Tridgell 1996
+ Copyright (C) Paul Mackerras 1996
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
}
-void print_child_argv(char **cmd)
-{
- rprintf(FINFO, RSYNC_NAME ": open connection using ");
- for (; *cmd; cmd++) {
- /* Look for characters that ought to be quoted. This
- * is not a great quoting algorithm, but it's
- * sufficient for a log message. */
- if (strspn(*cmd, "abcdefghijklmnopqrstuvwxyz"
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "0123456789"
- ",.-_=+@/") != strlen(*cmd)) {
- rprintf(FINFO, "\"%s\" ", *cmd);
- } else {
- rprintf(FINFO, "%s ", *cmd);
- }
- }
- rprintf(FINFO, "\n");
-}
-
-
/* this is derived from CVS code
note that in the child STDIN is set to blocking and STDOUT
used to cope with badly broken rsh implementations like the one on
solaris.
*/
-pid_t piped_child(char **command, int *f_in, int *f_out)
-{
- pid_t pid;
- int to_child_pipe[2];
- int from_child_pipe[2];
- extern int blocking_io;
-
- if (verbose > 0) {
- print_child_argv(command);
- }
-
- if (fd_pair(to_child_pipe) < 0 || fd_pair(from_child_pipe) < 0) {
- rprintf(FERROR, "pipe: %s\n", strerror(errno));
- exit_cleanup(RERR_IPC);
- }
-
-
- pid = do_fork();
- if (pid == -1) {
- rprintf(FERROR, "fork: %s\n", strerror(errno));
- exit_cleanup(RERR_IPC);
- }
-
- if (pid == 0) {
- extern int orig_umask;
- if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 ||
- close(to_child_pipe[1]) < 0 ||
- close(from_child_pipe[0]) < 0 ||
- dup2(from_child_pipe[1], STDOUT_FILENO) < 0) {
- rprintf(FERROR, "Failed to dup/close : %s\n",
- strerror(errno));
- exit_cleanup(RERR_IPC);
- }
- if (to_child_pipe[0] != STDIN_FILENO)
- close(to_child_pipe[0]);
- if (from_child_pipe[1] != STDOUT_FILENO)
- close(from_child_pipe[1]);
- umask(orig_umask);
- set_blocking(STDIN_FILENO);
- if (blocking_io) {
- set_blocking(STDOUT_FILENO);
- }
- execvp(command[0], command);
- rprintf(FERROR, "Failed to exec %s : %s\n",
- command[0], strerror(errno));
- exit_cleanup(RERR_IPC);
- }
+int piped_child(char **command,int *f_in,int *f_out)
+{
+ int pid;
+ int to_child_pipe[2];
+ int from_child_pipe[2];
+ extern int blocking_io;
+
+ if (fd_pair(to_child_pipe) < 0 ||
+ fd_pair(from_child_pipe) < 0) {
+ rprintf(FERROR,"pipe: %s\n",strerror(errno));
+ exit_cleanup(RERR_IPC);
+ }
+
+
+ pid = do_fork();
+ if (pid < 0) {
+ rprintf(FERROR,"fork: %s\n",strerror(errno));
+ exit_cleanup(RERR_IPC);
+ }
+
+ if (pid == 0)
+ {
+ extern int orig_umask;
+ if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 ||
+ close(to_child_pipe[1]) < 0 ||
+ close(from_child_pipe[0]) < 0 ||
+ dup2(from_child_pipe[1], STDOUT_FILENO) < 0) {
+ rprintf(FERROR,"Failed to dup/close : %s\n",strerror(errno));
+ exit_cleanup(RERR_IPC);
+ }
+ if (to_child_pipe[0] != STDIN_FILENO) close(to_child_pipe[0]);
+ if (from_child_pipe[1] != STDOUT_FILENO) close(from_child_pipe[1]);
+ umask(orig_umask);
+ set_blocking(STDIN_FILENO);
+ if (blocking_io) {
+ set_blocking(STDOUT_FILENO);
+ }
+ execvp(command[0], command);
+ rprintf(FERROR,"Failed to exec %s : %s\n",
+ command[0],strerror(errno));
+ exit_cleanup(RERR_IPC);
+ }
- if (close(from_child_pipe[1]) < 0 || close(to_child_pipe[0]) < 0) {
- rprintf(FERROR, "Failed to close : %s\n", strerror(errno));
- exit_cleanup(RERR_IPC);
- }
+ if (close(from_child_pipe[1]) < 0 ||
+ close(to_child_pipe[0]) < 0) {
+ rprintf(FERROR,"Failed to close : %s\n",strerror(errno));
+ exit_cleanup(RERR_IPC);
+ }
- *f_in = from_child_pipe[0];
- *f_out = to_child_pipe[1];
+ *f_in = from_child_pipe[0];
+ *f_out = to_child_pipe[1];
- return pid;
+ return pid;
}
-pid_t local_child(int argc, char **argv,int *f_in,int *f_out)
+int local_child(int argc, char **argv,int *f_in,int *f_out)
{
- pid_t pid;
+ int pid;
int to_child_pipe[2];
int from_child_pipe[2];
- extern int read_batch; /* dw */
if (fd_pair(to_child_pipe) < 0 ||
fd_pair(from_child_pipe) < 0) {
pid = do_fork();
- if (pid == -1) {
+ if (pid < 0) {
rprintf(FERROR,"fork: %s\n",strerror(errno));
exit_cleanup(RERR_IPC);
}
extern int am_sender;
extern int am_server;
- am_sender = read_batch ? 0 : !am_sender;
+ am_sender = !am_sender;
am_server = 1;
if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 ||
s = strdup(s);
if (!s) out_of_memory("glob_expand");
- if (asprintf(&base," %s/", base1) <= 0) out_of_memory("glob_expand");
+ base = (char *)malloc(strlen(base1)+3);
+ if (!base) out_of_memory("glob_expand");
+
+ sprintf(base," %s/", base1);
q = s;
while ((p = strstr(q,base)) && ((*argc) < maxargs)) {
}
}
+/* this is like vsnprintf but it always null terminates, so you
+ can fit at most n-1 chars in */
+int vslprintf(char *str, int n, const char *format, va_list ap)
+{
+ int ret = vsnprintf(str, n, format, ap);
+ if (ret >= n || ret < 0) {
+ str[n-1] = 0;
+ return -1;
+ }
+ str[ret] = 0;
+ return ret;
+}
+
+
+/* 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;
+}
+
+
void *Realloc(void *p, int size)
{
if (!p) return (void *)malloc(size);
return (int)*s1 - (int)*s2;
}
-static OFF_T last_ofs;
-static struct timeval print_time;
-static struct timeval start_time;
-static OFF_T start_ofs;
-
-static unsigned long msdiff(struct timeval *t1, struct timeval *t2)
-{
- return (t2->tv_sec - t1->tv_sec) * 1000
- + (t2->tv_usec - t1->tv_usec) / 1000;
-}
-
-
-/**
- * @param ofs Current position in file
- * @param size Total size of file
- * @param is_last True if this is the last time progress will be
- * printed for this file, so we should output a newline. (Not
- * necessarily the same as all bytes being received.)
- **/
-static void rprint_progress(OFF_T ofs, OFF_T size, struct timeval *now,
- int is_last)
-{
- int pct = (ofs == size) ? 100 : (int)((100.0*ofs)/size);
- unsigned long diff = msdiff(&start_time, now);
- double rate = diff ? (double) (ofs-start_ofs) * 1000.0 / diff / 1024.0 : 0;
- const char *units;
- double remain = rate ? (double) (size-ofs) / rate / 1000.0: 0.0;
- int remain_h, remain_m, remain_s;
-
- if (rate > 1024*1024) {
- rate /= 1024.0 * 1024.0;
- units = "GB/s";
- } else if (rate > 1024) {
- rate /= 1024.0;
- units = "MB/s";
- } else {
- units = "kB/s";
- }
-
- remain_s = (int) remain % 60;
- remain_m = (int) (remain / 60.0) % 60;
- remain_h = (int) (remain / 3600.0);
-
- rprintf(FINFO, "%12.0f %3d%% %7.2f%s %4d:%02d:%02d%s",
- (double) ofs, pct, rate, units,
- remain_h, remain_m, remain_s,
- is_last ? "\n" : "\r");
-}
+static OFF_T last_ofs;
void end_progress(OFF_T size)
{
extern int do_progress, am_server;
if (do_progress && !am_server) {
- struct timeval now;
- gettimeofday(&now, NULL);
- rprint_progress(size, size, &now, True);
+ rprintf(FINFO,"%.0f (100%%)\n", (double)size);
}
- last_ofs = 0;
- start_ofs = 0;
- print_time.tv_sec = print_time.tv_usec = 0;
- start_time.tv_sec = start_time.tv_usec = 0;
+ last_ofs = 0;
}
void show_progress(OFF_T ofs, OFF_T size)
{
extern int do_progress, am_server;
- struct timeval now;
-
- gettimeofday(&now, NULL);
-
- if (!start_time.tv_sec && !start_time.tv_usec) {
- start_time.tv_sec = now.tv_sec;
- start_time.tv_usec = now.tv_usec;
- start_ofs = ofs;
- }
-
- if (do_progress
- && !am_server
- && ofs > last_ofs + 1000
- && msdiff(&print_time, &now) > 250) {
- rprint_progress(ofs, size, &now, False);
- last_ofs = ofs;
- print_time.tv_sec = now.tv_sec;
- print_time.tv_usec = now.tv_usec;
+
+ if (do_progress && !am_server) {
+ if (ofs > last_ofs + 1000) {
+ int pct = (int)((100.0*ofs)/size);
+ rprintf(FINFO,"%.0f (%d%%)\r", (double)ofs, pct);
+ last_ofs = ofs;
+ }
}
}
}
-/**
- * Sleep for a specified number of milliseconds.
- *
- * Always returns TRUE. (In the future it might return FALSE if
- * interrupted.)
- **/
-int msleep(int t)
+/*******************************************************************
+sleep for a specified number of milliseconds
+********************************************************************/
+void msleep(int t)
{
int tdiff=0;
struct timeval tval,t1,t2;
tdiff = (t2.tv_sec - t1.tv_sec)*1000 +
(t2.tv_usec - t1.tv_usec)/1000;
}
-
- return True;
}
*******************************************************************/
int cmp_modtime(time_t file1, time_t file2)
{
+ time_t diff;
extern int modify_window;
if (file2 > file1) {
{
static int (*fn)();
int ret;
- char *cmd;
+ char cmd[1024];
- asprintf(&cmd, "/usr/X11R6/bin/xterm -display :0 -T Panic -n Panic -e /bin/sh -c 'cat /tmp/ierrs.*.%d ; gdb /proc/%d/exe %d'",
+ sprintf(cmd, "/usr/X11R6/bin/xterm -display :0 -T Panic -n Panic -e /bin/sh -c 'cat /tmp/ierrs.*.%d ; gdb /proc/%d/exe %d'",
getpid(), getpid(), getpid());
if (!fn) {
system(cmd);
- free(cmd);
-
return ret;
}
#endif
--- /dev/null
+#define VERSION "2.4.7pre1"