mirror of
https://github.com/RsyncProject/rsync.git
synced 2026-05-25 07:15:35 -04:00
Compare commits
6 Commits
v2.5.2pre2
...
v2.4.8pre1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d19fa730b9 | ||
|
|
5c6e0ee27c | ||
|
|
0d95824995 | ||
|
|
bbc09ffba9 | ||
|
|
a4677968cf | ||
|
|
03b1cddc31 |
29
NEWS
29
NEWS
@@ -1,34 +1,7 @@
|
||||
rsync 2.5.2 (???)
|
||||
rsync 2.4.8 (???)
|
||||
|
||||
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)
|
||||
|
||||
@@ -5,7 +5,7 @@ AC_CONFIG_SRCDIR([byteorder.h])
|
||||
AC_CONFIG_HEADER(config.h)
|
||||
AC_PREREQ(2.52)
|
||||
|
||||
RSYNC_VERSION=2.5.2pre2
|
||||
RSYNC_VERSION=2.5.2pre3
|
||||
AC_SUBST(RSYNC_VERSION)
|
||||
AC_MSG_NOTICE([Configuring rsync $RSYNC_VERSION])
|
||||
|
||||
@@ -30,8 +30,7 @@ then
|
||||
AC_MSG_WARN([rsync requires an ANSI C compiler and you don't seem to have one])
|
||||
fi
|
||||
|
||||
# compile with optimisation and without debugging by default, unless
|
||||
# --debug is given. We must decide this before testing the compiler.
|
||||
# We must decide this before testing the compiler.
|
||||
|
||||
# Please allow this to default to yes, so that your users have more
|
||||
# chance of getting a useful stack trace if problems occur.
|
||||
@@ -553,3 +552,7 @@ AC_SUBST(BUILD_POPT)
|
||||
|
||||
AC_CONFIG_FILES([Makefile lib/dummy zlib/dummy popt/dummy shconfig])
|
||||
AC_OUTPUT
|
||||
|
||||
AC_MSG_RESULT()
|
||||
AC_MSG_RESULT([ rsync ${RSYNC_VERSION} configuration successful])
|
||||
AC_MSG_RESULT()
|
||||
|
||||
74
exclude.c
74
exclude.c
@@ -1,7 +1,6 @@
|
||||
/* -*- 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
|
||||
@@ -21,8 +20,6 @@
|
||||
/* 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;
|
||||
@@ -31,7 +28,7 @@ extern int delete_mode;
|
||||
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;
|
||||
|
||||
@@ -87,8 +84,8 @@ static void free_exclude(struct exclude_struct *ex)
|
||||
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;
|
||||
@@ -124,62 +121,32 @@ static int check_one_exclude(char *name, struct exclude_struct *ex,
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
@@ -207,12 +174,12 @@ void add_exclude_list(const char *pattern, struct exclude_struct ***list, int in
|
||||
(*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)
|
||||
{
|
||||
@@ -221,10 +188,7 @@ struct exclude_struct **make_exclude_list(const char *fname,
|
||||
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;
|
||||
@@ -246,7 +210,7 @@ struct exclude_struct **make_exclude_list(const char *fname,
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
|
||||
@@ -399,7 +363,7 @@ void add_cvs_excludes(void)
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
170
flist.c
170
flist.c
@@ -1,7 +1,6 @@
|
||||
/*
|
||||
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
|
||||
@@ -18,14 +17,7 @@
|
||||
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"
|
||||
|
||||
@@ -55,9 +47,6 @@ extern int remote_version;
|
||||
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;
|
||||
@@ -66,35 +55,6 @@ static struct file_struct null_file;
|
||||
|
||||
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;
|
||||
@@ -148,14 +108,24 @@ static char *string_area_strdup(struct string_area **ap, const char *src)
|
||||
|
||||
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,
|
||||
@@ -180,7 +150,7 @@ int readlink_stat(const char *Path, STRUCT_STAT *Buffer, char *Linkbuf)
|
||||
}
|
||||
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;
|
||||
@@ -212,18 +182,14 @@ int link_stat(const char *Path, STRUCT_STAT *Buffer)
|
||||
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 */
|
||||
@@ -239,7 +205,7 @@ static void set_filesystem(char *fname)
|
||||
|
||||
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;
|
||||
@@ -247,8 +213,8 @@ static int to_wire_mode(mode_t 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;
|
||||
}
|
||||
@@ -333,15 +299,8 @@ static void send_file_entry(struct file_struct *file,int f,unsigned base_flags)
|
||||
|
||||
#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
|
||||
|
||||
@@ -456,13 +415,8 @@ static void receive_file_entry(struct file_struct **fptr,
|
||||
|
||||
#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
|
||||
|
||||
@@ -516,8 +470,7 @@ static int skip_filesystem(char *fname, STRUCT_STAT *st)
|
||||
}
|
||||
|
||||
#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,
|
||||
@@ -529,6 +482,7 @@ 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);
|
||||
@@ -542,18 +496,9 @@ struct file_struct *make_file(int f, char *fname, struct string_area **ap,
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -570,7 +515,8 @@ struct file_struct *make_file(int f, char *fname, struct string_area **ap,
|
||||
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;
|
||||
|
||||
|
||||
@@ -659,10 +605,7 @@ void send_file_name(int f,struct file_list *flist,char *fname,
|
||||
|
||||
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)
|
||||
@@ -676,9 +619,6 @@ void send_file_name(int f,struct file_list *flist,char *fname,
|
||||
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);
|
||||
@@ -753,11 +693,6 @@ static void send_directory(int f,struct file_list *flist,char *dir)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* 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;
|
||||
@@ -768,9 +703,7 @@ struct file_list *send_file_list(int f,int argc,char *argv[])
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -891,7 +824,8 @@ struct file_list *send_file_list(int f,int argc,char *argv[])
|
||||
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);
|
||||
|
||||
@@ -911,8 +845,6 @@ struct file_list *send_file_list(int f,int argc,char *argv[])
|
||||
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)
|
||||
@@ -990,7 +922,7 @@ struct file_list *recv_file_list(int f)
|
||||
}
|
||||
|
||||
/* 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) {
|
||||
@@ -1022,10 +954,6 @@ oom:
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 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;
|
||||
@@ -1148,10 +1076,6 @@ static void clean_flist(struct file_list *flist, int strip_root)
|
||||
}
|
||||
}
|
||||
|
||||
/* 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_
|
||||
@@ -1176,10 +1100,10 @@ static void clean_flist(struct file_list *flist, int strip_root)
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -1187,10 +1111,6 @@ static void clean_flist(struct file_list *flist, int strip_root)
|
||||
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
@@ -1203,11 +1123,9 @@ 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);
|
||||
}
|
||||
|
||||
233
io.c
233
io.c
@@ -1,8 +1,6 @@
|
||||
/* -*- 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
|
||||
@@ -29,24 +27,18 @@
|
||||
/* 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);
|
||||
@@ -55,8 +47,6 @@ static void check_timeout(void)
|
||||
{
|
||||
extern int am_server, am_daemon;
|
||||
time_t t;
|
||||
|
||||
err_list_push();
|
||||
|
||||
if (!io_timeout) return;
|
||||
|
||||
@@ -69,7 +59,7 @@ static void check_timeout(void)
|
||||
|
||||
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);
|
||||
@@ -86,12 +76,10 @@ void io_set_error_fd(int fd)
|
||||
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);
|
||||
@@ -103,8 +91,7 @@ static void read_error_fd(void)
|
||||
|
||||
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;
|
||||
@@ -114,68 +101,21 @@ static void read_error_fd(void)
|
||||
}
|
||||
|
||||
|
||||
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.
|
||||
*/
|
||||
static int no_flush;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
* 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);
|
||||
@@ -189,16 +129,11 @@ static int read_timeout (int fd, char *buf, size_t len)
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -217,27 +152,38 @@ static int read_timeout (int fd, char *buf, size_t len)
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
/* 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);
|
||||
@@ -247,20 +193,16 @@ static void read_loop (int fd, char *buf, size_t 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) {
|
||||
@@ -278,18 +220,17 @@ static int read_unbuffered(int fd, char *buf, size_t len)
|
||||
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);
|
||||
}
|
||||
@@ -297,7 +238,7 @@ static int read_unbuffered(int fd, char *buf, size_t len)
|
||||
read_loop(fd, line, remaining);
|
||||
line[remaining] = 0;
|
||||
|
||||
rprintf((enum logcode) tag, "%s", line);
|
||||
rprintf((enum logcode)tag,"%s", line);
|
||||
remaining = 0;
|
||||
}
|
||||
|
||||
@@ -305,18 +246,17 @@ static int read_unbuffered(int fd, char *buf, size_t len)
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
@@ -366,27 +306,25 @@ void read_buf(int f,char *buf,size_t len)
|
||||
|
||||
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) {
|
||||
@@ -411,14 +349,11 @@ static void writefd_unbuffered(int fd,char *buf,size_t len)
|
||||
&w_fds,NULL,
|
||||
&tv);
|
||||
|
||||
if (count == 0) {
|
||||
check_timeout();
|
||||
}
|
||||
|
||||
if (count <= 0) {
|
||||
if (errno == EBADF) {
|
||||
exit_cleanup(RERR_SOCKETIO);
|
||||
}
|
||||
check_timeout();
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -427,8 +362,8 @@ static void writefd_unbuffered(int fd,char *buf,size_t len)
|
||||
}
|
||||
|
||||
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) {
|
||||
@@ -442,10 +377,7 @@ static void writefd_unbuffered(int fd,char *buf,size_t len)
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -490,7 +422,7 @@ void io_start_buffering(int fd)
|
||||
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);
|
||||
|
||||
@@ -513,9 +445,6 @@ static void mplex_write(int fd, enum logcode code, char *buf, size_t len)
|
||||
void io_flush(void)
|
||||
{
|
||||
int fd = multiplex_out_fd;
|
||||
|
||||
err_list_push();
|
||||
|
||||
if (!io_buffer_count || no_flush) return;
|
||||
|
||||
if (io_multiplexing_out) {
|
||||
@@ -526,8 +455,6 @@ void io_flush(void)
|
||||
io_buffer_count = 0;
|
||||
}
|
||||
|
||||
|
||||
/* XXX: fd is ignored, which seems a little strange. */
|
||||
void io_end_buffering(int fd)
|
||||
{
|
||||
io_flush();
|
||||
@@ -537,12 +464,21 @@ void io_end_buffering(int fd)
|
||||
}
|
||||
}
|
||||
|
||||
/* 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;
|
||||
@@ -569,11 +505,6 @@ void write_int(int f,int32 x)
|
||||
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;
|
||||
@@ -608,10 +539,10 @@ void write_byte(int f,unsigned char c)
|
||||
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);
|
||||
@@ -630,6 +561,8 @@ int read_line(int f, char *buf, size_t maxlen)
|
||||
return 0;
|
||||
}
|
||||
|
||||
eof_error = 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -641,7 +574,7 @@ void io_printf(int fd, const char *format, ...)
|
||||
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);
|
||||
@@ -678,6 +611,14 @@ int io_multiplex_write(enum logcode code, char *buf, size_t len)
|
||||
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)
|
||||
{
|
||||
|
||||
294
log.c
294
log.c
@@ -1,7 +1,5 @@
|
||||
/* -*- 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
|
||||
@@ -19,121 +17,18 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
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);
|
||||
@@ -142,11 +37,12 @@ static void logit(int priority, char *buf)
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -158,13 +54,13 @@ void log_init(void)
|
||||
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
|
||||
@@ -182,30 +78,11 @@ void log_init(void)
|
||||
#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
|
||||
@@ -229,14 +106,12 @@ void rwrite(enum logcode code, char *buf, int len)
|
||||
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;
|
||||
}
|
||||
@@ -250,7 +125,7 @@ void rwrite(enum logcode code, char *buf, int len)
|
||||
|
||||
depth++;
|
||||
|
||||
log_init();
|
||||
log_open();
|
||||
logit(priority, buf);
|
||||
|
||||
depth--;
|
||||
@@ -258,7 +133,6 @@ void rwrite(enum logcode code, char *buf, int len)
|
||||
}
|
||||
|
||||
if (code == FERROR) {
|
||||
log_got_error = 1;
|
||||
f = stderr;
|
||||
}
|
||||
|
||||
@@ -277,90 +151,22 @@ void rwrite(enum logcode code, char *buf, int len)
|
||||
}
|
||||
|
||||
|
||||
/* This is the rsync debugging function. Call it with FINFO, FERROR or
|
||||
* FLOG. */
|
||||
void rprintf(enum logcode code, 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;
|
||||
|
||||
va_start(ap, format);
|
||||
/* Note: might return -1 */
|
||||
len = vsnprintf(buf, sizeof(buf), format, ap);
|
||||
len = vslprintf(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';
|
||||
}
|
||||
}
|
||||
if (len > sizeof(buf)-1) exit_cleanup(RERR_MESSAGEIO);
|
||||
|
||||
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, ...)
|
||||
{
|
||||
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);
|
||||
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++;
|
||||
|
||||
rwrite(code, buf, len);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void rflush(enum logcode code)
|
||||
{
|
||||
FILE *f = NULL;
|
||||
@@ -403,18 +209,14 @@ static void log_formatted(enum logcode code,
|
||||
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];
|
||||
@@ -426,18 +228,18 @@ static void log_formatted(enum logcode code,
|
||||
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);
|
||||
@@ -456,7 +258,7 @@ static void log_formatted(enum logcode code,
|
||||
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':
|
||||
@@ -467,35 +269,26 @@ static void log_formatted(enum logcode code,
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -530,15 +323,7 @@ void log_recv(struct file_struct *file, struct stats *initial_stats)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* 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) {
|
||||
@@ -548,20 +333,11 @@ void log_exit(int code, const char *file, int line)
|
||||
(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
|
||||
|
||||
|
||||
50
receiver.c
50
receiver.c
@@ -1,6 +1,5 @@
|
||||
/* -*- 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
|
||||
@@ -38,8 +37,8 @@ extern int make_backups;
|
||||
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;
|
||||
|
||||
@@ -83,15 +82,14 @@ static void delete_one(struct file_struct *f)
|
||||
{
|
||||
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));
|
||||
}
|
||||
@@ -179,7 +177,7 @@ static int get_tmpname(char *fnametmp, char *fname)
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -192,11 +190,11 @@ static int get_tmpname(char *fnametmp, char *fname)
|
||||
|
||||
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;
|
||||
@@ -305,7 +303,6 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
|
||||
int fd1,fd2;
|
||||
STRUCT_STAT st;
|
||||
char *fname;
|
||||
char template[MAXPATHLEN];
|
||||
char fnametmp[MAXPATHLEN];
|
||||
char *fnamecmp;
|
||||
char fnamecmpbuf[MAXPATHLEN];
|
||||
@@ -373,7 +370,7 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
|
||||
|
||||
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);
|
||||
@@ -414,7 +411,17 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
|
||||
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
|
||||
@@ -422,21 +429,16 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
|
||||
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));
|
||||
@@ -489,7 +491,7 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
|
||||
}
|
||||
|
||||
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 */
|
||||
|
||||
143
rsync.h
143
rsync.h
@@ -1,7 +1,6 @@
|
||||
/*
|
||||
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
|
||||
@@ -18,7 +17,6 @@
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
|
||||
#define False 0
|
||||
#define True 1
|
||||
|
||||
@@ -49,18 +47,7 @@
|
||||
#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
|
||||
|
||||
@@ -76,10 +63,7 @@
|
||||
|
||||
#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"
|
||||
|
||||
@@ -93,6 +77,12 @@ enum logcode {FNONE=0, FERROR=1, FINFO=2, FLOG=3 };
|
||||
|
||||
#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
|
||||
@@ -185,10 +175,6 @@ enum logcode {FNONE=0, FERROR=1, FINFO=2, FLOG=3 };
|
||||
#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>
|
||||
@@ -267,44 +253,15 @@ enum logcode {FNONE=0, FERROR=1, FINFO=2, FLOG=3 };
|
||||
#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))
|
||||
@@ -335,13 +292,9 @@ struct file_struct {
|
||||
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;
|
||||
@@ -377,11 +330,11 @@ struct sum_buf {
|
||||
};
|
||||
|
||||
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 {
|
||||
@@ -391,6 +344,7 @@ struct map_struct {
|
||||
};
|
||||
|
||||
struct exclude_struct {
|
||||
char *orig;
|
||||
char *pattern;
|
||||
int regular_exp;
|
||||
int fnmatch_flags;
|
||||
@@ -422,29 +376,9 @@ static inline int flist_up(struct file_list *flist, int i)
|
||||
}
|
||||
|
||||
#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[];
|
||||
@@ -542,13 +476,6 @@ extern int errno;
|
||||
# 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))
|
||||
|
||||
@@ -570,14 +497,6 @@ extern int errno;
|
||||
#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
|
||||
@@ -596,15 +515,3 @@ size_t strlcat(char *d, const char *s, size_t bufsize);
|
||||
#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
|
||||
|
||||
34
socket.c
34
socket.c
@@ -715,10 +715,11 @@ int check_name(int fd,
|
||||
{
|
||||
struct addrinfo hints, *res, *res0;
|
||||
int error;
|
||||
int ss_family = get_sockaddr_family(ss);
|
||||
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = PF_UNSPEC;
|
||||
hints.ai_flags = AI_CANONNAME;
|
||||
hints.ai_flags = ss_family;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
error = getaddrinfo(name_buf, port_buf, &hints, &res0);
|
||||
if (error) {
|
||||
@@ -733,14 +734,39 @@ int check_name(int fd,
|
||||
|
||||
/* We expect that one of the results will be the same as ss. */
|
||||
for (res = res0; res; res = res->ai_next) {
|
||||
if (res->ai_family != get_sockaddr_family(ss))
|
||||
if (res->ai_family != ss_family) {
|
||||
rprintf(FERROR,
|
||||
"check_name: response family %d != %d\n",
|
||||
res->ai_family, ss_family);
|
||||
continue;
|
||||
if (res->ai_addrlen != ss_len)
|
||||
}
|
||||
if (res->ai_addrlen != ss_len) {
|
||||
rprintf(FERROR,
|
||||
"check_name: addrlen %d != %d\n",
|
||||
res->ai_addrlen, ss_len);
|
||||
continue;
|
||||
if (memcmp(res->ai_addr, ss, res->ai_addrlen) == 0)
|
||||
}
|
||||
if (memcmp(res->ai_addr, ss, res->ai_addrlen) == 0) {
|
||||
rprintf(FERROR,
|
||||
"check_name: %d bytes of address identical\n",
|
||||
res->ai_addrlen);
|
||||
break;
|
||||
} else{
|
||||
rprintf(FERROR,
|
||||
"check_name: %d bytes of address NOT identical\n",
|
||||
res->ai_addrlen);
|
||||
}
|
||||
}
|
||||
|
||||
if (!res0) {
|
||||
/* We hit the end of the list without finding an
|
||||
* address that was the same as ss. */
|
||||
rprintf(FERROR, RSYNC_NAME
|
||||
": no known address for \"%s\": "
|
||||
"spoofed address?\n",
|
||||
name_buf);
|
||||
strcpy(name_buf, default_name);
|
||||
}
|
||||
if (res == NULL) {
|
||||
/* We hit the end of the list without finding an
|
||||
* address that was the same as ss. */
|
||||
|
||||
264
util.c
264
util.c
@@ -1,8 +1,6 @@
|
||||
/* -*- 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
|
||||
@@ -84,26 +82,6 @@ int fd_pair(int fd[2])
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
@@ -114,71 +92,66 @@ void print_child_argv(char **cmd)
|
||||
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)
|
||||
int 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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
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 (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) {
|
||||
@@ -188,7 +161,7 @@ pid_t local_child(int argc, char **argv,int *f_in,int *f_out)
|
||||
|
||||
|
||||
pid = do_fork();
|
||||
if (pid == -1) {
|
||||
if (pid < 0) {
|
||||
rprintf(FERROR,"fork: %s\n",strerror(errno));
|
||||
exit_cleanup(RERR_IPC);
|
||||
}
|
||||
@@ -197,7 +170,7 @@ pid_t local_child(int argc, char **argv,int *f_in,int *f_out)
|
||||
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 ||
|
||||
@@ -584,7 +557,10 @@ void glob_expand(char *base1, char **argv, int *argc, int maxargs)
|
||||
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)) {
|
||||
@@ -611,6 +587,33 @@ void strlower(char *s)
|
||||
}
|
||||
}
|
||||
|
||||
/* 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);
|
||||
@@ -832,91 +835,28 @@ int u_strcmp(const char *cs1, const char *cs2)
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -990,13 +930,10 @@ char *timestring(time_t t)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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;
|
||||
@@ -1015,8 +952,6 @@ int msleep(int t)
|
||||
tdiff = (t2.tv_sec - t1.tv_sec)*1000 +
|
||||
(t2.tv_usec - t1.tv_usec)/1000;
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
|
||||
@@ -1028,6 +963,7 @@ int msleep(int t)
|
||||
*******************************************************************/
|
||||
int cmp_modtime(time_t file1, time_t file2)
|
||||
{
|
||||
time_t diff;
|
||||
extern int modify_window;
|
||||
|
||||
if (file2 > file1) {
|
||||
@@ -1051,9 +987,9 @@ int _Insure_trap_error(int a1, int a2, int a3, int a4, int a5, int a6)
|
||||
{
|
||||
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) {
|
||||
@@ -1066,8 +1002,6 @@ int _Insure_trap_error(int a1, int a2, int a3, int a4, int a5, int a6)
|
||||
|
||||
system(cmd);
|
||||
|
||||
free(cmd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user