Buffer management fix.

Prepare for 2.5.7 release.
This commit is contained in:
Martin Pool
2003-12-04 04:23:29 +00:00
parent b11b50bcd0
commit 9fb21d2882
20 changed files with 890 additions and 1446 deletions

120
NEWS
View File

@@ -1,120 +1,12 @@
NEWS for rsync version 2.5.7
Protocol: 27 (changed)
Changes since version 2.5.6:
NEWS for rsync version 2.5.7:
ENHANCEMENTS:
SECURITY:
* Added --files-from, --no-relative, --no-implied-dirs, and --from0.
Note that --from0 affects the line-ending character for all the
--*-from options. (Wayne Davison)
* Length of csum2 is now per-file starting with protocol verison
27. (J.W. Schultz)
* Per-file dynamic block size is now sqrt(file length).
The per-file checksum size is determined according
to an algorythm provided by Donovan Baarda which
reduces the probability of rsync algorithm
corrupting data and falling back using the whole md4
checksums. (J.W. Schultz, Donovan Baarda)
* The --stats option no longer includes the (debug) malloc summary
unless the verbose option was specified at least twice.
BUG FIXES:
* Fixed several exclude/include matching bugs when using wild-cards.
This has a several user-visible effects, all of which make the
matching more consistent and intuitive. This should hopefully not
cause anyone problems since it makes the matching work more like
what people are expecting. (Wayne Davison)
- A pattern with a "**" no longer causes a "*" to match slashes.
For example, with "/*/foo/**", "foo" must be 2 levels deep.
- "**/foo" now matches at the base of the transfer (i.e. /foo).
- An non-anchored wildcard term floats to match beyond the base of
the transfer. E.g. "CVS/R*" matches at the end of the path,
just like the non-wildcard term "CVS/Root" does.
- Including a "**" in the match term causes it to be matched
against the entire path, not just the name portion, even if
there aren't any interior slashes in the term. E.g. "foo**bar"
would exclude "/path/foo-bar" (just like before) as well as
"/foo-path/baz-bar" (for instance).
* The exclude list specified in the daemon's config file is now
properly applied to the pulled items no matter how deep the
user's file args are in the source tree. (Wayne Davison)
* For protocol version >= 27, mdfour_tail() is called when the
block size (including checksum_seed) is a multiple of 64.
Previously it was not called, giving the wrong MD4 checksum.
(Craig Barratt)
* For protocol version >= 27, a 64 bit bit counter is used in
mdfour.c as required by the RFC. Previously only a 32 bit bit
counter was used, causing incorrect MD4 file checksums for
file sizes >= 512MB - 4. (Craig Barratt)
* Fixed a crash bug when interacting with older rsync versions and
multiple files of the same name are destined for the same dir.
(Wayne Davison)
* Keep tmp names from overflowing MAXPATHLEN.
* Make --link-dest honor the absence of -p, -o, and -g.
* Made rsync treat a trailing slash in the destination in a more
consistent manner.
* Fixed file I/O error detection. (John Van Essen)
* Fixed a compression (-z) bug when syncing a mostly-matching file
that contains already-compressed data. (Yasuoka Masahiko and
Wayne Davison)
* Fixed a bug in the --backup code that could cause deleted files
to not get backed up.
* Call setgroups() in a more portable manner.
* Improved file-related error messages to better indicate exactly
what pathname failed. (Wayne Davison)
* Fixed some bugs in the handling of --delete and --exclude when
using the --relative (-R) option. (Wayne Davison)
* Fixed bug that prevented regular files from replacing
special files and caused a directory in --link-dest or
--compare-dest to block the creation of a file with the
same path. A directory still cannot be replaced by a
regular file unless --delete specified. (J.W. Schultz)
* Detect and report when open or opendir succeed but read and
readdir fail caused by network filesystems issues and truncated
files. (David Norwood, Michael Brown, J.W. Schultz)
INTERNAL:
* Eliminated vestigial support for old versions that we stopped
supporting. (J.W. Schultz)
* Simplified some of the option-parsing code. (Wayne Davison)
* Some cleanup made to the exclude code, as well as some new
defines added to enhance readability. (Wayne Davison)
* Changed the protocol-version code so that it can interact at a
lower protocol level than the maximum supported by both sides.
Added an undocumented option, --protocol=N, to force the value
we advertise to the other side (primarily for testing purposes).
(Wayne Davison)
* Fix buffer handling bugs. (Andrew Tridgell, Martin Pool, Paul
Russell, Andrea Barisani)
NEWS for rsync version 2.5.6, aka the dwd-between-jobs release
Protocol: 26 (unchanged)
Changes since version 2.5.5:
ENHANCEMENTS:
@@ -155,7 +47,7 @@ Changes since version 2.5.5:
(Dave Dykstra)
BUG FIXES:
* Fix "forward name lookup failed" errors on AIX 4.3.3. (John
L. Allen, Martin Pool)
@@ -191,7 +83,7 @@ Changes since version 2.5.5:
INTERNAL:
* Many code cleanups and improved internal documentation. (Martin
* Many code cleanups and improved internal documentation. (Martin
Pool, Nelson Beebe)
* Portability fixes. (Dave Dykstra and Wayne Davison)

21
batch.c
View File

@@ -185,15 +185,14 @@ struct file_list *create_flist_from_batch(void)
fdb_open = 1;
fdb_close = 0;
batch_flist = (struct file_list *) malloc(sizeof(batch_flist[0]));
batch_flist = new(struct file_list);
if (!batch_flist) {
out_of_memory("create_flist_from_batch");
}
batch_flist->count = 0;
batch_flist->malloced = 1000;
batch_flist->files =
(struct file_struct **) malloc(sizeof(batch_flist->files[0]) *
batch_flist->malloced);
batch_flist->files = new_array(struct file_struct *,
batch_flist->malloced);
if (!batch_flist->files) {
out_of_memory("create_flist_from_batch");
}
@@ -207,14 +206,10 @@ struct file_list *create_flist_from_batch(void)
batch_flist->malloced += 1000;
else
batch_flist->malloced *= 2;
batch_flist->files =
(struct file_struct **) realloc(batch_flist->
files,
sizeof
(batch_flist->
files[0]) *
batch_flist->
malloced);
batch_flist->files
= realloc_array(batch_flist->files,
struct file_struct *,
batch_flist->malloced);
if (!batch_flist->files)
out_of_memory("create_flist_from_batch");
}
@@ -282,7 +277,7 @@ void read_batch_flist_info(struct file_struct **fptr)
char buff[256];
struct file_struct *file;
file = (struct file_struct *) malloc(sizeof(*file));
file = new(struct file_struct);
if (!file)
out_of_memory("read_batch_flist_info");
memset((char *) file, 0, sizeof(*file));

View File

@@ -24,7 +24,7 @@ int csum_length=2; /* initial value */
#define CSUM_CHUNK 64
int checksum_seed = 0;
extern int protocol_version;
extern int remote_version;
/*
a simple 32 bit checksum that can be upadted from either end
@@ -58,7 +58,7 @@ void get_checksum2(char *buf,int len,char *sum)
if (len > len1) {
if (buf1) free(buf1);
buf1 = (char *)malloc(len+4);
buf1 = new_array(char, len+4);
len1 = len;
if (!buf1) out_of_memory("get_checksum2");
}
@@ -74,13 +74,7 @@ void get_checksum2(char *buf,int len,char *sum)
for(i = 0; i + CSUM_CHUNK <= len; i += CSUM_CHUNK) {
mdfour_update(&m, (uchar *)(buf1+i), CSUM_CHUNK);
}
/*
* Prior to version 27 an incorrect MD4 checksum was computed
* by failing to call mdfour_tail() for block sizes that
* are multiples of 64. This is fixed by calling mdfour_update()
* even when there are no more bytes.
*/
if (len - i > 0 || protocol_version >= 27) {
if (len - i > 0) {
mdfour_update(&m, (uchar *)(buf1+i), (len-i));
}
@@ -111,16 +105,8 @@ void file_checksum(char *fname,char *sum,OFF_T size)
mdfour_update(&m, (uchar *)tmpchunk, CSUM_CHUNK);
}
/*
* Prior to version 27 an incorrect MD4 checksum was computed
* by failing to call mdfour_tail() for block sizes that
* are multiples of 64. This is fixed by calling mdfour_update()
* even when there are no more bytes.
*/
if (len - i > 0) {
memcpy(tmpchunk, map_ptr(buf,i,len-i), len-i);
}
if (len - i > 0 || protocol_version >= 27) {
mdfour_update(&m, (uchar *)tmpchunk, (len-i));
}
@@ -131,6 +117,16 @@ void file_checksum(char *fname,char *sum,OFF_T size)
}
void checksum_init(void)
{
if (remote_version >= 14)
csum_length = 2; /* adaptive */
else
csum_length = SUM_LENGTH;
}
static int sumresidue;
static char sumrbuf[CSUM_CHUNK];
static struct mdfour md;
@@ -184,7 +180,7 @@ void sum_update(char *p, int len)
void sum_end(char *sum)
{
if (sumresidue || protocol_version >= 27) {
if (sumresidue) {
mdfour_update(&md, (uchar *)sumrbuf, sumresidue);
}

View File

@@ -5,7 +5,7 @@ AC_CONFIG_SRCDIR([byteorder.h])
AC_CONFIG_HEADER(config.h)
AC_PREREQ(2.52)
RSYNC_VERSION=2.5.6
RSYNC_VERSION=2.5.7
AC_SUBST(RSYNC_VERSION)
AC_MSG_NOTICE([Configuring rsync $RSYNC_VERSION])
@@ -429,6 +429,15 @@ if test x"$rsync_cv_HAVE_SOCKETPAIR" = x"yes"; then
AC_DEFINE(HAVE_SOCKETPAIR, 1, [ ])
fi
AC_CACHE_CHECK([for working fnmatch],rsync_cv_HAVE_FNMATCH,[
AC_TRY_RUN([#include <fnmatch.h>
main() { exit((fnmatch("*.o", "x.o", FNM_PATHNAME) == 0 &&
fnmatch("a/b/*", "a/b/c/d", FNM_PATHNAME) != 0) ? 0: 1); }],
rsync_cv_HAVE_FNMATCH=yes,rsync_cv_HAVE_FNMATCH=no,rsync_cv_HAVE_FNMATCH=cross)])
if test x"$rsync_cv_HAVE_FNMATCH" = x"yes"; then
AC_DEFINE(HAVE_FNMATCH, 1, [ ])
fi
if test x"$with_included_popt" != x"yes"
then
AC_CHECK_LIB(popt, poptGetContext, , [with_included_popt=yes])

379
exclude.c
View File

@@ -1,19 +1,19 @@
/* -*- c-file-style: "linux" -*-
*
*
* Copyright (C) 1996-2001 by Andrew Tridgell <tridge@samba.org>
* Copyright (C) 1996 by Paul Mackerras
* Copyright (C) 2002 by Martin Pool
*
*
* 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
@@ -27,20 +27,16 @@
#include "rsync.h"
extern int verbose;
extern int delete_mode;
struct exclude_struct **exclude_list;
struct exclude_struct **local_exclude_list;
struct exclude_struct **server_exclude_list;
char *exclude_path_prefix = NULL;
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)
{
struct exclude_struct *ret;
char *cp;
int pat_len;
ret = (struct exclude_struct *)malloc(sizeof(*ret));
ret = new(struct exclude_struct);
if (!ret) out_of_memory("make_exclude");
memset(ret, 0, sizeof(*ret));
@@ -54,37 +50,33 @@ static struct exclude_struct *make_exclude(const char *pattern, int include)
ret->include = include;
}
if (exclude_path_prefix)
ret->match_flags |= MATCHFLG_ABS_PATH;
if (exclude_path_prefix && *pattern == '/') {
ret->pattern = malloc(strlen(exclude_path_prefix)
+ strlen(pattern) + 1);
if (!ret->pattern) out_of_memory("make_exclude");
sprintf(ret->pattern, "%s%s", exclude_path_prefix, pattern);
}
else {
ret->pattern = strdup(pattern);
if (!ret->pattern) out_of_memory("make_exclude");
}
ret->pattern = strdup(pattern);
if (!ret->pattern) out_of_memory("make_exclude");
if (strpbrk(pattern, "*[?")) {
ret->match_flags |= MATCHFLG_WILD;
if (strstr(pattern, "**")) {
ret->match_flags |= MATCHFLG_WILD2;
/* If the pattern starts with **, note that. */
if (*pattern == '*' && pattern[1] == '*')
ret->match_flags |= MATCHFLG_WILD2_PREFIX;
}
ret->regular_exp = 1;
ret->fnmatch_flags = FNM_PATHNAME;
if (strstr(pattern, "**")) {
static int tested;
if (!tested) {
tested = 1;
if (fnmatch("a/b/*", "a/b/c/d", FNM_PATHNAME)==0) {
rprintf(FERROR,"WARNING: fnmatch FNM_PATHNAME is broken on your system\n");
}
}
ret->fnmatch_flags = 0;
}
}
pat_len = strlen(ret->pattern);
if (pat_len > 1 && ret->pattern[pat_len-1] == '/') {
ret->pattern[pat_len-1] = 0;
if (strlen(pattern) > 1 && pattern[strlen(pattern)-1] == '/') {
ret->pattern[strlen(pattern)-1] = 0;
ret->directory = 1;
}
for (cp = ret->pattern; (cp = strchr(cp, '/')) != NULL; cp++)
ret->slash_cnt++;
if (!strchr(ret->pattern,'/')) {
ret->local = 1;
}
return ret;
}
@@ -96,98 +88,35 @@ static void free_exclude(struct exclude_struct *ex)
free(ex);
}
void free_exclude_list(struct exclude_struct ***listp)
{
struct exclude_struct **list = *listp;
if (verbose > 2)
rprintf(FINFO,"clearing exclude list\n");
if (!list)
return;
while (*list)
free_exclude(*list++);
free(*listp);
*listp = NULL;
}
static int check_one_exclude(char *name, struct exclude_struct *ex,
int name_is_dir)
STRUCT_STAT *st)
{
char *p;
int match_start = 0;
int match_start=0;
char *pattern = ex->pattern;
/* If the pattern does not have any slashes AND it does not have
* a "**" (which could match a slash), then we just match the
* name portion of the path. */
if (!ex->slash_cnt && !(ex->match_flags & MATCHFLG_WILD2)) {
if ((p = strrchr(name,'/')) != NULL)
name = p+1;
}
else if ((ex->match_flags & MATCHFLG_ABS_PATH) && *name != '/') {
static char full_name[MAXPATHLEN];
extern char curr_dir[];
int plus = curr_dir[1] == '\0'? 1 : 0;
snprintf(full_name, sizeof full_name,
"%s/%s", curr_dir+plus, name);
name = full_name;
}
if (ex->local && (p=strrchr(name,'/')))
name = p+1;
if (!name[0]) return 0;
if (ex->directory && !name_is_dir) return 0;
if (ex->directory && !S_ISDIR(st->st_mode)) return 0;
if (*pattern == '/') {
if (*pattern == '/' && *name != '/') {
match_start = 1;
pattern++;
if (*name == '/')
name++;
}
if (ex->match_flags & MATCHFLG_WILD) {
/* A non-anchored match with an infix slash and no "**"
* needs to match the last slash_cnt+1 name elements. */
if (!match_start && ex->slash_cnt &&
!(ex->match_flags & MATCHFLG_WILD2)) {
int cnt = ex->slash_cnt + 1;
for (p = name + strlen(name) - 1; p >= name; p--) {
if (*p == '/' && !--cnt)
break;
}
name = p+1;
}
if (wildmatch(pattern, name))
if (ex->regular_exp) {
if (fnmatch(pattern, name, ex->fnmatch_flags) == 0) {
return 1;
if (ex->match_flags & MATCHFLG_WILD2_PREFIX) {
/* If the **-prefixed pattern has a '/' as the next
* character, then try to match the rest of the
* pattern at the root. */
if (pattern[2] == '/' && wildmatch(pattern+3, name))
return 1;
}
else if (!match_start && ex->match_flags & MATCHFLG_WILD2) {
/* A non-anchored match with an infix or trailing "**"
* (but not a prefixed "**") needs to try matching
* after every slash. */
while ((name = strchr(name, '/')) != NULL) {
name++;
if (wildmatch(pattern, name))
return 1;
}
}
} else if (match_start) {
if (strcmp(name,pattern) == 0)
return 1;
} else {
int l1 = strlen(name);
int l2 = strlen(pattern);
if (l2 <= l1 &&
if (l2 <= l1 &&
strcmp(name+(l1-l2),pattern) == 0 &&
(l1==l2 || name[l1-(l2+1)] == '/')) {
(l1==l2 || (!match_start && name[l1-(l2+1)] == '/'))) {
return 1;
}
}
@@ -198,18 +127,18 @@ static int check_one_exclude(char *name, struct exclude_struct *ex,
static void report_exclude_result(char const *name,
struct exclude_struct const *ent,
int name_is_dir)
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",
name_is_dir ? "directory" : "file",
name, ent->pattern,
ent->directory ? "/" : "");
/* 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 ? "/" : "");
}
@@ -217,114 +146,136 @@ static void report_exclude_result(char const *name,
* Return true if file NAME is defined to be excluded by either
* LOCAL_EXCLUDE_LIST or the globals EXCLUDE_LIST.
*/
int check_exclude(struct exclude_struct **list, char *name, int name_is_dir)
int check_exclude(char *name, struct exclude_struct **local_exclude_list,
STRUCT_STAT *st)
{
struct exclude_struct *ent;
int n;
struct exclude_struct *ent;
while ((ent = *list++) != NULL) {
if (check_one_exclude(name, ent, name_is_dir)) {
report_exclude_result(name, ent, name_is_dir);
return !ent->include;
}
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;
}
}
}
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;
}
}
}
return 0;
}
void add_exclude(struct exclude_struct ***listp, const char *pattern, int include)
void add_exclude_list(const char *pattern, struct exclude_struct ***list, int include)
{
struct exclude_struct **list = *listp;
int len = 0;
int len=0;
if (list && *list)
for (; (*list)[len]; len++) ;
if (*pattern == '!' && !pattern[1]) {
free_exclude_list(listp);
return;
if (strcmp(pattern,"!") == 0) {
if (verbose > 2)
rprintf(FINFO,"clearing exclude list\n");
while ((len)--) {
free_exclude((*list)[len]);
}
free((*list));
*list = NULL;
return;
}
if (list)
for (; list[len]; len++) {}
list = *listp = (struct exclude_struct **)Realloc(list,sizeof(struct exclude_struct *)*(len+2));
if (!list || !(list[len] = make_exclude(pattern, include)))
*list = realloc_array(*list, struct exclude_struct *, len+2);
if (!*list || !((*list)[len] = make_exclude(pattern, include)))
out_of_memory("add_exclude");
if (verbose > 2) {
rprintf(FINFO,"add_exclude(%s,%s)\n",pattern,
include ? "include" : "exclude");
include ? "include" : "exclude");
}
list[len+1] = NULL;
(*list)[len+1] = NULL;
}
void add_exclude(const char *pattern, int include)
{
add_exclude_list(pattern,&exclude_list, include);
}
struct exclude_struct **make_exclude_list(const char *fname,
struct exclude_struct **list1,
int fatal, int include)
{
struct exclude_struct **list=list1;
FILE *f;
char line[MAXPATHLEN];
if (strcmp(fname, "-")) {
f = fopen(fname,"r");
} else {
f = fdopen(0, "r");
}
if (!f) {
if (fatal) {
rsyserr(FERROR, errno,
"failed to open %s file %s",
include ? "include" : "exclude",
fname);
exit_cleanup(RERR_FILEIO);
}
return list;
}
while (fgets(line,MAXPATHLEN,f)) {
int l = strlen(line);
while (l && (line[l-1] == '\n' || line[l-1] == '\r')) l--;
line[l] = 0;
if (line[0] && (line[0] != ';') && (line[0] != '#')) {
/* Skip lines starting with semicolon or pound.
It probably wouldn't cause any harm to not skip
them but there's no need to save them. */
add_exclude_list(line,&list,include);
}
}
fclose(f);
return list;
}
void add_exclude_file(struct exclude_struct ***listp, const char *fname,
int fatal, int include)
void add_exclude_file(const char *fname, int fatal, int include)
{
int fd;
char line[MAXPATHLEN];
char *eob = line + MAXPATHLEN - 1;
extern int eol_nulls;
if (!fname || !*fname) return;
if (!fname || !*fname)
return;
if (*fname != '-' || fname[1])
fd = open(fname, O_RDONLY|O_BINARY);
else
fd = 0;
if (fd < 0) {
if (fatal) {
rsyserr(FERROR, errno,
"failed to open %s file %s",
include ? "include" : "exclude",
fname);
exit_cleanup(RERR_FILEIO);
}
return;
}
while (1) {
char ch, *s = line;
int cnt;
while (1) {
if ((cnt = read(fd, &ch, 1)) <= 0) {
if (cnt < 0 && errno == EINTR)
continue;
break;
}
if (eol_nulls? !ch : (ch == '\n' || ch == '\r'))
break;
if (s < eob)
*s++ = ch;
}
*s = '\0';
if (*line && *line != ';' && *line != '#') {
/* Skip lines starting with semicolon or pound.
* It probably wouldn't cause any harm to not skip
* them but there's no need to save them. */
add_exclude(listp, line, include);
}
if (cnt <= 0)
break;
}
close(fd);
exclude_list = make_exclude_list(fname,exclude_list,fatal,include);
}
void send_exclude_list(int f)
{
int i;
extern int protocol_version;
extern int remote_version;
extern int list_only, recurse;
/* This is a complete hack - blame Rusty.
*
* FIXME: This pattern shows up in the output of
* report_exclude_result(), which is not ideal. */
if (list_only && !recurse)
add_exclude(&exclude_list, "/*/*", ADD_EXCLUDE);
if (list_only && !recurse) {
add_exclude("/*/*", 0);
}
if (!exclude_list) {
write_int(f,0);
@@ -335,13 +286,13 @@ void send_exclude_list(int f)
int l;
char pattern[MAXPATHLEN];
strlcpy(pattern,exclude_list[i]->pattern,sizeof(pattern));
strlcpy(pattern,exclude_list[i]->pattern,sizeof(pattern));
if (exclude_list[i]->directory) strlcat(pattern,"/", sizeof(pattern));
l = strlen(pattern);
if (l == 0) continue;
if (exclude_list[i]->include) {
if (protocol_version < 19) {
if (remote_version < 19) {
rprintf(FERROR,"remote rsync does not support include syntax - aborting\n");
exit_cleanup(RERR_UNSUPPORTED);
}
@@ -351,7 +302,7 @@ void send_exclude_list(int f)
write_int(f,l);
}
write_buf(f,pattern,l);
}
}
write_int(f,0);
}
@@ -365,7 +316,7 @@ void recv_exclude_list(int f)
while ((l=read_int(f))) {
if (l >= MAXPATHLEN) overflow("recv_exclude_list");
read_sbuf(f,line,l);
add_exclude(&exclude_list, line, ADD_EXCLUDE);
add_exclude(line,0);
}
}
@@ -401,7 +352,7 @@ char *get_exclude_tok(char *p)
/* Is this a '+' or '-' followed by a space (not whitespace)? */
if ((*s=='+' || *s=='-') && *(s+1)==' ')
s+=2;
/* Skip to the next space or the end of the string */
while (!isspace(* (unsigned char *) s) && *s != '\0')
s++;
@@ -417,16 +368,26 @@ char *get_exclude_tok(char *p)
return(t);
}
void add_exclude_line(struct exclude_struct ***listp,
const char *line, int include)
void add_exclude_line(char *p)
{
char *tok, *p;
if (!line || !*line) return;
p = strdup(line);
char *tok;
if (!p || !*p) return;
p = strdup(p);
if (!p) out_of_memory("add_exclude_line");
for (tok=get_exclude_tok(p); tok; tok=get_exclude_tok(NULL))
add_exclude(tok, 0);
free(p);
}
void add_include_line(char *p)
{
char *tok;
if (!p || !*p) return;
p = strdup(p);
if (!p) out_of_memory("add_include_line");
for (tok=get_exclude_tok(p); tok; tok=get_exclude_tok(NULL))
add_exclude(listp, tok, include);
add_exclude(tok, 1);
free(p);
}
@@ -444,14 +405,14 @@ void add_cvs_excludes(void)
char fname[MAXPATHLEN];
char *p;
int i;
for (i=0; cvs_ignore_list[i]; i++)
add_exclude(&exclude_list, cvs_ignore_list[i], ADD_EXCLUDE);
add_exclude(cvs_ignore_list[i], 0);
if ((p=getenv("HOME")) && strlen(p) < (MAXPATHLEN-12)) {
snprintf(fname,sizeof(fname), "%s/.cvsignore",p);
add_exclude_file(&exclude_list,fname,MISSING_OK,ADD_EXCLUDE);
add_exclude_file(fname,0,0);
}
add_exclude_line(&exclude_list, getenv("CVSIGNORE"), ADD_EXCLUDE);
add_exclude_line(getenv("CVSIGNORE"));
}

