mirror of
https://github.com/RsyncProject/rsync.git
synced 2026-04-04 14:34:25 -04:00
Buffer management fix.
Prepare for 2.5.7 release.
This commit is contained in:
120
NEWS
120
NEWS
@@ -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
21
batch.c
@@ -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));
|
||||
|
||||
32
checksum.c
32
checksum.c
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
11
configure.in
11
configure.in
@@ -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
379
exclude.c
@@ -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"));
|
||||
}
|
||||
|
||||
37
fileio.c
37
fileio.c
@@ -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
311
flist.c
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
4
hlink.c
4
hlink.c
@@ -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
261
io.c
@@ -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);
|
||||
|
||||
86
loadparm.c
86
loadparm.c
@@ -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
28
log.c
@@ -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
156
match.c
@@ -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;
|
||||
|
||||
8
params.c
8
params.c
@@ -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);
|
||||
|
||||
209
receiver.c
209
receiver.c
@@ -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
78
rsync.c
@@ -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
129
rsync.h
@@ -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
252
sender.c
@@ -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
84
token.c
@@ -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);
|
||||
|
||||
@@ -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
124
util.c
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user