View File

@@ -69,22 +69,19 @@ static int write_sparse(int f,char *buf,size_t len)
return len;
}
/*
* write_file does not allow incomplete writes. It loops internally
* until len bytes are written or errno is set.
*/
int write_file(int f,char *buf,size_t len)
{
int ret = 0;
if (!sparse_files) {
return write(f,buf,len);
}
while (len>0) {
int r1;
if (sparse_files) {
int len1 = MIN(len, SPARSE_WRITE_SIZE);
r1 = write_sparse(f, buf, len1);
} else {
r1 = write(f, buf, len);
}
int len1 = MIN(len, SPARSE_WRITE_SIZE);
int r1 = write_sparse(f, buf, len1);
if (r1 <= 0) {
if (ret > 0) return ret;
return r1;
@@ -105,7 +102,7 @@ int write_file(int f,char *buf,size_t len)
struct map_struct *map_file(int fd,OFF_T len)
{
struct map_struct *map;
map = (struct map_struct *)malloc(sizeof(*map));
map = new(struct map_struct);
if (!map) out_of_memory("map_file");
map->fd = fd;
@@ -115,7 +112,6 @@ struct map_struct *map_file(int fd,OFF_T len)
map->p_offset = 0;
map->p_fd_offset = 0;
map->p_len = 0;
map->status = 0;
return map;
}
@@ -160,7 +156,7 @@ char *map_ptr(struct map_struct *map,OFF_T offset,int len)
/* make sure we have allocated enough memory for the window */
if (window_size > map->p_size) {
map->p = (char *)Realloc(map->p, window_size);
map->p = realloc_array(map->p, char, window_size);
if (!map->p) out_of_memory("map_ptr");
map->p_size = window_size;
}
@@ -192,11 +188,7 @@ char *map_ptr(struct map_struct *map,OFF_T offset,int len)
}
if ((nread=read(map->fd,map->p + read_offset,read_size)) != read_size) {
if (nread < 0) {
nread = 0;
if (!map->status)
map->status = errno;
}
if (nread < 0) nread = 0;
/* the best we can do is zero the buffer - the file
has changed mid transfer! */
memset(map->p+read_offset+nread, 0, read_size - nread);
@@ -211,18 +203,13 @@ char *map_ptr(struct map_struct *map,OFF_T offset,int len)
}
int unmap_file(struct map_struct *map)
void unmap_file(struct map_struct *map)
{
int ret;
if (map->p) {
free(map->p);
map->p = NULL;
}
ret = map->status;
memset(map, 0, sizeof(*map));
free(map);
return ret;
}

311
flist.c
View File

@@ -1,18 +1,18 @@
/*
/*
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
@@ -41,8 +41,6 @@ extern int always_checksum;
extern int cvs_exclude;
extern int recurse;
extern char *files_from;
extern int filesfrom_fd;
extern int one_file_system;
extern int make_backups;
@@ -54,28 +52,25 @@ extern int preserve_uid;
extern int preserve_gid;
extern int preserve_times;
extern int relative_paths;
extern int implied_dirs;
extern int copy_links;
extern int copy_unsafe_links;
extern int protocol_version;
extern int remote_version;
extern int io_error;
extern int sanitize_paths;
extern int read_batch;
extern int write_batch;
extern struct exclude_struct **exclude_list;
extern struct exclude_struct **server_exclude_list;
extern struct exclude_struct **local_exclude_list;
static struct exclude_struct **local_exclude_list;
static struct file_struct null_file;
static void clean_flist(struct file_list *flist, int strip_root, int no_dups);
static void clean_flist(struct file_list *flist, int strip_root);
static int show_filelist_p(void)
{
return verbose && (recurse || files_from) && !am_server;
return verbose && recurse && !am_server;
}
static void start_filelist_progress(char *kind)
@@ -123,10 +118,10 @@ static struct string_area *string_area_new(int size)
if (size <= 0)
size = ARENA_SIZE;
a = malloc(sizeof(*a));
a = new(struct string_area);
if (!a)
out_of_memory("string_area_new");
a->current = a->base = malloc(size);
a->current = a->base = new_array(char, size);
if (!a->current)
out_of_memory("string_area_new buffer");
a->end = a->base + size;
@@ -221,12 +216,12 @@ int readlink_stat(const char *path, STRUCT_STAT * buffer, char *linkbuf)
if (S_ISLNK(buffer->st_mode)) {
int l;
l = readlink((char *) path, linkbuf, MAXPATHLEN - 1);
if (l == -1)
if (l == -1)
return -1;
linkbuf[l] = 0;
if (copy_unsafe_links && unsafe_symlink(linkbuf, path)) {
if (verbose > 1) {
rprintf(FINFO,"copying unsafe symlink \"%s\" -> \"%s\"\n",
rprintf(FINFO,"copying unsafe symlink \"%s\" -> \"%s\"\n",
path, linkbuf);
}
return do_stat(path, buffer);
@@ -252,37 +247,20 @@ 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. The value of
* exclude_level is set to either SERVER_EXCLUDES or ALL_EXCLUDES.
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(char *fname, int is_dir, int exclude_level)
static int check_exclude_file(int f, char *fname, STRUCT_STAT * st)
{
#if 0 /* This currently never happens, so avoid a useless compare. */
if (exclude_level == NO_EXCLUDES)
extern int delete_excluded;
/* f is set to -1 when calculating deletion file list */
if ((f == -1) && delete_excluded) {
return 0;
#endif
if (fname) {
/* never exclude '.', even if somebody does --exclude '*' */
if (fname[0] == '.' && !fname[1])
return 0;
/* Handle the -R version of the '.' dir. */
if (fname[0] == '/') {
int len = strlen(fname);
if (fname[len-1] == '.' && fname[len-2] == '/')
return 0;
}
}
if (server_exclude_list
&& check_exclude(server_exclude_list, fname, is_dir))
return 1;
if (exclude_level != ALL_EXCLUDES)
return 0;
if (exclude_list && check_exclude(exclude_list, fname, is_dir))
return 1;
if (local_exclude_list
&& check_exclude(local_exclude_list, fname, is_dir))
if (check_exclude(fname, local_exclude_list, st)) {
return 1;
}
return 0;
}
@@ -327,27 +305,28 @@ static char *flist_dir;
static void flist_expand(struct file_list *flist)
{
if (flist->count >= flist->malloced) {
size_t new_bytes;
void *new_ptr;
if (flist->malloced < 1000)
flist->malloced += 1000;
else
flist->malloced *= 2;
new_bytes = sizeof(flist->files[0]) * flist->malloced;
if (flist->files)
new_ptr = realloc(flist->files, new_bytes);
new_ptr = realloc_array(flist->files,
struct file_struct *,
flist->malloced);
else
new_ptr = malloc(new_bytes);
new_ptr = new_array(struct file_struct *,
flist->malloced);
if (verbose >= 2) {
rprintf(FINFO, "expand file_list to %.0f bytes, did%s move\n",
(double) new_bytes,
(double)sizeof(flist->files[0])
* flist->malloced,
(new_ptr == flist->files) ? " not" : "");
}
flist->files = (struct file_struct **) new_ptr;
if (!flist->files)
@@ -396,7 +375,7 @@ static void send_file_entry(struct file_struct *file, int f,
for (l1 = 0;
lastname[l1] && (fname[l1] == lastname[l1]) && (l1 < 255);
l1++) {}
l1++);
l2 = strlen(fname) - l1;
if (l1 > 0)
@@ -446,7 +425,7 @@ static void send_file_entry(struct file_struct *file, int f,
#if SUPPORT_HARD_LINKS
if (preserve_hard_links && S_ISREG(file->mode)) {
if (protocol_version < 26) {
if (remote_version < 26) {
/* 32-bit dev_t and ino_t */
write_int(f, (int) file->dev);
write_int(f, (int) file->inode);
@@ -459,7 +438,7 @@ static void send_file_entry(struct file_struct *file, int f,
#endif
if (always_checksum) {
if (protocol_version < 21) {
if (remote_version < 21) {
write_buf(f, file->sum, 2);
} else {
write_buf(f, file->sum, MD4_SUM_LENGTH);
@@ -502,7 +481,7 @@ static void receive_file_entry(struct file_struct **fptr,
else
l2 = read_byte(f);
file = (struct file_struct *) malloc(sizeof(*file));
file = new(struct file_struct);
if (!file)
out_of_memory("receive_file_entry");
memset((char *) file, 0, sizeof(*file));
@@ -569,7 +548,7 @@ static void receive_file_entry(struct file_struct **fptr,
rprintf(FERROR, "overflow: l=%d\n", l);
overflow("receive_file_entry");
}
file->link = (char *) malloc(l + 1);
file->link = new_array(char, l + 1);
if (!file->link)
out_of_memory("receive_file_entry 2");
read_sbuf(f, file->link, l);
@@ -579,7 +558,7 @@ static void receive_file_entry(struct file_struct **fptr,
}
#if SUPPORT_HARD_LINKS
if (preserve_hard_links && S_ISREG(file->mode)) {
if (protocol_version < 26) {
if (remote_version < 26) {
file->dev = read_int(f);
file->inode = read_int(f);
} else {
@@ -590,10 +569,10 @@ static void receive_file_entry(struct file_struct **fptr,
#endif
if (always_checksum) {
file->sum = (char *) malloc(MD4_SUM_LENGTH);
file->sum = new_array(char, MD4_SUM_LENGTH);
if (!file->sum)
out_of_memory("md4 sum");
if (protocol_version < 21) {
if (remote_version < 21) {
read_buf(f, file->sum, 2);
} else {
read_buf(f, file->sum, MD4_SUM_LENGTH);
@@ -660,8 +639,8 @@ static int skip_filesystem(char *fname, STRUCT_STAT * st)
* statting directories if we're not recursing, but this is not a very
* important case. Some systems may not have d_type.
**/
struct file_struct *make_file(char *fname, struct string_area **ap,
int exclude_level)
struct file_struct *make_file(int f, char *fname, struct string_area **ap,
int noexcludes)
{
struct file_struct *file;
STRUCT_STAT st;
@@ -683,26 +662,27 @@ struct file_struct *make_file(char *fname, struct string_area **ap,
if (readlink_stat(fname, &st, linkbuf) != 0) {
int save_errno = errno;
if (errno == ENOENT && exclude_level != NO_EXCLUDES) {
/* either symlink pointing nowhere or file that
if ((errno == ENOENT) && !noexcludes) {
/* either symlink pointing nowhere or file that
* was removed during rsync run; see if excluded
* before reporting an error */
if (check_exclude_file(fname, 0, exclude_level)) {
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 failed: %s\n",
full_fname(fname), strerror(save_errno));
rprintf(FERROR, "readlink %s: %s\n",
fname, strerror(save_errno));
return NULL;
}
/* backup.c calls us with exclude_level set to NO_EXCLUDES. */
if (exclude_level == NO_EXCLUDES)
/* we use noexcludes from backup.c */
if (noexcludes)
goto skip_excludes;
if (S_ISDIR(st.st_mode) && !recurse && !files_from) {
if (S_ISDIR(st.st_mode) && !recurse) {
rprintf(FINFO, "skipping directory %s\n", fname);
return NULL;
}
@@ -712,18 +692,19 @@ struct file_struct *make_file(char *fname, struct string_area **ap,
return NULL;
}
if (check_exclude_file(fname, S_ISDIR(st.st_mode) != 0, exclude_level))
if (check_exclude_file(f, fname, &st))
return NULL;
if (lp_ignore_nonreadable(module_id) && access(fname, R_OK) != 0)
return NULL;
skip_excludes:
if (verbose > 2)
rprintf(FINFO, "make_file(%s,*,%d)\n", fname, exclude_level);
rprintf(FINFO, "make_file(%d,%s)\n", f, fname);
file = (struct file_struct *) malloc(sizeof(*file));
file = new(struct file_struct);
if (!file)
out_of_memory("make_file");
memset((char *) file, 0, sizeof(*file));
@@ -799,12 +780,8 @@ void send_file_name(int f, struct file_list *flist, char *fname,
int recursive, unsigned base_flags)
{
struct file_struct *file;
extern int delete_excluded;
/* f is set to -1 when calculating deletion file list */
file = make_file(fname, &flist->string_area,
f == -1 && delete_excluded? SERVER_EXCLUDES
: ALL_EXCLUDES);
file = make_file(f, fname, &flist->string_area, 0);
if (!file)
return;
@@ -816,7 +793,7 @@ void send_file_name(int f, struct file_list *flist, char *fname,
if (write_batch) /* dw */
file->flags = FLAG_DELETE;
if (file->basename[0]) {
if (strcmp(file->basename, "")) {
flist->files[flist->count++] = file;
send_file_entry(file, f, base_flags);
}
@@ -843,8 +820,7 @@ static void send_directory(int f, struct file_list *flist, char *dir)
d = opendir(dir);
if (!d) {
io_error = 1;
rprintf(FERROR, "opendir %s failed: %s\n",
full_fname(dir), strerror(errno));
rprintf(FERROR, "opendir(%s): %s\n", dir, strerror(errno));
return;
}
@@ -853,8 +829,9 @@ static void send_directory(int f, struct file_list *flist, char *dir)
if (fname[l - 1] != '/') {
if (l == MAXPATHLEN - 1) {
io_error = 1;
rprintf(FERROR, "skipping long-named directory: %s\n",
full_fname(fname));
rprintf(FERROR,
"skipping long-named directory %s\n",
fname);
closedir(d);
return;
}
@@ -868,51 +845,45 @@ static void send_directory(int f, struct file_list *flist, char *dir)
if (cvs_exclude) {
if (strlen(fname) + strlen(".cvsignore") <= MAXPATHLEN - 1) {
strcpy(p, ".cvsignore");
add_exclude_file(&exclude_list,fname,MISSING_OK,ADD_EXCLUDE);
local_exclude_list =
make_exclude_list(fname, NULL, 0, 0);
} else {
io_error = 1;
rprintf(FINFO,
"cannot cvs-exclude in long-named directory %s\n",
full_fname(fname));
fname);
}
}
for (errno = 0, di = readdir(d); di; errno = 0, di = readdir(d)) {
for (di = readdir(d); di; di = readdir(d)) {
char *dname = d_name(di);
if (dname[0] == '.' && (dname[1] == '\0'
|| (dname[1] == '.' && dname[2] == '\0')))
if (strcmp(dname, ".") == 0 || strcmp(dname, "..") == 0)
continue;
strlcpy(p, dname, MAXPATHLEN - l);
send_file_name(f, flist, fname, recurse, 0);
}
if (errno) {
io_error = 1;
rprintf(FERROR, "readdir(%s): (%d) %s\n",
dir, errno, strerror(errno));
}
if (local_exclude_list)
free_exclude_list(&local_exclude_list); /* Zeros pointer too */
if (local_exclude_list) {
add_exclude_list("!", &local_exclude_list, 0);
}
closedir(d);
}
/**
* The delete_files() function in receiver.c sets f to -1 so that we just
* construct the file list in memory without sending it over the wire. It
* also has the side-effect of ignoring user-excludes if delete_excluded
* is set (so that the delete list includes user-excluded files).
*
* I <b>think</b> 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 l;
int i, l;
STRUCT_STAT st;
char *p, *dir, *olddir;
char lastpath[MAXPATHLEN] = "";
struct file_list *flist;
int64 start_write;
int use_ff_fd = 0;
if (show_filelist_p() && f != -1)
start_filelist_progress("building file list");
@@ -923,37 +894,23 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
if (f != -1) {
io_start_buffering(f);
if (filesfrom_fd >= 0) {
if (argv[0] && !push_dir(argv[0], 0)) {
rprintf(FERROR, "push_dir %s failed: %s\n",
full_fname(argv[0]), strerror(errno));
exit_cleanup(RERR_FILESELECT);
}
use_ff_fd = 1;
}
}
while (1) {
for (i = 0; i < argc; i++) {
char fname2[MAXPATHLEN];
char *fname = fname2;
if (use_ff_fd) {
if (read_filesfrom_line(filesfrom_fd, fname) == 0)
break;
sanitize_path(fname, NULL);
} else {
if (argc-- == 0)
break;
strlcpy(fname, *argv++, MAXPATHLEN);
if (sanitize_paths)
sanitize_path(fname, NULL);
}
strlcpy(fname, argv[i], MAXPATHLEN);
l = strlen(fname);
if (fname[l - 1] == '/') {
if (l == 2 && fname[0] == '.') {
/* Turn "./" into just "." rather than "./." */
fname[1] = '\0';
if (l != 1 && fname[l - 1] == '/') {
if ((l == 2) && (fname[0] == '.')) {
/* Turn ./ into just . rather than ./.
This was put in to avoid a problem with
rsync -aR --delete from ./
The send_file_name() below of ./ was
mysteriously preventing deletes */
fname[1] = 0;
} else {
strlcat(fname, ".", MAXPATHLEN);
}
@@ -962,13 +919,13 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
if (link_stat(fname, &st) != 0) {
if (f != -1) {
io_error = 1;
rprintf(FERROR, "link_stat %s failed: %s\n",
full_fname(fname), strerror(errno));
rprintf(FERROR, "link_stat %s : %s\n",
fname, strerror(errno));
}
continue;
}
if (S_ISDIR(st.st_mode) && !recurse && !files_from) {
if (S_ISDIR(st.st_mode) && !recurse) {
rprintf(FINFO, "skipping directory %s\n", fname);
continue;
}
@@ -986,37 +943,31 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
dir = fname;
fname = p + 1;
}
} else if (f != -1 && implied_dirs && (p=strrchr(fname,'/')) && p != fname) {
} else if (f != -1 && (p = strrchr(fname, '/'))) {
/* this ensures we send the intermediate directories,
thus getting their permissions right */
char *lp = lastpath, *fn = fname, *slash = fname;
*p = 0;
/* Skip any initial directories in our path that we
* have in common with lastpath. */
while (*fn && *lp == *fn) {
if (*fn == '/')
slash = fn;
lp++, fn++;
}
*p = '/';
if (fn != p || (*lp && *lp != '/')) {
int copy_links_saved = copy_links;
int recurse_saved = recurse;
copy_links = copy_unsafe_links;
/* set recurse to 1 to prevent make_file
* from ignoring directory, but still
* turn off the recursive parameter to
* send_file_name */
recurse = 1;
while ((slash = strchr(slash+1, '/')) != 0) {
*slash = 0;
send_file_name(f, flist, fname, 0, 0);
*slash = '/';
if (strcmp(lastpath, fname)) {
strlcpy(lastpath, fname, sizeof(lastpath));
*p = '/';
for (p = fname + 1; (p = strchr(p, '/'));
p++) {
int copy_links_saved = copy_links;
int recurse_saved = recurse;
*p = 0;
copy_links = copy_unsafe_links;
/* set recurse to 1 to prevent make_file
from ignoring directory, but still
turn off the recursive parameter to
send_file_name */
recurse = 1;
send_file_name(f, flist, fname, 0,
0);
copy_links = copy_links_saved;
recurse = recurse_saved;
*p = '/';
}
copy_links = copy_links_saved;
recurse = recurse_saved;
*p = 0;
strlcpy(lastpath, fname, sizeof lastpath);
} else {
*p = '/';
}
}
@@ -1029,8 +980,8 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
if (!olddir) {
io_error = 1;
rprintf(FERROR, "push_dir %s failed: %s\n",
full_fname(dir), strerror(errno));
rprintf(FERROR, "push_dir %s : %s\n",
dir, strerror(errno));
continue;
}
@@ -1045,8 +996,8 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
if (olddir != NULL) {
flist_dir = NULL;
if (pop_dir(olddir) != 0) {
rprintf(FERROR, "pop_dir %s failed: %s\n",
full_fname(dir), strerror(errno));
rprintf(FERROR, "pop_dir %s : %s\n",
dir, strerror(errno));
exit_cleanup(RERR_FILESELECT);
}
}
@@ -1060,16 +1011,16 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
finish_filelist_progress(flist);
}
clean_flist(flist, 0, 0);
clean_flist(flist, 0);
/* now send the uid/gid list. This was introduced in protocol
version 15 */
if (f != -1) {
if (f != -1 && remote_version >= 15) {
send_uid_list(f);
}
/* send the io_error flag */
if (f != -1) {
/* if protocol version is >= 17 then send the io_error flag */
if (f != -1 && remote_version >= 17) {
extern int module_id;
write_int(f, lp_ignore_errors(module_id) ? 0 : io_error);
}
@@ -1101,22 +1052,20 @@ struct file_list *recv_file_list(int f)
start_read = stats.total_read;
flist = (struct file_list *) malloc(sizeof(flist[0]));
flist = new(struct file_list);
if (!flist)
goto oom;
flist->count = 0;
flist->malloced = 1000;
flist->files =
(struct file_struct **) malloc(sizeof(flist->files[0]) *
flist->malloced);
flist->files = new_array(struct file_struct *, flist->malloced);
if (!flist->files)
goto oom;
for (flags = read_byte(f); flags; flags = read_byte(f)) {
int i = flist->count;
flist_expand(flist);
receive_file_entry(&flist->files[i], flags, f);
@@ -1137,19 +1086,19 @@ struct file_list *recv_file_list(int f)
if (verbose > 2)
rprintf(FINFO, "received %d names\n", flist->count);
clean_flist(flist, relative_paths, 1);
clean_flist(flist, relative_paths);
if (show_filelist_p()) {
finish_filelist_progress(flist);
}
/* now recv the uid/gid list. This was introduced in protocol version 15 */
if (f != -1) {
if (f != -1 && remote_version >= 15) {
recv_uid_list(f, flist);
}
/* recv the io_error flag */
if (f != -1 && !read_batch) { /* dw-added readbatch */
/* if protocol version is >= 17 then recv the io_error flag */
if (f != -1 && remote_version >= 17 && !read_batch) { /* dw-added readbatch */
extern int module_id;
extern int ignore_errors;
if (lp_ignore_errors(module_id) || ignore_errors) {
@@ -1251,7 +1200,7 @@ struct file_list *flist_new(void)
{
struct file_list *flist;
flist = (struct file_list *) malloc(sizeof(flist[0]));
flist = new(struct file_list);
if (!flist)
out_of_memory("send_file_list");
@@ -1294,11 +1243,11 @@ void flist_free(struct file_list *flist)
/*
* This routine ensures we don't have any duplicate names in our file list.
* duplicate names can cause corruption because of the pipelining
* duplicate names can cause corruption because of the pipelining
*/
static void clean_flist(struct file_list *flist, int strip_root, int no_dups)
static void clean_flist(struct file_list *flist, int strip_root)
{
int i, prev_i = 0;
int i;
char *name, *prev_name = NULL;
if (!flist || flist->count == 0)
@@ -1307,9 +1256,8 @@ static void clean_flist(struct file_list *flist, int strip_root, int no_dups)
qsort(flist->files, flist->count,
sizeof(flist->files[0]), (int (*)()) file_compare);
for (i = no_dups? 0 : flist->count; i < flist->count; i++) {
for (i = 0; i < flist->count; i++) {
if (flist->files[i]->basename) {
prev_i = i;
prev_name = f_name(flist->files[i]);
break;
}
@@ -1324,11 +1272,6 @@ static void clean_flist(struct file_list *flist, int strip_root, int no_dups)
"removing duplicate name %s from file list %d\n",
name, i);
}
/* Make sure that if we unduplicate '.', that we don't
* lose track of a user-specified starting point (or
* else deletions will mysteriously fail with -R). */
if (flist->files[i]->flags & FLAG_DELETE)
flist->files[prev_i]->flags |= FLAG_DELETE;
/* it's not great that the flist knows the semantics of
* the file memory usage, but i'd rather not add a flag
* byte to that struct.
@@ -1338,10 +1281,6 @@ static void clean_flist(struct file_list *flist, int strip_root, int no_dups)
else
free_file(flist->files[i]);
}
else
prev_i = i;
/* We set prev_name every iteration to avoid it becoming
* invalid when names[][] in f_name() wraps around. */
prev_name = name;
}

View File

@@ -57,9 +57,7 @@ void init_hard_links(struct file_list *flist)
if (hlink_list)
free(hlink_list);
if (!(hlink_list =
(struct file_struct *) malloc(sizeof(hlink_list[0]) *
flist->count)))
if (!(hlink_list = new_array(struct file_struct, flist->count)))
out_of_memory("init_hard_links");
for (i = 0; i < flist->count; i++)

261
io.c
View File

@@ -76,12 +76,6 @@ int kludge_around_eof = False;
static int io_error_fd = -1;
static int io_filesfrom_f_in = -1;
static int io_filesfrom_f_out = -1;
static char io_filesfrom_buf[2048];
static char *io_filesfrom_bp;
static char io_filesfrom_lastchar;
static int io_filesfrom_buflen;
static void read_loop(int fd, char *buf, size_t len);
@@ -91,7 +85,7 @@ static void check_timeout(void)
time_t t;
err_list_push();
if (!io_timeout) return;
if (!last_io) {
@@ -124,8 +118,8 @@ static void read_error_fd(void)
int fd = io_error_fd;
int tag, len;
/* io_error_fd is temporarily disabled -- is this meant to
* prevent indefinite recursion? */
/* io_error_fd is temporarily disabled -- is this meant to
* prevent indefinite recursion? */
io_error_fd = -1;
read_loop(fd, buf, 4);
@@ -137,8 +131,8 @@ 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;
@@ -147,24 +141,6 @@ static void read_error_fd(void)
io_error_fd = fd;
}
/**
* When we're the receiver and we have a local --files-from list of names
* that needs to be sent over the socket to the sender, we have to do two
* things at the same time: send the sender a list of what files we're
* processing and read the incoming file+info list from the sender. We do
* this by augmenting the read_timeout() function to copy this data. It
* uses the io_filesfrom_buf to read a block of data from f_in (when it is
* ready, since it might be a pipe) and then blast it out f_out (when it
* is ready to receive more data).
*/
void io_set_filesfrom_fds(int f_in, int f_out)
{
io_filesfrom_f_in = f_in;
io_filesfrom_f_out = f_out;
io_filesfrom_bp = io_filesfrom_buf;
io_filesfrom_lastchar = '\0';
io_filesfrom_buflen = 0;
}
/**
* It's almost always an error to get an EOF when we're trying to read
@@ -176,28 +152,28 @@ void io_set_filesfrom_fds(int f_in, int f_out)
* program where that is a problem (start_socket_client),
* kludge_around_eof is True and we just exit.
*/
static void whine_about_eof(void)
static void whine_about_eof (void)
{
if (kludge_around_eof)
exit_cleanup(0);
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);
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)
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));
RSYNC_NAME, strerror (err));
exit_cleanup(RERR_STREAMIO);
}
@@ -213,7 +189,7 @@ static void die_from_readerr(int err)
* 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)
static int read_timeout (int fd, char *buf, size_t len)
{
int n, ret=0;
@@ -221,33 +197,16 @@ static int read_timeout(int fd, char *buf, size_t len)
while (ret == 0) {
/* until we manage to read *something* */
fd_set r_fds, w_fds;
fd_set fds;
struct timeval tv;
int fd_count = fd+1;
int count;
FD_ZERO(&r_fds);
FD_SET(fd, &r_fds);
FD_ZERO(&fds);
FD_SET(fd, &fds);
if (io_error_fd != -1) {
FD_SET(io_error_fd, &r_fds);
if (io_error_fd >= fd_count) fd_count = io_error_fd+1;
}
if (io_filesfrom_f_out != -1) {
int new_fd;
if (io_filesfrom_buflen == 0) {
if (io_filesfrom_f_in != -1) {
FD_SET(io_filesfrom_f_in, &r_fds);
new_fd = io_filesfrom_f_in;
} else {
io_filesfrom_f_out = -1;
new_fd = -1;
}
} else {
FD_ZERO(&w_fds);
FD_SET(io_filesfrom_f_out, &w_fds);
new_fd = io_filesfrom_f_out;
}
if (new_fd >= fd_count) fd_count = new_fd+1;
FD_SET(io_error_fd, &fds);
if (io_error_fd > fd) fd_count = io_error_fd+1;
}
tv.tv_sec = io_timeout?io_timeout:SELECT_TIMEOUT;
@@ -255,9 +214,7 @@ static int read_timeout(int fd, char *buf, size_t len)
errno = 0;
count = select(fd_count, &r_fds,
io_filesfrom_buflen? &w_fds : NULL,
NULL, &tv);
count = select(fd_count, &fds, NULL, NULL, &tv);
if (count == 0) {
check_timeout();
@@ -270,76 +227,11 @@ static int read_timeout(int fd, char *buf, size_t len)
continue;
}
if (io_error_fd != -1 && FD_ISSET(io_error_fd, &r_fds)) {
if (io_error_fd != -1 && FD_ISSET(io_error_fd, &fds)) {
read_error_fd();
}
if (io_filesfrom_f_out != -1) {
if (io_filesfrom_buflen) {
if (FD_ISSET(io_filesfrom_f_out, &w_fds)) {
int l = write(io_filesfrom_f_out,
io_filesfrom_bp,
io_filesfrom_buflen);
if (l > 0) {
if (!(io_filesfrom_buflen -= l))
io_filesfrom_bp = io_filesfrom_buf;
else
io_filesfrom_bp += l;
} else {
/* XXX should we complain? */
io_filesfrom_f_out = -1;
}
}
} else if (io_filesfrom_f_in != -1) {
if (FD_ISSET(io_filesfrom_f_in, &r_fds)) {
int l = read(io_filesfrom_f_in,
io_filesfrom_buf,
sizeof io_filesfrom_buf);
if (l <= 0) {
/* Send end-of-file marker */
io_filesfrom_buf[0] = '\0';
io_filesfrom_buf[1] = '\0';
io_filesfrom_buflen = io_filesfrom_lastchar? 2 : 1;
io_filesfrom_f_in = -1;
} else {
extern int eol_nulls;
if (!eol_nulls) {
char *s = io_filesfrom_buf + l;
/* Transform CR and/or LF into '\0' */
while (s-- > io_filesfrom_buf) {
if (*s == '\n' || *s == '\r')
*s = '\0';
}
}
if (!io_filesfrom_lastchar) {
/* Last buf ended with a '\0', so don't
* let this buf start with one. */
while (l && !*io_filesfrom_bp)
io_filesfrom_bp++, l--;
}
if (!l)
io_filesfrom_bp = io_filesfrom_buf;
else {
char *f = io_filesfrom_bp;
char *t = f;
char *eob = f + l;
/* Eliminate any multi-'\0' runs. */
while (f != eob) {
if (!(*t++ = *f++)) {
while (f != eob && !*f)
f++, l--;
}
}
io_filesfrom_lastchar = f[-1];
}
io_filesfrom_buflen = l;
}
}
}
}
if (!FD_ISSET(fd, &r_fds)) continue;
if (!FD_ISSET(fd, &fds)) continue;
n = read(fd, buf, len);
@@ -351,76 +243,28 @@ static int read_timeout(int fd, char *buf, size_t len)
last_io = time(NULL);
continue;
} else if (n == 0) {
whine_about_eof();
whine_about_eof ();
return -1; /* doesn't return */
} else if (n == -1) {
if (errno == EINTR || errno == EWOULDBLOCK ||
errno == EAGAIN)
continue;
die_from_readerr(errno);
else
die_from_readerr (errno);
}
}
return ret;
}
/**
* Read a line into the "fname" buffer (which must be at least MAXPATHLEN
* characters long).
*/
int read_filesfrom_line(int fd, char *fname)
{
char ch, *s, *eob = fname + MAXPATHLEN - 1;
int cnt;
extern int io_timeout;
extern int eol_nulls;
extern char *remote_filesfrom_file;
extern int am_server;
int reading_remotely = remote_filesfrom_file || (am_server && fd == 0);
int nulls = eol_nulls || reading_remotely;
start:
s = fname;
while (1) {
cnt = read(fd, &ch, 1);
if (cnt < 0 && (errno == EWOULDBLOCK
|| errno == EINTR || errno == EAGAIN)) {
struct timeval tv;
fd_set fds;
FD_ZERO(&fds);
FD_SET(fd, &fds);
tv.tv_sec = io_timeout? io_timeout : SELECT_TIMEOUT;
tv.tv_usec = 0;
if (!select(fd+1, &fds, NULL, NULL, &tv))
check_timeout();
continue;
}
if (cnt != 1)
break;
if (nulls? !ch : (ch == '\r' || ch == '\n')) {
/* Skip empty lines if reading locally. */
if (!reading_remotely && s == fname)
continue;
break;
}
if (s < eob)
*s++ = ch;
}
*s = '\0';
/* Dump comments. */
if (*fname == '#' || *fname == ';')
goto start;
return s - fname;
}
/**
* 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)
static void read_loop (int fd, char *buf, size_t len)
{
while (len) {
int n = read_timeout(fd, buf, len);
@@ -471,9 +315,9 @@ static int read_unbuffered(int fd, char *buf, size_t len)
exit_cleanup(RERR_STREAMIO);
}
if (remaining > sizeof line - 1) {
rprintf(FERROR, "multiplexing overflow %ld\n\n",
(long)remaining);
if (remaining > sizeof(line) - 1) {
rprintf(FERROR, "multiplexing overflow %d\n\n",
remaining);
exit_cleanup(RERR_STREAMIO);
}
@@ -494,15 +338,15 @@ static int read_unbuffered(int fd, char *buf, size_t len)
* have been read. If all @p 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;
while (total < N) {
io_flush();
ret = read_unbuffered(fd, buffer + total, N-total);
ret = read_unbuffered (fd, buffer + total, N-total);
total += ret;
}
@@ -523,6 +367,7 @@ int32 read_int(int f)
int64 read_longint(int f)
{
extern int remote_version;
int64 ret;
char b[8];
ret = read_int(f);
@@ -535,8 +380,10 @@ int64 read_longint(int f)
rprintf(FERROR,"Integer overflow - attempted 64 bit offset\n");
exit_cleanup(RERR_UNSUPPORTED);
#else
readfd(f,b,8);
ret = IVAL(b,0) | (((int64)IVAL(b,4))<<32);
if (remote_version >= 16) {
readfd(f,b,8);
ret = IVAL(b,0) | (((int64)IVAL(b,4))<<32);
}
#endif
return ret;
@@ -549,14 +396,14 @@ 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;
}
@@ -579,7 +426,7 @@ static void sleep_for_bwlimit(int bytes_written)
assert(bytes_written > 0);
assert(bwlimit > 0);
tv.tv_usec = bytes_written * 1000 / bwlimit;
tv.tv_sec = tv.tv_usec / 1000000;
tv.tv_usec = tv.tv_usec % 1000000;
@@ -607,11 +454,11 @@ static void writefd_unbuffered(int fd,char *buf,size_t len)
while (total < len) {
FD_ZERO(&w_fds);
FD_ZERO(&r_fds);
FD_SET(fd,&w_fds);
fd_count = fd;
if (io_error_fd != -1) {
FD_ZERO(&r_fds);
FD_SET(io_error_fd,&r_fds);
if (io_error_fd > fd_count)
fd_count = io_error_fd;
@@ -688,7 +535,7 @@ void io_start_buffering(int fd)
{
if (io_buffer) return;
multiplex_out_fd = fd;
io_buffer = (char *)malloc(IO_BUFFER_SIZE);
io_buffer = new_array(char, IO_BUFFER_SIZE);
if (!io_buffer) out_of_memory("writefd");
io_buffer_count = 0;
}
@@ -704,8 +551,8 @@ static void mplex_write(int fd, enum logcode code, char *buf, size_t len)
SIVAL(buffer, 0, ((MPLEX_BASE + (int)code)<<24) + len);
if (n > (sizeof buffer - 4)) {
n = sizeof buffer - 4;
if (n > (sizeof(buffer)-4)) {
n = sizeof(buffer)-4;
}
memcpy(&buffer[4], buf, n);
@@ -765,7 +612,7 @@ static void writefd(int fd,char *buf,size_t len)
len -= n;
io_buffer_count += n;
}
if (io_buffer_count == IO_BUFFER_SIZE) io_flush();
}
}
@@ -793,23 +640,19 @@ void write_int_named(int f, int32 x, const char *phase)
*/
void write_longint(int f, int64 x)
{
extern int remote_version;
char b[8];
if (x <= 0x7FFFFFFF) {
if (remote_version < 16 || x <= 0x7FFFFFFF) {
write_int(f, (int)x);
return;
}
#ifdef NO_INT64
rprintf(FERROR,"Integer overflow - attempted 64 bit offset\n");
exit_cleanup(RERR_UNSUPPORTED);
#else
write_int(f, (int32)0xFFFFFFFF);
SIVAL(b,0,(x&0xFFFFFFFF));
SIVAL(b,4,((x>>32)&0xFFFFFFFF));
writefd(f,b,8);
#endif
}
void write_buf(int f,char *buf,size_t len)
@@ -867,9 +710,9 @@ void io_printf(int fd, const char *format, ...)
va_list ap;
char buf[1024];
int len;
va_start(ap, format);
len = vsnprintf(buf, sizeof buf, format, ap);
len = vsnprintf(buf, sizeof(buf), format, ap);
va_end(ap);
if (len < 0) exit_cleanup(RERR_STREAMIO);

View File

@@ -6,17 +6,17 @@
* 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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
@@ -36,7 +36,7 @@
* 3) add it to the list of available functions (eg: using FN_GLOBAL_STRING())
* 4) If it's a global then initialise it in init_globals. If a local
* (ie. service) parameter then initialise it in the sDefault structure
*
*
*
* Notes:
* The configuration file is processed sequentially for speed. It is NOT
@@ -61,7 +61,7 @@ typedef char pstring[1024];
typedef enum
{
P_BOOL,P_BOOLREV,P_CHAR,P_INTEGER,P_OCTAL,
P_PATH,P_STRING,P_GSTRING,P_ENUM,P_SEP
P_STRING,P_GSTRING,P_ENUM,P_SEP
} parm_type;
typedef enum
@@ -93,7 +93,7 @@ struct parm_struct
#define iSERVICE(i) (*pSERVICE(i))
#define LP_SNUM_OK(iService) (((iService) >= 0) && ((iService) < iNumServices))
/*
/*
* This structure describes global (ie., server-wide) parameters.
*/
typedef struct
@@ -109,8 +109,8 @@ static global Globals;
/*
* This structure describes a single service.
/*
* This structure describes a single service.
*/
typedef struct
{
@@ -144,7 +144,7 @@ typedef struct
/* This is a default service used to prime a services structure */
static service sDefault =
static service sDefault =
{
NULL, /* name */
NULL, /* path */
@@ -156,7 +156,7 @@ static service sDefault =
False, /* transfer logging */
False, /* ignore errors */
"nobody",/* uid */
/* TODO: This causes problems on Debian, where it is called
* "nogroup". Debian patch this in their version of the
* package, but it would be nice to be consistent. Possibly
@@ -165,7 +165,7 @@ static service sDefault =
* What is the best behaviour? Perhaps always using (gid_t)
* -2? */
"nobody",/* gid */
NULL, /* hosts allow */
NULL, /* hosts deny */
NULL, /* auth users */
@@ -222,7 +222,7 @@ static struct enum_list enum_facilities[] = {
{ LOG_NEWS, "news" },
#endif
#ifdef LOG_AUTH
{ LOG_AUTH, "security" },
{ LOG_AUTH, "security" },
#endif
#ifdef LOG_SYSLOG
{ LOG_SYSLOG, "syslog" },
@@ -274,7 +274,7 @@ static struct parm_struct parm_table[] =
{"name", P_STRING, P_LOCAL, &sDefault.name, NULL, 0},
{"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL, 0},
{"lock file", P_STRING, P_LOCAL, &sDefault.lock_file, NULL, 0},
{"path", P_PATH, P_LOCAL, &sDefault.path, NULL, 0},
{"path", P_STRING, P_LOCAL, &sDefault.path, NULL, 0},
{"read only", P_BOOL, P_LOCAL, &sDefault.read_only, NULL, 0},
{"list", P_BOOL, P_LOCAL, &sDefault.list, NULL, 0},
{"use chroot", P_BOOL, P_LOCAL, &sDefault.use_chroot, NULL, 0},
@@ -319,8 +319,8 @@ static void init_locals(void)
/*
In this section all the functions that are used to access the
parameters from the rest of the program are defined
In this section all the functions that are used to access the
parameters from the rest of the program are defined
*/
#define FN_GLOBAL_STRING(fn_name,ptr) \
@@ -376,11 +376,12 @@ FN_LOCAL_INTEGER(lp_timeout, timeout)
FN_LOCAL_INTEGER(lp_max_connections, max_connections)
/* local prototypes */
static int strwicmp(char *psz1, char *psz2);
static int map_parameter(char *parmname);
static BOOL set_boolean(BOOL *pb, char *parmvalue);
static int strwicmp( char *psz1, char *psz2 );
static int map_parameter( char *parmname);
static BOOL set_boolean( BOOL *pb, char *parmvalue );
static int getservicebyname(char *name, service *pserviceDest);
static void copy_service(service *pserviceDest, service *pserviceSource);
static void copy_service( service *pserviceDest,
service *pserviceSource);
static BOOL do_parameter(char *parmname, char *parmvalue);
static BOOL do_section(char *sectionname);
@@ -420,7 +421,7 @@ static void string_set(char **s, const char *v)
/***************************************************************************
add a new service to the services array initialising it with the given
add a new service to the services array initialising it with the given
service
***************************************************************************/
static int add_a_service(service *pservice, char *name)
@@ -432,7 +433,7 @@ static int add_a_service(service *pservice, char *name)
tservice = *pservice;
/* it might already exist */
if (name)
if (name)
{
i = getservicebyname(name,NULL);
if (i >= 0)
@@ -441,10 +442,10 @@ static int add_a_service(service *pservice, char *name)
i = iNumServices;
ServicePtrs = (service **)Realloc(ServicePtrs,sizeof(service *)*num_to_alloc);
ServicePtrs = realloc_array(ServicePtrs, service *, num_to_alloc);
if (ServicePtrs)
pSERVICE(iNumServices) = (service *)malloc(sizeof(service));
pSERVICE(iNumServices) = new(service);
if (!ServicePtrs || !pSERVICE(iNumServices))
return(-1);
@@ -454,7 +455,7 @@ static int add_a_service(service *pservice, char *name)
init_service(pSERVICE(i));
copy_service(pSERVICE(i),&tservice);
if (name)
string_set(&iSERVICE(i).name,name);
string_set(&iSERVICE(i).name,name);
return(i);
}
@@ -492,7 +493,7 @@ static int strwicmp(char *psz1, char *psz2)
}
/***************************************************************************
Map a parameter's string representation to something we can use.
Map a parameter's string representation to something we can use.
Returns False if the parameter string is not recognised, else TRUE.
***************************************************************************/
static int map_parameter(char *parmname)
@@ -502,7 +503,7 @@ static int map_parameter(char *parmname)
if (*parmname == '-')
return(-1);
for (iIndex = 0; parm_table[iIndex].label; iIndex++)
for (iIndex = 0; parm_table[iIndex].label; iIndex++)
if (strwicmp(parm_table[iIndex].label, parmname) == 0)
return(iIndex);
@@ -513,7 +514,7 @@ static int map_parameter(char *parmname)
/***************************************************************************
Set a boolean variable from the text value stored in the passed string.
Returns True in success, False if the passed string does not correctly
Returns True in success, False if the passed string does not correctly
represent a boolean.
***************************************************************************/
static BOOL set_boolean(BOOL *pb, char *parmvalue)
@@ -547,7 +548,7 @@ static int getservicebyname(char *name, service *pserviceDest)
int iService;
for (iService = iNumServices - 1; iService >= 0; iService--)
if (strwicmp(iSERVICE(iService).name, name) == 0)
if (strwicmp(iSERVICE(iService).name, name) == 0)
{
if (pserviceDest != NULL)
copy_service(pserviceDest, pSERVICE(iService));
@@ -563,7 +564,7 @@ static int getservicebyname(char *name, service *pserviceDest)
Copy a service structure to another
***************************************************************************/
static void copy_service(service *pserviceDest,
static void copy_service(service *pserviceDest,
service *pserviceSource)
{
int i;
@@ -571,9 +572,9 @@ static void copy_service(service *pserviceDest,
for (i=0;parm_table[i].label;i++)
if (parm_table[i].ptr && parm_table[i].class == P_LOCAL) {
void *def_ptr = parm_table[i].ptr;
void *src_ptr =
void *src_ptr =
((char *)pserviceSource) + PTR_DIFF(def_ptr,&sDefault);
void *dest_ptr =
void *dest_ptr =
((char *)pserviceDest) + PTR_DIFF(def_ptr,&sDefault);
switch (parm_table[i].type)
@@ -593,7 +594,6 @@ static void copy_service(service *pserviceDest,
*(char *)dest_ptr = *(char *)src_ptr;
break;
case P_PATH:
case P_STRING:
string_set(dest_ptr,*(char **)src_ptr);
break;
@@ -614,7 +614,6 @@ static BOOL lp_do_parameter(int snum, char *parmname, char *parmvalue)
int parmnum, i;
void *parm_ptr=NULL; /* where we are going to store the result */
void *def_ptr=NULL;
char *cp;
parmnum = map_parameter(parmname);
@@ -661,15 +660,6 @@ static BOOL lp_do_parameter(int snum, char *parmname, char *parmvalue)
sscanf(parmvalue,"%o",(int *)parm_ptr);
break;
case P_PATH:
string_set(parm_ptr,parmvalue);
if ((cp = *(char**)parm_ptr) != NULL) {
int len = strlen(cp);
while (len > 1 && cp[len-1] == '/') len--;
cp[len] = '\0';
}
break;
case P_STRING:
string_set(parm_ptr,parmvalue);
break;
@@ -721,7 +711,7 @@ static BOOL do_section(char *sectionname)
init_locals();
/* if we've just struck a global section, note the fact. */
bInGlobalSection = isglobal;
bInGlobalSection = isglobal;
/* check for multiple global sections */
if (bInGlobalSection)
@@ -753,7 +743,7 @@ static BOOL do_section(char *sectionname)
/***************************************************************************
Load the services array from the services file. Return True on success,
Load the services array from the services file. Return True on success,
False on failure.
***************************************************************************/
BOOL lp_load(char *pszFname, int globals_only)
@@ -763,11 +753,11 @@ BOOL lp_load(char *pszFname, int globals_only)
extern int am_root;
pstring n2;
BOOL bRetval;
bRetval = False;
bInGlobalSection = True;
init_globals();
if (pszFname)
@@ -780,7 +770,7 @@ BOOL lp_load(char *pszFname, int globals_only)
/* We get sections first, so have to start 'behind' to make up */
iServiceIndex = -1;
bRetval = pm_process(n2, globals_only?NULL:do_section, do_parameter);
return (bRetval);
}
@@ -804,7 +794,7 @@ int lp_number(char *name)
int iService;
for (iService = iNumServices - 1; iService >= 0; iService--)
if (strequal(lp_name(iService), name))
if (strequal(lp_name(iService), name))
break;
return (iService);

28
log.c
View File

@@ -90,10 +90,10 @@ static struct err_list *err_list_tail;
static void err_list_add(int code, char *buf, int len)
{
struct err_list *el;
el = (struct err_list *)malloc(sizeof(*el));
el = new(struct err_list);
if (!el) exit_cleanup(RERR_MALLOC);
el->next = NULL;
el->buf = malloc(len+4);
el->buf = new_array(char, len+4);
if (!el->buf) exit_cleanup(RERR_MALLOC);
memcpy(el->buf+4, buf, len);
SIVAL(el->buf, 0, ((code+MPLEX_BASE)<<24) | len);
@@ -238,9 +238,9 @@ void rwrite(enum logcode code, char *buf, int len)
return;
}
/* next, if we are a server and multiplexing is enabled,
* pass it to the other side. */
if (am_server && io_multiplex_write(code, buf, len)) {
/* next, if we are a server but not in daemon mode, and multiplexing
* is enabled, pass it to the other side. */
if (am_server && !am_daemon && io_multiplex_write(code, buf, len)) {
return;
}
@@ -250,9 +250,7 @@ void rwrite(enum logcode code, char *buf, int len)
* side because we don't want the client to see most errors for
* security reasons. We do want early messages when running daemon
* mode over a remote shell to go to the remote side; those will
* fall through to the next case.
* Note that this is only for the time before multiplexing is enabled.
*/
* fall through to the next case. */
if (am_daemon && (!am_server || log_initialised)) {
static int depth;
int priority = LOG_INFO;
@@ -572,3 +570,17 @@ void log_exit(int code, const char *file, int line)
name, 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.
* Called when a file starts to be transferred.
*/
void log_transfer(struct file_struct *file, const char *fname)
{
extern int verbose;
if (!verbose) return;
rprintf(FINFO, "%s\n", fname);
}

156
match.c
View File

@@ -1,17 +1,17 @@
/*
/*
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
@@ -19,9 +19,12 @@
#include "rsync.h"
extern int csum_length;
extern int verbose;
extern int am_server;
extern int do_progress;
extern int remote_version;
typedef unsigned short tag;
@@ -40,8 +43,8 @@ static int total_matches;
extern struct stats stats;
struct target {
tag t;
int i;
tag t;
int i;
};
static struct target *targets;
@@ -53,33 +56,34 @@ static int *tag_table;
static int compare_targets(struct target *t1,struct target *t2)
{
return (int)t1->t - (int)t2->t;
return((int)t1->t - (int)t2->t);
}
static void build_hash_table(struct sum_struct *s)
{
int i;
int i;
if (!tag_table)
tag_table = (int *)malloc(sizeof(tag_table[0])*TABLESIZE);
if (!tag_table)
tag_table = new_array(int, TABLESIZE);
targets = (struct target *)malloc(sizeof(targets[0])*s->count);
if (!tag_table || !targets)
out_of_memory("build_hash_table");
targets = new_array(struct target, s->count);
if (!tag_table || !targets)
out_of_memory("build_hash_table");
for (i = 0; i < (int)s->count; i++) {
targets[i].i = i;
targets[i].t = gettag(s->sums[i].sum1);
}
for (i=0;i<(int) s->count;i++) {
targets[i].i = i;
targets[i].t = gettag(s->sums[i].sum1);
}
qsort(targets,s->count,sizeof(targets[0]),(int (*)())compare_targets);
qsort(targets,s->count,sizeof(targets[0]),(int (*)())compare_targets);
for (i = 0; i < TABLESIZE; i++)
tag_table[i] = NULL_TAG;
for (i=0;i<TABLESIZE;i++)
tag_table[i] = NULL_TAG;
for (i = s->count-1; i >= 0; i--)
tag_table[targets[i].t] = i;
for (i=s->count-1;i>=0;i--) {
tag_table[targets[i].t] = i;
}
}
@@ -115,8 +119,8 @@ static void matched(int f,struct sum_struct *s,struct map_struct *buf,
stats.matched_data += s->sums[i].len;
n += s->sums[i].len;
}
for (j = 0; j < n; j += CHUNK_SIZE) {
for (j=0;j<n;j+=CHUNK_SIZE) {
int n1 = MIN(CHUNK_SIZE,n-j);
sum_update(map_ptr(buf,last_match+j,n1),n1);
}
@@ -127,7 +131,7 @@ static void matched(int f,struct sum_struct *s,struct map_struct *buf,
else
last_match = offset;
if (buf && do_progress) {
if (buf) {
show_progress(last_match, buf->file_size);
if (i == -1) end_progress(buf->file_size);
@@ -141,7 +145,7 @@ static void hash_search(int f,struct sum_struct *s,
OFF_T offset, end;
int j,k, last_i;
char sum2[SUM_LENGTH];
uint32 s1, s2, sum;
uint32 s1, s2, sum;
schar *map;
/* last_i is used to encourage adjacent matches, allowing the RLL coding of the
@@ -150,34 +154,36 @@ static void hash_search(int f,struct sum_struct *s,
if (verbose > 2)
rprintf(FINFO,"hash search b=%ld len=%.0f\n",
(long) s->blength, (double)len);
k = MIN(len, (OFF_T)s->blength);
(long) s->n, (double)len);
/* cast is to make s->n signed; it should always be reasonably
* small */
k = MIN(len, (OFF_T) s->n);
map = (schar *)map_ptr(buf,0,k);
sum = get_checksum1((char *)map, k);
s1 = sum & 0xFFFF;
s2 = sum >> 16;
if (verbose > 3)
rprintf(FINFO, "sum=%.8x k=%d\n", sum, k);
offset = 0;
end = len + 1 - s->sums[s->count-1].len;
if (verbose > 3)
rprintf(FINFO, "hash search s->blength=%ld len=%.0f count=%ld\n",
(long) s->blength, (double) len, (long) s->count);
rprintf(FINFO, "hash search s->n=%ld len=%.0f count=%ld\n",
(long) s->n, (double) len, (long) s->count);
do {
tag t = gettag2(s1,s2);
int done_csum2 = 0;
j = tag_table[t];
if (verbose > 4)
rprintf(FINFO,"offset=%.0f sum=%08x\n",(double)offset,sum);
if (j == NULL_TAG) {
goto null_tag;
}
@@ -186,47 +192,47 @@ static void hash_search(int f,struct sum_struct *s,
tag_hits++;
for (; j < (int) s->count && targets[j].t == t; j++) {
int l, i = targets[j].i;
if (sum != s->sums[i].sum1) continue;
/* also make sure the two blocks are the same length */
l = MIN((OFF_T)s->blength, len-offset);
if (l != s->sums[i].len) continue;
l = MIN(s->n,len-offset);
if (l != s->sums[i].len) continue;
if (verbose > 3)
rprintf(FINFO,"potential match at %.0f target=%d %d sum=%08x\n",
(double)offset,j,i,sum);
if (!done_csum2) {
map = (schar *)map_ptr(buf,offset,l);
get_checksum2((char *)map,l,sum2);
done_csum2 = 1;
}
if (memcmp(sum2,s->sums[i].sum2,s->s2length) != 0) {
if (memcmp(sum2,s->sums[i].sum2,csum_length) != 0) {
false_alarms++;
continue;
}
/* we've found a match, but now check to see
* if last_i can hint at a better match */
if last_i can hint at a better match */
for (j++; j < (int) s->count && targets[j].t == t; j++) {
int i2 = targets[j].i;
if (i2 == last_i + 1) {
if (sum != s->sums[i2].sum1) break;
if (memcmp(sum2,s->sums[i2].sum2,s->s2length) != 0) break;
/* we've found an adjacent match - the RLL coder
* will be happy */
if (memcmp(sum2,s->sums[i2].sum2,csum_length) != 0) break;
/* we've found an adjacent match - the RLL coder
will be happy */
i = i2;
break;
}
}
last_i = i;
matched(f,s,buf,offset,i);
offset += s->sums[i].len - 1;
k = MIN((OFF_T)s->blength, len-offset);
k = MIN((len-offset), s->n);
map = (schar *)map_ptr(buf,offset,k);
sum = get_checksum1((char *)map, k);
s1 = sum & 0xFFFF;
@@ -234,13 +240,13 @@ static void hash_search(int f,struct sum_struct *s,
matches++;
break;
}
null_tag:
/* Trim off the first byte from the checksum */
map = (schar *)map_ptr(buf,offset,k+1);
s1 -= map[0] + CHAR_OFFSET;
s2 -= k * (map[0]+CHAR_OFFSET);
/* Add on the next byte (if there is one) to the checksum */
if (k < (len-offset)) {
s1 += (map[k]+CHAR_OFFSET);
@@ -255,13 +261,13 @@ static void hash_search(int f,struct sum_struct *s,
match. The 3 reads are caused by the
running match, the checksum update and the
literal send. */
if (offset > last_match
&& offset-last_match >= CHUNK_SIZE+s->blength
&& end-offset > CHUNK_SIZE) {
matched(f,s,buf,offset - s->blength, -2);
if (offset > last_match &&
offset-last_match >= CHUNK_SIZE+s->n &&
(end-offset > CHUNK_SIZE)) {
matched(f,s,buf,offset - s->n, -2);
}
} while (++offset < end);
matched(f,s,buf,len,-1);
map_ptr(buf,len-1,1);
}
@@ -289,25 +295,25 @@ void match_sums(int f, struct sum_struct *s, struct map_struct *buf, OFF_T len)
last_match = 0;
false_alarms = 0;
tag_hits = 0;
matches = 0;
data_transfer = 0;
matches=0;
data_transfer=0;
sum_init();
if (len > 0 && s->count>0) {
build_hash_table(s);
if (verbose > 2)
if (verbose > 2)
rprintf(FINFO,"built hash table\n");
hash_search(f,s,buf,len);
if (verbose > 2)
if (verbose > 2)
rprintf(FINFO,"done hash search\n");
} else {
OFF_T j;
/* by doing this in pieces we avoid too many seeks */
for (j = 0; j < len-CHUNK_SIZE; j += CHUNK_SIZE) {
for (j=0;j<(len-CHUNK_SIZE);j+=CHUNK_SIZE) {
int n1 = MIN(CHUNK_SIZE,(len-CHUNK_SIZE)-j);
matched(f,s,buf,j+n1,-2);
}
@@ -316,21 +322,23 @@ void match_sums(int f, struct sum_struct *s, struct map_struct *buf, OFF_T len)
sum_end(file_sum);
if (verbose > 2)
rprintf(FINFO,"sending file_sum\n");
write_buf(f,file_sum,MD4_SUM_LENGTH);
if (write_batch) /* dw */
write_batch_delta_file(file_sum, MD4_SUM_LENGTH);
if (remote_version >= 14) {
if (verbose > 2)
rprintf(FINFO,"sending file_sum\n");
write_buf(f,file_sum,MD4_SUM_LENGTH);
if (write_batch) /* dw */
write_batch_delta_file(file_sum, MD4_SUM_LENGTH);
}
if (targets) {
free(targets);
targets=NULL;
}
if (verbose > 2)
rprintf(FINFO, "false_alarms=%d tag_hits=%d matches=%d\n",
false_alarms, tag_hits, matches);
total_tag_hits += tag_hits;
total_false_alarms += false_alarms;
total_matches += matches;

View File

@@ -207,7 +207,7 @@ static BOOL Section( FILE *InFile, BOOL (*sfunc)(char *) )
if( i > (bSize - 2) )
{
bSize += BUFR_INC;
bufr = Realloc( bufr, bSize );
bufr = realloc_array( bufr, char, bSize );
if( NULL == bufr )
{
rprintf(FERROR, "%s Memory re-allocation failure.", func);
@@ -301,7 +301,7 @@ static BOOL Parameter( FILE *InFile, BOOL (*pfunc)(char *, char *), int c )
if( i > (bSize - 2) ) /* Ensure there's space for next char. */
{
bSize += BUFR_INC;
bufr = Realloc( bufr, bSize );
bufr = realloc_array( bufr, char, bSize );
if( NULL == bufr )
{
rprintf(FERROR, "%s Memory re-allocation failure.", func) ;
@@ -366,7 +366,7 @@ static BOOL Parameter( FILE *InFile, BOOL (*pfunc)(char *, char *), int c )
if( i > (bSize - 2) ) /* Make sure there's enough room. */
{
bSize += BUFR_INC;
bufr = Realloc( bufr, bSize );
bufr = realloc_array( bufr, char, bSize );
if( NULL == bufr )
{
rprintf(FERROR, "%s Memory re-allocation failure.", func) ;
@@ -530,7 +530,7 @@ BOOL pm_process( char *FileName,
else /* If we don't have a buffer */
{ /* allocate one, then parse, */
bSize = BUFR_INC; /* then free. */
bufr = (char *)malloc( bSize );
bufr = new_array( char, bSize );
if( NULL == bufr )
{
rprintf(FERROR,"%s memory allocation failure.\n", func);

View File

@@ -23,7 +23,7 @@
extern int verbose;
extern int recurse;
extern int delete_mode;
extern int protocol_version;
extern int remote_version;
extern int csum_length;
extern struct stats stats;
extern int dry_run;
@@ -35,10 +35,7 @@ extern int io_error;
extern char *tmpdir;
extern char *compare_dest;
extern int make_backups;
extern int do_progress;
extern char *backup_dir;
extern char *backup_suffix;
extern int backup_suffix_len;
static struct delete_list {
DEV64_T dev;
@@ -59,7 +56,7 @@ static int delete_already_done(struct file_list *flist,int j)
for (i=0;i<dlist_len;i++) {
if (st.st_ino == delete_list[i].inode &&
(DEV64_T)st.st_dev == delete_list[i].dev)
st.st_dev == delete_list[i].dev)
return 1;
}
@@ -70,7 +67,8 @@ static void add_delete_entry(struct file_struct *file)
{
if (dlist_len == dlist_alloc_len) {
dlist_alloc_len += 1024;
delete_list = (struct delete_list *)Realloc(delete_list, sizeof(delete_list[0])*dlist_alloc_len);
delete_list = realloc_array(delete_list, struct delete_list,
dlist_alloc_len);
if (!delete_list) out_of_memory("add_delete_entry");
}
@@ -82,33 +80,26 @@ static void add_delete_entry(struct file_struct *file)
rprintf(FINFO,"added %s to delete list\n", f_name(file));
}
static void delete_one(char *fn, int is_dir)
static void delete_one(struct file_struct *f)
{
if (!is_dir) {
if (robust_unlink(fn) != 0) {
rprintf(FERROR, "delete_one: unlink %s failed: %s\n",
full_fname(fn), strerror(errno));
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));
} else if (verbose) {
rprintf(FINFO, "deleting %s\n", fn);
rprintf(FINFO,"deleting %s\n",f_name(f));
}
} else {
if (do_rmdir(fn) != 0) {
if (errno != ENOTEMPTY && errno != EEXIST) {
rprintf(FERROR, "delete_one: rmdir %s failed: %s\n",
full_fname(fn), strerror(errno));
}
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));
} else if (verbose) {
rprintf(FINFO, "deleting directory %s\n", fn);
rprintf(FINFO,"deleting directory %s\n",f_name(f));
}
}
}
static int is_backup_file(char *fn)
{
int k = strlen(fn) - backup_suffix_len;
return k > 0 && strcmp(fn+k, backup_suffix) == 0;
}
/* this deletes any files on the receiving side that are not present
@@ -136,7 +127,7 @@ void delete_files(struct file_list *flist)
if (!S_ISDIR(flist->files[j]->mode) ||
!(flist->files[j]->flags & FLAG_DELETE)) continue;
if (protocol_version < 19 &&
if (remote_version < 19 &&
delete_already_done(flist, j)) continue;
name = strdup(f_name(flist->files[j]));
@@ -152,20 +143,20 @@ void delete_files(struct file_list *flist)
for (i=local_file_list->count-1;i>=0;i--) {
if (max_delete && deletion_count > max_delete) break;
if (!local_file_list->files[i]->basename) continue;
if (protocol_version < 19 &&
if (remote_version < 19 &&
S_ISDIR(local_file_list->files[i]->mode))
add_delete_entry(local_file_list->files[i]);
if (-1 == flist_find(flist,local_file_list->files[i])) {
char *f = f_name(local_file_list->files[i]);
if (make_backups && (backup_dir || !is_backup_file(f))) {
int k = strlen(f) - strlen(backup_suffix);
/* Hi Andrew, do we really need to play with backup_suffix here? */
if (make_backups && ((k <= 0) ||
(strcmp(f+k,backup_suffix) != 0))) {
(void) make_backup(f);
if (verbose)
rprintf(FINFO, "deleting %s\n", f);
} else {
int mode = local_file_list->files[i]->mode;
delete_one(f, S_ISDIR(mode) != 0);
deletion_count++;
delete_one(local_file_list->files[i]);
}
deletion_count++;
}
}
flist_free(local_file_list);
@@ -174,63 +165,40 @@ void delete_files(struct file_list *flist)
}
/*
* get_tmpname() - create a tmp filename for a given filename
*
* If a tmpdir is defined, use that as the directory to
* put it in. Otherwise, the tmp filename is in the same
* directory as the given name. Note that there may be no
* directory at all in the given name!
*
* The tmp filename is basically the given filename with a
* dot prepended, and .XXXXXX appended (for mkstemp() to
* put its unique gunk in). Take care to not exceed
* either the MAXPATHLEN or NAME_MAX, esp. the last, as
* the basename basically becomes 8 chars longer. In that
* case, the original name is shortened sufficiently to
* make it all fit.
*
* Of course, there's no real reason for the tmp name to
* look like the original, except to satisfy us humans.
* As long as it's unique, rsync will work.
*/
static int get_tmpname(char *fnametmp, char *fname)
{
char *f;
int length = 0;
int maxname;
/* open tmp file */
if (tmpdir) {
strlcpy(fnametmp, tmpdir, MAXPATHLEN - 2);
length = strlen(fnametmp);
fnametmp[length++] = '/';
fnametmp[length] = '\0'; /* always NULL terminated */
}
if ((f = strrchr(fname, '/')) != NULL) {
++f;
if (!tmpdir) {
length = f - fname;
/* copy up to and including the slash */
strlcpy(fnametmp, fname, length + 1);
f = strrchr(fname,'/');
if (f == NULL)
f = fname;
else
f++;
if (strlen(tmpdir)+strlen(f)+10 > MAXPATHLEN) {
rprintf(FERROR,"filename too long\n");
return 0;
}
} else {
f = fname;
snprintf(fnametmp,MAXPATHLEN, "%s/.%s.XXXXXX",tmpdir,f);
return 1;
}
fnametmp[length++] = '.';
fnametmp[length] = '\0'; /* always NULL terminated */
maxname = MIN(MAXPATHLEN - 7 - length, NAME_MAX - 8);
f = strrchr(fname,'/');
if (maxname < 1) {
rprintf(FERROR, "temporary filename too long: %s\n", fname);
fnametmp[0] = '\0';
if (strlen(fname)+9 > MAXPATHLEN) {
rprintf(FERROR,"filename too long\n");
return 0;
}
strlcpy(fnametmp + length, f, maxname);
strcat(fnametmp + length, ".XXXXXX");
if (f) {
*f = 0;
snprintf(fnametmp,MAXPATHLEN,"%s/.%s.XXXXXX",
fname,f+1);
*f = '/';
} else {
snprintf(fnametmp,MAXPATHLEN,".%s.XXXXXX",fname);
}
return 1;
}
@@ -240,8 +208,7 @@ static int receive_data(int f_in,struct map_struct *buf,int fd,char *fname,
OFF_T total_size)
{
int i;
struct sum_struct sum;
unsigned int len;
unsigned int n,remainder,len,count;
OFF_T offset = 0;
OFF_T offset2;
char *data;
@@ -249,13 +216,15 @@ static int receive_data(int f_in,struct map_struct *buf,int fd,char *fname,
static char file_sum2[MD4_SUM_LENGTH];
char *map=NULL;
read_sum_head(f_in, &sum);
count = read_int(f_in);
n = read_int(f_in);
remainder = read_int(f_in);
sum_init();
for (i=recv_token(f_in,&data); i != 0; i=recv_token(f_in,&data)) {
if (do_progress)
show_progress(offset, total_size);
show_progress(offset, total_size);
if (i > 0) {
extern int cleanup_got_literal;
@@ -271,8 +240,7 @@ static int receive_data(int f_in,struct map_struct *buf,int fd,char *fname,
sum_update(data,i);
if (fd != -1 && write_file(fd,data,i) != i) {
rprintf(FERROR, "write failed on %s: %s\n",
full_fname(fname), strerror(errno));
rprintf(FERROR,"write failed on %s : %s\n",fname,strerror(errno));
exit_cleanup(RERR_FILEIO);
}
offset += i;
@@ -280,10 +248,10 @@ static int receive_data(int f_in,struct map_struct *buf,int fd,char *fname,
}
i = -(i+1);
offset2 = i*(OFF_T)sum.blength;
len = sum.blength;
if (i == (int) sum.count-1 && sum.remainder != 0)
len = sum.remainder;
offset2 = i*(OFF_T)n;
len = n;
if (i == (int) count-1 && remainder != 0)
len = remainder;
stats.matched_data += len;
@@ -299,31 +267,32 @@ static int receive_data(int f_in,struct map_struct *buf,int fd,char *fname,
}
if (fd != -1 && write_file(fd,map,len) != (int) len) {
rprintf(FERROR, "write failed on %s: %s\n",
full_fname(fname), strerror(errno));
rprintf(FERROR,"write failed on %s : %s\n",
fname,strerror(errno));
exit_cleanup(RERR_FILEIO);
}
offset += len;
}
if (do_progress)
end_progress(total_size);
end_progress(total_size);
if (fd != -1 && offset > 0 && sparse_end(fd) != 0) {
rprintf(FERROR, "write failed on %s: %s\n",
full_fname(fname), strerror(errno));
rprintf(FERROR,"write failed on %s : %s\n",
fname,strerror(errno));
exit_cleanup(RERR_FILEIO);
}
sum_end(file_sum1);
read_buf(f_in,file_sum2,MD4_SUM_LENGTH);
if (verbose > 2) {
rprintf(FINFO,"got file_sum\n");
}
if (fd != -1
&& memcmp(file_sum1,file_sum2,MD4_SUM_LENGTH) != 0) {
return 0;
if (remote_version >= 14) {
read_buf(f_in,file_sum2,MD4_SUM_LENGTH);
if (verbose > 2) {
rprintf(FINFO,"got file_sum\n");
}
if (fd != -1 &&
memcmp(file_sum1,file_sum2,MD4_SUM_LENGTH) != 0) {
return 0;
}
}
return 1;
}
@@ -362,7 +331,7 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
i = read_int(f_in);
if (i == -1) {
if (phase==0) {
if (phase==0 && remote_version >= 13) {
phase++;
csum_length = SUM_LENGTH;
if (verbose > 2)
@@ -389,8 +358,8 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
fname = local_name;
if (dry_run) {
if (!am_server && verbose) { /* log transfer */
rprintf(FINFO, "%s\n", fname);
if (!am_server) {
log_transfer(file, fname);
}
continue;
}
@@ -414,35 +383,22 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
}
if (fd1 != -1 && do_fstat(fd1,&st) != 0) {
rprintf(FERROR, "fstat %s failed: %s\n",
full_fname(fnamecmp), strerror(errno));
rprintf(FERROR,"fstat %s : %s\n",fnamecmp,strerror(errno));
receive_data(f_in,NULL,-1,NULL,file->length);
close(fd1);
continue;
}
if (fd1 != -1 && S_ISDIR(st.st_mode) && fnamecmp == fname) {
/* this special handling for directories
* wouldn't be necessary if robust_rename()
* and the underlying robust_unlink could cope
* with directories
*/
rprintf(FERROR,"recv_files: %s is a directory\n",
full_fname(fnamecmp));
receive_data(f_in, NULL, -1, NULL, file->length);
if (fd1 != -1 && !S_ISREG(st.st_mode)) {
rprintf(FERROR,"%s : not a regular file (recv_files)\n",fnamecmp);
receive_data(f_in,NULL,-1,NULL,file->length);
close(fd1);
continue;
}
if (fd1 != -1 && !S_ISREG(st.st_mode)) {
close(fd1);
fd1 = -1;
buf = NULL;
}
if (fd1 != -1 && !preserve_perms) {
/* if the file exists already and we aren't preserving
permissions then act as though the remote end sent
/* if the file exists already and we aren't perserving
presmissions then act as though the remote end sent
us the file permissions we already have */
file->mode = st.st_mode;
}
@@ -480,8 +436,7 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
fd2 = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS);
}
if (fd2 == -1) {
rprintf(FERROR, "mkstemp %s failed: %s\n",
full_fname(fnametmp), strerror(errno));
rprintf(FERROR,"mkstemp %s failed: %s\n",fnametmp,strerror(errno));
receive_data(f_in,buf,-1,NULL,file->length);
if (buf) unmap_file(buf);
if (fd1 != -1) close(fd1);
@@ -490,8 +445,8 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
cleanup_set(fnametmp, fname, file, buf, fd1, fd2);
if (!am_server && verbose) { /* log transfer */
rprintf(FINFO, "%s\n", fname);
if (!am_server) {
log_transfer(file, fname);
}
/* recv file data */
@@ -515,7 +470,7 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
if (!recv_ok) {
if (csum_length == SUM_LENGTH) {
rprintf(FERROR,"ERROR: file corruption in %s. File changed during transfer?\n",
full_fname(fname));
fname);
} else {
if (verbose > 1)
rprintf(FINFO,"redoing %s(%d)\n",fname,i);

78
rsync.c
View File

@@ -1,17 +1,17 @@
/*
/*
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
@@ -43,8 +43,8 @@ void free_sums(struct sum_struct *s)
/*
* delete a file or directory. If force_delete is set then delete
* recursively
* delete a file or directory. If force_delete is set then delete
* recursively
*/
int delete_file(char *fname)
{
@@ -67,31 +67,29 @@ int delete_file(char *fname)
if (!S_ISDIR(st.st_mode)) {
if (robust_unlink(fname) == 0 || errno == ENOENT) return 0;
rprintf(FERROR, "delete_file: unlink %s failed: %s\n",
full_fname(fname), strerror(errno));
rprintf(FERROR,"delete_file: unlink(%s) : %s\n", fname, strerror(errno));
return -1;
}
if (do_rmdir(fname) == 0 || errno == ENOENT) return 0;
if (!force_delete || !recurse ||
if (!force_delete || !recurse ||
(errno != ENOTEMPTY && errno != EEXIST)) {
rprintf(FERROR, "delete_file: rmdir %s failed: %s\n",
full_fname(fname), strerror(errno));
rprintf(FERROR,"delete_file: rmdir(%s) : %s\n", fname, strerror(errno));
return -1;
}
/* now we do a recsursive delete on the directory ... */
d = opendir(fname);
if (!d) {
rprintf(FERROR, "delete_file: opendir %s failed: %s\n",
full_fname(fname), strerror(errno));
rprintf(FERROR,"delete_file: opendir(%s): %s\n",
fname,strerror(errno));
return -1;
}
for (errno = 0, di = readdir(d); di; errno = 0, di = readdir(d)) {
for (di=readdir(d); di; di=readdir(d)) {
char *dname = d_name(di);
if (strcmp(dname,".") == 0
|| strcmp(dname,"..") == 0)
if (strcmp(dname,".")==0 ||
strcmp(dname,"..")==0)
continue;
snprintf(buf, sizeof(buf), "%s/%s", fname, dname);
if (verbose > 0)
@@ -100,19 +98,12 @@ int delete_file(char *fname)
closedir(d);
return -1;
}
}
if (errno) {
rprintf(FERROR, "delete_file: readdir %s failed: %s\n",
full_fname(fname), strerror(errno));
closedir(d);
return -1;
}
}
closedir(d);
if (do_rmdir(fname) != 0) {
rprintf(FERROR, "delete_file: rmdir %s failed: %s\n",
full_fname(fname), strerror(errno));
rprintf(FERROR,"delete_file: rmdir(%s) : %s\n", fname, strerror(errno));
return -1;
}
@@ -133,7 +124,7 @@ static int is_in_group(gid_t gid)
/* treat failure (-1) as if not member of any group */
ngroups = getgroups(0, 0);
if (ngroups > 0) {
gidset = (GETGROUPS_T *) malloc(ngroups * sizeof(GETGROUPS_T));
gidset = new_array(GETGROUPS_T, ngroups);
ngroups = getgroups(ngroups, gidset);
}
}
@@ -154,7 +145,7 @@ static int is_in_group(gid_t gid)
}
int set_perms(char *fname,struct file_struct *file,STRUCT_STAT *st,
int report)
int report)
{
int updated = 0;
STRUCT_STAT st2;
@@ -164,8 +155,7 @@ int set_perms(char *fname,struct file_struct *file,STRUCT_STAT *st,
if (!st) {
if (link_stat(fname,&st2) != 0) {
rprintf(FERROR, "stat %s failed: %s\n",
full_fname(fname), strerror(errno));
rprintf(FERROR,"stat %s : %s\n",fname,strerror(errno));
return 0;
}
st = &st2;
@@ -177,8 +167,8 @@ int set_perms(char *fname,struct file_struct *file,STRUCT_STAT *st,
because some filesystems can't do it */
if (set_modtime(fname,file->modtime) != 0 &&
!S_ISDIR(st->st_mode)) {
rprintf(FERROR, "failed to set times on %s: %s\n",
full_fname(fname), strerror(errno));
rprintf(FERROR,"failed to set times on %s : %s\n",
fname,strerror(errno));
return 0;
} else {
updated = 1;
@@ -199,8 +189,7 @@ int set_perms(char *fname,struct file_struct *file,STRUCT_STAT *st,
change_gid?file->gid:st->st_gid) != 0) {
/* shouldn't have attempted to change uid or gid
unless have the privilege */
rprintf(FERROR, "chown %s failed: %s\n",
full_fname(fname), strerror(errno));
rprintf(FERROR,"chown %s : %s\n", fname,strerror(errno));
return 0;
}
/* a lchown had been done - we have to re-stat if the
@@ -214,17 +203,17 @@ int set_perms(char *fname,struct file_struct *file,STRUCT_STAT *st,
#ifdef HAVE_CHMOD
if (!S_ISLNK(st->st_mode)) {
if ((st->st_mode & CHMOD_BITS) != (file->mode & CHMOD_BITS)) {
if (st->st_mode != file->mode) {
updated = 1;
if (do_chmod(fname,(file->mode & CHMOD_BITS)) != 0) {
rprintf(FERROR, "failed to set permissions on %s: %s\n",
full_fname(fname), strerror(errno));
if (do_chmod(fname,file->mode) != 0) {
rprintf(FERROR,"failed to set permissions on %s : %s\n",
fname,strerror(errno));
return 0;
}
}
}
#endif
if (verbose > 1 && report) {
if (updated)
rprintf(FINFO,"%s\n",fname);
@@ -251,18 +240,17 @@ void finish_transfer(char *fname, char *fnametmp, struct file_struct *file)
/* move tmp file over real file */
if (robust_rename(fnametmp,fname) != 0) {
if (errno == EXDEV) {
/* rename failed on cross-filesystem link.
/* rename failed on cross-filesystem link.
Copy the file instead. */
if (copy_file(fnametmp,fname, file->mode & INITACCESSPERMS)) {
rprintf(FERROR, "copy %s -> \"%s\": %s\n",
full_fname(fnametmp), fname,
strerror(errno));
rprintf(FERROR,"copy %s -> %s : %s\n",
fnametmp,fname,strerror(errno));
} else {
set_perms(fname,file,NULL,0);
}
} else {
rprintf(FERROR,"rename %s -> \"%s\": %s\n",
full_fname(fnametmp), fname, strerror(errno));
rprintf(FERROR,"rename %s -> %s : %s\n",
fnametmp,fname,strerror(errno));
}
do_unlink(fnametmp);
} else {

129
rsync.h
View File

@@ -50,28 +50,20 @@
#define SAME_TIME (1<<7)
/* update this if you make incompatible changes */
#define PROTOCOL_VERSION 27
#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.
*
* Interoperation with old but supported protocol versions
* should cause a warning to be printed. At a future date
* the old protocol will become the minimum and
* compatibility code removed.
*
* There are two possible explanations for the limit at
* MAX_PROTOCOL_VERSION: 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 MIN_PROTOCL_VERSION and
* MAX_PROTOCOL_VERSION. */
#define MIN_PROTOCOL_VERSION 17
#define OLD_PROTOCOL_VERSION 20
#define MAX_PROTOCOL_VERSION 40
* 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 MIN_PROTOCOL_VERSION 15
#define MAX_PROTOCOL_VERSION 30
#define RSYNC_PORT 873
@@ -85,16 +77,6 @@
#define MPLEX_BASE 7
#define NO_EXCLUDES 0
#define SERVER_EXCLUDES 1
#define ALL_EXCLUDES 2
#define MISSING_OK 0
#define MISSING_FATAL 1
#define ADD_INCLUDE 1
#define ADD_EXCLUDE 0
/* 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. */
@@ -124,10 +106,6 @@ enum logcode {FNONE=0, FERROR=1, FINFO=2, FLOG=3 };
#include <stdlib.h>
#endif
#if defined(HAVE_MALLOC_H) && (defined(HAVE_MALLINFO) || !defined(HAVE_STDLIB_H))
#include <malloc.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
@@ -136,6 +114,10 @@ enum logcode {FNONE=0, FERROR=1, FINFO=2, FLOG=3 };
#include <string.h>
#endif
#ifdef HAVE_MALLOC_H
#include <malloc.h>
#endif
#ifdef TIME_WITH_SYS_TIME
#include <sys/time.h>
#include <time.h>
@@ -192,10 +174,20 @@ enum logcode {FNONE=0, FERROR=1, FINFO=2, FLOG=3 };
#endif
#endif
#ifdef HAVE_FNMATCH
#include <fnmatch.h>
#else
#include "lib/fnmatch.h"
#endif
#ifdef HAVE_GLOB_H
#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>
@@ -281,17 +273,6 @@ enum logcode {FNONE=0, FERROR=1, FINFO=2, FLOG=3 };
#define NO_INT64
#endif
#if (SIZEOF_LONG == 8)
#define uint64 unsigned long
#elif (SIZEOF_INT == 8)
#define uint64 unsigned int
#elif HAVE_LONGLONG
#define uint64 unsigned long long
#else
/* As long as it gets... */
#define uint64 unsigned off_t
#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
@@ -323,8 +304,8 @@ enum logcode {FNONE=0, FERROR=1, FINFO=2, FLOG=3 };
* cope with platforms on which this is an unsigned int or even a
* struct. Later.
*/
#define INO64_T uint64
#define DEV64_T uint64
#define INO64_T int64
#define DEV64_T int64
#ifndef MIN
#define MIN(a,b) ((a)<(b)?(a):(b))
@@ -341,17 +322,11 @@ enum logcode {FNONE=0, FERROR=1, FINFO=2, FLOG=3 };
/* the length of the md4 checksum */
#define MD4_SUM_LENGTH 16
#define SUM_LENGTH 16
#define SHORT_SUM_LENGTH 2
#define BLOCKSUM_BIAS 10
#ifndef MAXPATHLEN
#define MAXPATHLEN 1024
#endif
#ifndef NAME_MAX
#define NAME_MAX 255
#endif
#ifndef INADDR_NONE
#define INADDR_NONE 0xffffffff
#endif
@@ -410,35 +385,23 @@ struct sum_struct {
OFF_T flength; /**< total file length */
size_t count; /**< how many chunks */
size_t remainder; /**< flength % block_length */
size_t blength; /**< block_length */
size_t s2length; /**< sum2_length */
size_t n; /**< block_length */
struct sum_buf *sums; /**< points to info for each chunk */
};
struct map_struct {
char *p; /* Window pointer */
int fd; /* File Descriptor */
int p_size; /* Window size at allocation */
int p_len; /* Window size after fill */
/* p_size and p_len could be
* consolodated by using a local
* variable in map_ptr() */
int status; /* first errno from read errors */
OFF_T file_size; /* File size (from stat) */
OFF_T p_offset; /* Window start */
OFF_T p_fd_offset; /* offset of cursor in fd ala lseek */
char *p;
int fd,p_size,p_len;
OFF_T file_size, p_offset, p_fd_offset;
};
#define MATCHFLG_WILD 0x0001 /* pattern has '*', '[', and/or '?' */
#define MATCHFLG_WILD2 0x0002 /* pattern has '**' */
#define MATCHFLG_WILD2_PREFIX 0x0004 /* pattern starts with '**' */
#define MATCHFLG_ABS_PATH 0x0008 /* path-match on absolute path */
struct exclude_struct {
char *pattern;
int match_flags;
int regular_exp;
int fnmatch_flags;
int include;
int directory;
int slash_cnt;
int local;
};
struct stats {
@@ -465,7 +428,6 @@ static inline int flist_up(struct file_list *flist, int i)
#include "byteorder.h"
#include "lib/mdfour.h"
#include "lib/wildmatch.h"
#include "lib/permstring.h"
#include "lib/addrinfo.h"
@@ -480,13 +442,11 @@ int asprintf(char **ptr, const char *format, ...);
int vasprintf(char **ptr, const char *format, va_list ap);
#endif
#if !defined(HAVE_VSNPRINTF) || !defined(HAVE_C99_VSNPRINTF)
#define vsnprintf rsync_vsnprintf
int vsnprintf(char *str, size_t count, const char *fmt, va_list args);
#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)
#define snprintf rsync_snprintf
#if !defined(HAVE_SNPRINTF) && !defined(HAVE_C99_VSNPRINTF)
int snprintf(char *str,size_t count,const char *fmt,...);
#endif
@@ -537,16 +497,6 @@ extern int errno;
#define S_IWUSR 0200
#endif
#ifndef ACCESSPERMS
#define ACCESSPERMS 0777
#endif
#ifndef S_ISVTX
#define S_ISVTX 0
#endif
#define CHMOD_BITS (S_ISUID | S_ISGID | S_ISVTX | ACCESSPERMS)
#ifndef _S_IFMT
#define _S_IFMT 0170000
#endif
@@ -610,6 +560,9 @@ extern int errno;
#define IS_DEVICE(mode) (S_ISCHR(mode) || S_ISBLK(mode) || S_ISSOCK(mode) || S_ISFIFO(mode))
#ifndef ACCESSPERMS
#define ACCESSPERMS 0777
#endif
/* Initial mask on permissions given to temporary files. Mask off setuid
bits and group access because of potential race-condition security
holes, and mask other access because mode 707 is bizarre */
@@ -626,6 +579,10 @@ extern int errno;
#endif
/* Convenient wrappers for malloc and realloc. Use them. */
#define new(type) ((type *)malloc(sizeof(type)))
#define new_array(type, num) ((type *)_new_array(sizeof(type), (num)))
#define realloc_array(ptr, type, num) ((type *)_realloc_array((ptr), sizeof(type), (num)))
/* use magic gcc attributes to catch format errors */
void rprintf(enum logcode , const char *, ...)
@@ -642,10 +599,6 @@ void rsyserr(enum logcode, int, const char *, ...)
#define inet_ntoa rep_inet_ntoa
#endif
/* Make sure that the O_BINARY flag is defined. */
#ifndef O_BINARY
#define O_BINARY 0
#endif
#ifndef HAVE_STRLCPY
size_t strlcpy(char *d, const char *s, size_t bufsize);

252
sender.c
View File

@@ -1,17 +1,17 @@
/*
/*
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
@@ -20,6 +20,7 @@
#include "rsync.h"
extern int verbose;
extern int remote_version;
extern int csum_length;
extern struct stats stats;
extern int io_error;
@@ -36,19 +37,6 @@ extern int am_server;
**/
void read_sum_head(int f, struct sum_struct *sum)
{
extern int protocol_version;
sum->count = read_int(f);
sum->blength = read_int(f);
if (protocol_version < 27)
sum->s2length = csum_length;
else
sum->s2length = read_int(f);
sum->remainder = read_int(f);
}
/**
* Receive the checksums for a buffer
**/
@@ -58,27 +46,27 @@ static struct sum_struct *receive_sums(int f)
int i;
OFF_T offset = 0;
s = (struct sum_struct *)malloc(sizeof(*s));
s = new(struct sum_struct);
if (!s) out_of_memory("receive_sums");
read_sum_head(f, s);
s->count = read_int(f);
s->n = read_int(f);
s->remainder = read_int(f);
s->sums = NULL;
if (verbose > 3)
rprintf(FINFO, "count=%ld n=%ld rem=%ld\n",
(long) s->count, (long) s->blength,
(long) s->remainder);
rprintf(FINFO,"count=%ld n=%ld rem=%ld\n",
(long) s->count, (long) s->n, (long) s->remainder);
if (s->count == 0)
if (s->count == 0)
return(s);
s->sums = (struct sum_buf *)malloc(sizeof(s->sums[0])*s->count);
s->sums = new_array(struct sum_buf, s->count);
if (!s->sums) out_of_memory("receive_sums");
for (i = 0; i < (int) s->count; i++) {
for (i=0; i < (int) s->count;i++) {
s->sums[i].sum1 = read_int(f);
read_buf(f, s->sums[i].sum2, s->s2length);
read_buf(f,s->sums[i].sum2,csum_length);
s->sums[i].offset = offset;
s->sums[i].i = i;
@@ -86,13 +74,13 @@ static struct sum_struct *receive_sums(int f)
if (i == (int) s->count-1 && s->remainder != 0) {
s->sums[i].len = s->remainder;
} else {
s->sums[i].len = s->blength;
s->sums[i].len = s->n;
}
offset += s->sums[i].len;
if (verbose > 3)
rprintf(FINFO, "chunk[%d] len=%d offset=%.0f sum1=%08x\n",
i, s->sums[i].len, (double)s->sums[i].offset, s->sums[i].sum1);
rprintf(FINFO,"chunk[%d] len=%d offset=%.0f sum1=%08x\n",
i,s->sums[i].len,(double)s->sums[i].offset,s->sums[i].sum1);
}
s->flength = offset;
@@ -102,17 +90,17 @@ static struct sum_struct *receive_sums(int f)
void send_files(struct file_list *flist, int f_out, int f_in)
{
void send_files(struct file_list *flist,int f_out,int f_in)
{
int fd = -1;
struct sum_struct *s;
struct map_struct *buf = NULL;
STRUCT_STAT st;
char fname[MAXPATHLEN];
char fname[MAXPATHLEN];
int i;
struct file_struct *file;
int phase = 0;
extern struct stats stats;
extern struct stats stats;
struct stats initial_stats;
extern int write_batch; /* dw */
extern int read_batch; /* dw */
@@ -123,26 +111,26 @@ void send_files(struct file_list *flist, int f_out, int f_in)
int done; /* dw */
if (verbose > 2)
rprintf(FINFO, "send_files starting\n");
rprintf(FINFO,"send_files starting\n");
while (1) {
int offset = 0;
int offset=0;
i = read_int(f_in);
if (i == -1) {
if (phase == 0) {
if (phase==0 && remote_version >= 13) {
phase++;
csum_length = SUM_LENGTH;
write_int(f_out, -1);
write_int(f_out,-1);
if (verbose > 2)
rprintf(FINFO, "send_files phase=%d\n", phase);
rprintf(FINFO,"send_files phase=%d\n",phase);
continue;
}
break;
}
if (i < 0 || i >= flist->count) {
rprintf(FERROR, "Invalid file index %d (count=%d)\n",
rprintf(FERROR,"Invalid file index %d (count=%d)\n",
i, flist->count);
exit_cleanup(RERR_PROTOCOL);
}
@@ -154,26 +142,26 @@ void send_files(struct file_list *flist, int f_out, int f_in)
fname[0] = 0;
if (file->basedir) {
strlcpy(fname, file->basedir, MAXPATHLEN);
strlcpy(fname,file->basedir,MAXPATHLEN);
if (strlen(fname) == MAXPATHLEN-1) {
io_error = 1;
rprintf(FERROR, "send_files failed on long-named directory %s\n",
full_fname(fname));
fname);
return;
}
strlcat(fname, "/", MAXPATHLEN);
strlcat(fname,"/",MAXPATHLEN);
offset = strlen(file->basedir)+1;
}
strlcat(fname, f_name(file), MAXPATHLEN);
if (verbose > 2)
rprintf(FINFO, "send_files(%d, %s)\n", i, fname);
if (dry_run) {
if (!am_server && verbose) { /* log transfer */
rprintf(FINFO, "%s\n", fname+offset);
strlcat(fname,f_name(file),MAXPATHLEN);
if (verbose > 2)
rprintf(FINFO,"send_files(%d,%s)\n",i,fname);
if (dry_run) {
if (!am_server) {
log_transfer(file, fname+offset);
}
write_int(f_out, i);
write_int(f_out,i);
continue;
}
@@ -182,130 +170,128 @@ void send_files(struct file_list *flist, int f_out, int f_in)
s = receive_sums(f_in);
if (!s) {
io_error = 1;
rprintf(FERROR, "receive_sums failed\n");
rprintf(FERROR,"receive_sums failed\n");
return;
}
if (write_batch)
write_batch_csum_info(&i, flist->count, s);
write_batch_csum_info(&i,flist->count,s);
if (!read_batch) {
fd = do_open(fname, O_RDONLY, 0);
if (fd == -1) {
io_error = 1;
rprintf(FERROR, "send_files failed to open %s: %s\n",
full_fname(fname), strerror(errno));
rprintf(FERROR,"send_files failed to open %s: %s\n",
fname,strerror(errno));
free_sums(s);
continue;
}
/* map the local file */
if (do_fstat(fd, &st) != 0) {
if (do_fstat(fd,&st) != 0) {
io_error = 1;
rprintf(FERROR, "fstat failed: %s\n", strerror(errno));
rprintf(FERROR,"fstat failed : %s\n",strerror(errno));
free_sums(s);
close(fd);
return;
}
if (st.st_size > 0) {
buf = map_file(fd, st.st_size);
buf = map_file(fd,st.st_size);
} else {
buf = NULL;
}
if (verbose > 2)
rprintf(FINFO, "send_files mapped %s of size %.0f\n",
fname, (double)st.st_size);
write_int(f_out, i);
rprintf(FINFO,"send_files mapped %s of size %.0f\n",
fname,(double)st.st_size);
write_int(f_out,i);
if (write_batch)
write_batch_delta_file((char *)&i, sizeof(i));
write_batch_delta_file((char *)&i,sizeof(i));
write_sum_head(f_out, s);
write_int(f_out,s->count);
write_int(f_out,s->n);
write_int(f_out,s->remainder);
}
if (verbose > 2 && !read_batch)
rprintf(FINFO, "calling match_sums %s\n", fname);
if (!am_server && verbose) { /* log transfer */
rprintf(FINFO, "%s\n", fname+offset);
if (verbose > 2)
if (!read_batch)
rprintf(FINFO,"calling match_sums %s\n",fname);
if (!am_server) {
log_transfer(file, fname+offset);
}
set_compression(fname);
if (read_batch) { /* dw */
/* read checksums originally computed on sender side */
read_batch_csum_info(i, s, &checksums_match);
if (checksums_match) {
read_batch_delta_file( (char *) &j, sizeof(int) );
if (j != i) { /* if flist index entries don't match*/
rprintf(FINFO, "index mismatch in send_files\n");
rprintf(FINFO, "read index = %d flist ndx = %d\n", j, i);
close_batch_delta_file();
close_batch_csums_file();
exit_cleanup(1);
} else {
write_int(f_out, j);
write_sum_head(f_out, s);
done = 0;
while (!done) {
read_batch_delta_file( (char *) &buff_len, sizeof(int) );
write_int(f_out, buff_len);
if (buff_len == 0) {
done = 1;
} else {
if (buff_len > 0) {
read_batch_delta_file(buff, buff_len);
write_buf(f_out, buff, buff_len);
}
}
} /* end while */
read_batch_delta_file( buff, MD4_SUM_LENGTH);
write_buf(f_out, buff, MD4_SUM_LENGTH);
if (read_batch) { /* dw */
/* read checksums originally computed on sender side */
read_batch_csum_info(i, s, &checksums_match);
if (checksums_match) {
read_batch_delta_file( (char *) &j, sizeof(int) );
if (j != i) { /* if flist index entries don't match*/
rprintf(FINFO,"index mismatch in send_files\n");
rprintf(FINFO,"read index = %d flist ndx = %d\n",j,i);
close_batch_delta_file();
close_batch_csums_file();
exit_cleanup(1);
}
else {
write_int(f_out,j);
write_int(f_out,s->count);
write_int(f_out,s->n);
write_int(f_out,s->remainder);
done=0;
while (!done) {
read_batch_delta_file( (char *) &buff_len, sizeof(int) );
write_int(f_out,buff_len);
if (buff_len == 0) {
done = 1;
}
else {
if (buff_len > 0) {
read_batch_delta_file(buff, buff_len);
write_buf(f_out,buff,buff_len);
}
}
} /* end while */
read_batch_delta_file( buff, MD4_SUM_LENGTH);
write_buf(f_out, buff, MD4_SUM_LENGTH);
} /* j=i */
} else { /* not checksum match */
rprintf (FINFO, "readbatch & checksums don't match\n");
rprintf (FINFO, "filename=%s is being skipped\n", fname);
continue;
}
} else {
match_sums(f_out, s, buf, st.st_size);
log_send(file, &initial_stats);
}
} /* j=i */
} else { /* not checksum match */
rprintf (FINFO,"readbatch & checksums don't match\n");
rprintf (FINFO,"filename=%s is being skipped\n",
fname);
continue;
}
} else {
match_sums(f_out,s,buf,st.st_size);
log_send(file, &initial_stats);
}
if (!read_batch) { /* dw */
if (buf) {
j = unmap_file(buf);
if (j) {
io_error = 1;
rprintf(FERROR,
"read errors mapping %s: (%d) %s\n",
full_fname(fname),
j,
strerror(j));
}
}
close(fd);
if (buf) unmap_file(buf);
close(fd);
}
free_sums(s);
if (verbose > 2)
rprintf(FINFO, "sender finished %s\n", fname);
rprintf(FINFO,"sender finished %s\n",fname);
}
if (verbose > 2)
rprintf(FINFO, "send files finished\n");
rprintf(FINFO,"send files finished\n");
match_report();
write_int(f_out, -1);
write_int(f_out,-1);
if (write_batch || read_batch) { /* dw */
close_batch_csums_file();
close_batch_delta_file();
close_batch_csums_file();
close_batch_delta_file();
}
}

84
token.c
View File

@@ -51,7 +51,7 @@ void set_compression(char *fname)
strlower(fname);
for (tok=strtok(dont," ");tok;tok=strtok(NULL," ")) {
if (wildmatch(tok, fname)) {
if (fnmatch(tok, fname, 0) == 0) {
compression_level = 0;
break;
}
@@ -68,7 +68,7 @@ static int simple_recv_token(int f,char **data)
int n;
if (!buf) {
buf = (char *)malloc(CHUNK_SIZE);
buf = new_array(char, CHUNK_SIZE);
if (!buf) out_of_memory("simple_recv_token");
}
@@ -90,8 +90,8 @@ static int simple_recv_token(int f,char **data)
static void simple_send_token(int f,int token,
struct map_struct *buf,OFF_T offset,int n)
{
extern int write_batch;
int hold_int;
extern int write_batch; /* dw */
int hold_int; /* dw */
if (n > 0) {
int l = 0;
@@ -100,8 +100,8 @@ static void simple_send_token(int f,int token,
write_int(f,n1);
write_buf(f,map_ptr(buf,offset+l,n1),n1);
if (write_batch) {
write_batch_delta_file( (char *) &n1, sizeof(int) );
write_batch_delta_file(map_ptr(buf,offset+l,n1),n1);
write_batch_delta_file( (char *) &n1, sizeof(int) );
write_batch_delta_file(map_ptr(buf,offset+l,n1),n1);
}
l += n1;
}
@@ -110,8 +110,8 @@ static void simple_send_token(int f,int token,
if (token != -2) {
write_int(f,-(token+1));
if (write_batch) {
hold_int = -(token+1);
write_batch_delta_file( (char *) &hold_int, sizeof(int) );
hold_int = -(token+1);
write_batch_delta_file( (char *) &hold_int, sizeof(int) );
}
}
}
@@ -127,12 +127,6 @@ static void simple_send_token(int f,int token,
#define MAX_DATA_COUNT 16383 /* fit 14 bit count into 2 bytes with flags */
/* zlib.h says that if we want to be able to compress something in a single
* call, avail_out must be at least 0.1% larger than avail_in plus 12 bytes.
* We'll add in 0.1%+16, just to be safe (and we'll avoid floating point,
* to ensure that this is a compile-time value). */
#define AVAIL_OUT_SIZE(avail_in_size) ((avail_in_size)*1001/1000+16)
/* For coding runs of tokens */
static int last_token = -1;
static int run_start;
@@ -144,14 +138,6 @@ static z_stream tx_strm;
/* Output buffer */
static char *obuf;
/* We want obuf to be able to hold both MAX_DATA_COUNT+2 bytes as well as
* AVAIL_OUT_SIZE(CHUNK_SIZE) bytes, so make sure that it's large enough. */
#if MAX_DATA_COUNT+2 > AVAIL_OUT_SIZE(CHUNK_SIZE)
#define OBUF_SIZE (MAX_DATA_COUNT+2)
#else
#define OBUF_SIZE AVAIL_OUT_SIZE(CHUNK_SIZE)
#endif
/* Send a deflated token */
static void
send_deflated_token(int f, int token,
@@ -159,8 +145,8 @@ send_deflated_token(int f, int token,
{
int n, r;
static int init_done, flush_pending;
extern int write_batch;
char temp_byte;
extern int write_batch; /* dw */
char temp_byte; /* dw */
if (last_token == -1) {
/* initialization */
@@ -174,7 +160,7 @@ send_deflated_token(int f, int token,
rprintf(FERROR, "compression init failed\n");
exit_cleanup(RERR_STREAMIO);
}
if ((obuf = malloc(OBUF_SIZE)) == NULL)
if ((obuf = new_array(char, MAX_DATA_COUNT+2)) == NULL)
out_of_memory("send_deflated_token");
init_done = 1;
} else
@@ -193,26 +179,26 @@ send_deflated_token(int f, int token,
n = last_token - run_start;
if (r >= 0 && r <= 63) {
write_byte(f, (n==0? TOKEN_REL: TOKENRUN_REL) + r);
if (write_batch) {
temp_byte = (char)( (n==0? TOKEN_REL: TOKENRUN_REL) + r);
write_batch_delta_file(&temp_byte,sizeof(char));
if (write_batch) { /* dw */
temp_byte = (char)( (n==0? TOKEN_REL: TOKENRUN_REL) + r);
write_batch_delta_file(&temp_byte,sizeof(char));
}
} else {
write_byte(f, (n==0? TOKEN_LONG: TOKENRUN_LONG));
write_int(f, run_start);
if (write_batch) {
temp_byte = (char)(n==0? TOKEN_LONG: TOKENRUN_LONG);
write_batch_delta_file(&temp_byte,sizeof(temp_byte));
write_batch_delta_file((char *)&run_start,sizeof(run_start));
if (write_batch) { /* dw */
temp_byte = (char)(n==0? TOKEN_LONG: TOKENRUN_LONG);
write_batch_delta_file(&temp_byte,sizeof(temp_byte));
write_batch_delta_file((char *)&run_start,sizeof(run_start));
}
}
if (n != 0) {
write_byte(f, n);
write_byte(f, n >> 8);
if (write_batch) {
write_batch_delta_file((char *)&n,sizeof(char));
temp_byte = (char)(n >> 8);
write_batch_delta_file(&temp_byte,sizeof(temp_byte));
if (write_batch) { /* dw */
write_batch_delta_file((char *)&n,sizeof(char));
temp_byte = (char) n >> 8;
write_batch_delta_file(&temp_byte,sizeof(temp_byte));
}
}
last_run_end = last_token;
@@ -272,8 +258,8 @@ send_deflated_token(int f, int token,
obuf[0] = DEFLATED_DATA + (n >> 8);
obuf[1] = n;
write_buf(f, obuf, n+2);
if (write_batch)
write_batch_delta_file(obuf,n+2);
if (write_batch) /* dw */
write_batch_delta_file(obuf,n+2);
}
}
} while (nb != 0 || tx_strm.avail_out == 0);
@@ -283,9 +269,9 @@ send_deflated_token(int f, int token,
if (token == -1) {
/* end of file - clean up */
write_byte(f, END_FLAG);
if (write_batch) {
temp_byte = END_FLAG;
write_batch_delta_file((char *)&temp_byte,sizeof(temp_byte));
if (write_batch) { /* dw */
temp_byte = END_FLAG;
write_batch_delta_file((char *)&temp_byte,sizeof(temp_byte));
}
} else if (token != -2) {
@@ -294,7 +280,7 @@ send_deflated_token(int f, int token,
tx_strm.next_in = (Bytef *) map_ptr(buf, offset, toklen);
tx_strm.avail_in = toklen;
tx_strm.next_out = (Bytef *) obuf;
tx_strm.avail_out = AVAIL_OUT_SIZE(CHUNK_SIZE);
tx_strm.avail_out = MAX_DATA_COUNT;
r = deflate(&tx_strm, Z_INSERT_ONLY);
if (r != Z_OK || tx_strm.avail_in != 0) {
rprintf(FERROR, "deflate on token returned %d (%d bytes left)\n",
@@ -336,8 +322,8 @@ recv_deflated_token(int f, char **data)
rprintf(FERROR, "inflate init failed\n");
exit_cleanup(RERR_STREAMIO);
}
if ((cbuf = malloc(MAX_DATA_COUNT)) == NULL
|| (dbuf = malloc(AVAIL_OUT_SIZE(CHUNK_SIZE))) == NULL)
if (!(cbuf = new_array(char, MAX_DATA_COUNT))
|| !(dbuf = new_array(char, CHUNK_SIZE)))
out_of_memory("recv_deflated_token");
init_done = 1;
} else {
@@ -366,9 +352,9 @@ recv_deflated_token(int f, char **data)
/* check previous inflated stuff ended correctly */
rx_strm.avail_in = 0;
rx_strm.next_out = (Bytef *)dbuf;
rx_strm.avail_out = AVAIL_OUT_SIZE(CHUNK_SIZE);
rx_strm.avail_out = CHUNK_SIZE;
r = inflate(&rx_strm, Z_SYNC_FLUSH);
n = AVAIL_OUT_SIZE(CHUNK_SIZE) - rx_strm.avail_out;
n = CHUNK_SIZE - rx_strm.avail_out;
/*
* Z_BUF_ERROR just means no progress was
* made, i.e. the decompressor didn't have
@@ -422,9 +408,9 @@ recv_deflated_token(int f, char **data)
case r_inflating:
rx_strm.next_out = (Bytef *)dbuf;
rx_strm.avail_out = AVAIL_OUT_SIZE(CHUNK_SIZE);
rx_strm.avail_out = CHUNK_SIZE;
r = inflate(&rx_strm, Z_NO_FLUSH);
n = AVAIL_OUT_SIZE(CHUNK_SIZE) - rx_strm.avail_out;
n = CHUNK_SIZE - rx_strm.avail_out;
if (r != Z_OK) {
rprintf(FERROR, "inflate returned %d (%d bytes)\n", r, n);
exit_cleanup(RERR_STREAMIO);
@@ -479,7 +465,7 @@ static void see_deflate_token(char *buf, int len)
}
}
rx_strm.next_out = (Bytef *)dbuf;
rx_strm.avail_out = AVAIL_OUT_SIZE(CHUNK_SIZE);
rx_strm.avail_out = CHUNK_SIZE;
r = inflate(&rx_strm, Z_SYNC_FLUSH);
if (r != Z_OK) {
rprintf(FERROR, "inflate (token) returned %d\n", r);

View File

@@ -41,7 +41,7 @@ static struct idlist *gidlist;
static struct idlist *add_list(int id, char *name)
{
struct idlist *list = (struct idlist *)malloc(sizeof(list[0]));
struct idlist *list = new(struct idlist);
if (!list) out_of_memory("add_list");
list->next = NULL;
list->name = strdup(name);
@@ -241,7 +241,7 @@ void recv_uid_list(int f, struct file_list *flist)
id = read_int(f);
while (id != 0) {
int len = read_byte(f);
name = (char *)malloc(len+1);
name = new_array(char, len+1);
if (!name) out_of_memory("recv_uid_list");
read_sbuf(f, name, len);
if (!list) {
@@ -264,7 +264,7 @@ void recv_uid_list(int f, struct file_list *flist)
id = read_int(f);
while (id != 0) {
int len = read_byte(f);
name = (char *)malloc(len+1);
name = new_array(char, len+1);
if (!name) out_of_memory("recv_uid_list");
read_sbuf(f, name, len);
if (!list) {

124
util.c
View File

@@ -345,10 +345,9 @@ int robust_unlink(char *fname)
counter = 1;
} while (((rc = access(path, 0)) == 0) && (counter != start));
if (verbose > 0) {
if (verbose > 0)
rprintf(FINFO,"renaming %s to %s because of text busy\n",
fname, path);
}
fname, path);
/* maybe we should return rename()'s exit status? Nah. */
if (do_rename(fname, path) != 0) {
@@ -459,31 +458,14 @@ int lock_range(int fd, int offset, int len)
return fcntl(fd,F_SETLK,&lock) == 0;
}
static int exclude_server_path(char *arg)
{
char *s;
extern struct exclude_struct **server_exclude_list;
if (server_exclude_list) {
for (s = arg; (s = strchr(s, '/')) != NULL; ) {
*s = '\0';
if (check_exclude(server_exclude_list, arg, 1)) {
/* We must leave arg truncated! */
return 1;
}
*s++ = '/';
}
}
return 0;
}
static void glob_expand_one(char *s, char **argv, int *argc, int maxargs)
{
#if !(defined(HAVE_GLOB) && defined(HAVE_GLOB_H))
if (!*s) s = ".";
s = argv[*argc] = strdup(s);
exclude_server_path(s);
argv[*argc] = strdup(s);
(*argc)++;
return;
#else
extern int sanitize_paths;
glob_t globbuf;
@@ -491,21 +473,20 @@ static void glob_expand_one(char *s, char **argv, int *argc, int maxargs)
if (!*s) s = ".";
s = argv[*argc] = strdup(s);
argv[*argc] = strdup(s);
if (sanitize_paths) {
sanitize_path(s, NULL);
sanitize_path(argv[*argc], NULL);
}
memset(&globbuf, 0, sizeof(globbuf));
if (!exclude_server_path(s))
glob(s, 0, NULL, &globbuf);
glob(argv[*argc], 0, NULL, &globbuf);
if (globbuf.gl_pathc == 0) {
(*argc)++;
globfree(&globbuf);
return;
}
for (i=0; i<(maxargs - (*argc)) && i < (int) globbuf.gl_pathc;i++) {
if (i == 0) free(s);
if (i == 0) free(argv[*argc]);
argv[(*argc) + i] = strdup(globbuf.gl_pathv[i]);
if (!argv[(*argc) + i]) out_of_memory("glob_expand");
}
@@ -514,31 +495,29 @@ static void glob_expand_one(char *s, char **argv, int *argc, int maxargs)
#endif
}
/* This routine is only used in daemon mode. */
void glob_expand(char *base1, char **argv, int *argc, int maxargs)
{
char *s = argv[*argc];
char *p, *q;
char *base = base1;
int base_len = strlen(base);
if (!s || !*s) return;
if (strncmp(s, base, base_len) == 0)
s += base_len;
if (strncmp(s, base, strlen(base)) == 0) {
s += strlen(base);
}
s = strdup(s);
if (!s) out_of_memory("glob_expand");
if (asprintf(&base," %s/", base1) <= 0) out_of_memory("glob_expand");
base_len++;
q = s;
while ((p = strstr(q,base)) && ((*argc) < maxargs)) {
/* split it at this point */
*p = 0;
glob_expand_one(q, argv, argc, maxargs);
q = p + base_len;
q = p+strlen(base);
}
if (*q && (*argc < maxargs)) glob_expand_one(q, argv, argc, maxargs);
@@ -559,13 +538,6 @@ void strlower(char *s)
}
}
void *Realloc(void *p, int size)
{
if (!p) return (void *)malloc(size);
return (void *)realloc(p, size);
}
void clean_fname(char *name)
{
char *p;
@@ -669,7 +641,7 @@ void sanitize_path(char *p, char *reldir)
}
allowdotdot = 0;
if ((*p == '.') && (*(p+1) == '.') &&
((*(p+2) == '/') || (*(p+2) == '\0'))) {
((*(p+2) == '/') || (*(p+2) == '\0'))) {
/* ".." component followed by slash or end */
if ((depth > 0) && (sanp == start)) {
/* allow depth levels of .. at the beginning */
@@ -720,7 +692,7 @@ void sanitize_path(char *p, char *reldir)
}
char curr_dir[MAXPATHLEN];
static char curr_dir[MAXPATHLEN];
/**
* Like chdir() but can be reversed with pop_dir() if @p save is set.
@@ -746,7 +718,7 @@ char *push_dir(char *dir, int save)
if (*dir == '/') {
strlcpy(curr_dir, dir, sizeof(curr_dir));
} else if (dir[0] != '.' || dir[1] != '\0') {
} else {
strlcat(curr_dir,"/", sizeof(curr_dir));
strlcat(curr_dir,dir, sizeof(curr_dir));
}
@@ -774,52 +746,6 @@ int pop_dir(char *dir)
return 0;
}
/**
* Return a quoted string with the full pathname of the indicated filename.
* The string " (in MODNAME)" may also be appended. The returned pointer
* remains valid until the next time full_fname() is called.
**/
char *full_fname(char *fn)
{
extern int module_id;
static char *result = NULL;
char *m1, *m2, *m3;
char *p1, *p2;
if (result)
free(result);
if (*fn == '/')
p1 = p2 = "";
else {
p1 = curr_dir;
p2 = "/";
}
if (module_id >= 0) {
m1 = " (in ";
m2 = lp_name(module_id);
m3 = ")";
if (*p1) {
if (!lp_use_chroot(module_id)) {
char *p = lp_path(module_id);
if (*p != '/' || p[1])
p1 += strlen(p);
}
if (!*p1)
p2++;
else
p1++;
}
else
fn++;
} else
m1 = m2 = m3 = "";
asprintf(&result, "\"%s%s%s\"%s%s%s", p1, p2, fn, m1, m2, m3);
return result;
}
/** We need to supply our own strcmp function for file list comparisons
to ensure that signed/unsigned usage is consistent between machines. */
int u_strcmp(const char *cs1, const char *cs2)
@@ -1008,3 +934,23 @@ int _Insure_trap_error(int a1, int a2, int a3, int a4, int a5, int a6)
return ret;
}
#endif
#define MALLOC_MAX 0x40000000
void *_new_array(unsigned int size, unsigned long num)
{
if (num >= MALLOC_MAX/size)
return NULL;
return malloc(size * num);
}
void *_realloc_array(void *ptr, unsigned int size, unsigned long num)
{
if (num >= MALLOC_MAX/size)
return NULL;
/* No realloc should need this, but just in case... */
if (!ptr)
return malloc(size * num);
return realloc(ptr, size * num);
}