diff options
author | Martin Pool <mbp@samba.org> | 2003-12-04 04:23:29 +0000 |
---|---|---|
committer | Martin Pool <mbp@samba.org> | 2003-12-04 04:23:29 +0000 |
commit | 9fb21d28828123e8bab3e32f20a0e794e830f7d5 (patch) | |
tree | 62b9a56279a8c728c0fa152c6cbf677a5b1eccb9 | |
parent | b11b50bcd026a0a052bdfab7b96c97045b658d86 (diff) | |
download | rsync-9fb21d28828123e8bab3e32f20a0e794e830f7d5.tar.gz |
Buffer management fix.
Prepare for 2.5.7 release.
-rw-r--r-- | NEWS | 120 | ||||
-rw-r--r-- | batch.c | 21 | ||||
-rw-r--r-- | checksum.c | 32 | ||||
-rw-r--r-- | configure.in | 11 | ||||
-rw-r--r-- | exclude.c | 361 | ||||
-rw-r--r-- | fileio.c | 37 | ||||
-rw-r--r-- | flist.c | 311 | ||||
-rw-r--r-- | hlink.c | 4 | ||||
-rw-r--r-- | io.c | 261 | ||||
-rw-r--r-- | loadparm.c | 86 | ||||
-rw-r--r-- | log.c | 28 | ||||
-rw-r--r-- | match.c | 156 | ||||
-rw-r--r-- | params.c | 8 | ||||
-rw-r--r-- | receiver.c | 209 | ||||
-rw-r--r-- | rsync.c | 78 | ||||
-rw-r--r-- | rsync.h | 129 | ||||
-rw-r--r-- | sender.c | 254 | ||||
-rw-r--r-- | token.c | 84 | ||||
-rw-r--r-- | uidlist.c | 6 | ||||
-rw-r--r-- | util.c | 124 |
20 files changed, 882 insertions, 1438 deletions
@@ -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: - - * 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. + SECURITY: - * 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) @@ -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)); @@ -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); } diff --git a/configure.in b/configure.in index 68dac5a0..de1abd34 100644 --- a/configure.in +++ b/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]) @@ -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; + + 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; + } + } + } - 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 (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; - - if (*pattern == '!' && !pattern[1]) { - free_exclude_list(listp); - return; + int len=0; + if (list && *list) + for (; (*list)[len]; len++) ; + + 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); +} -void add_exclude_file(struct exclude_struct ***listp, const char *fname, - int fatal, int include) +struct exclude_struct **make_exclude_list(const char *fname, + struct exclude_struct **list1, + int fatal, int include) { - int fd; + struct exclude_struct **list=list1; + FILE *f; char line[MAXPATHLEN]; - char *eob = line + MAXPATHLEN - 1; - extern int eol_nulls; - if (!fname || !*fname) - return; - - if (*fname != '-' || fname[1]) - fd = open(fname, O_RDONLY|O_BINARY); - else - fd = 0; - if (fd < 0) { + 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); + "failed to open %s file %s", + include ? "include" : "exclude", + fname); exit_cleanup(RERR_FILEIO); } - return; + return list; } - 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 != '#') { + 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(listp, line, include); + 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); } - if (cnt <= 0) - break; } - close(fd); + fclose(f); + return list; +} + + +void add_exclude_file(const char *fname, int fatal, int include) +{ + if (!fname || !*fname) return; + + 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")); } @@ -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; } @@ -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; } @@ -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++) @@ -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); @@ -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); @@ -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); +} @@ -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; @@ -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); @@ -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); - close(fd1); - continue; - } - 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); - fd1 = -1; - buf = NULL; + continue; } 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); @@ -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 { @@ -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); @@ -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); - - } /* 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 */ + /* 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); + } 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(); } } @@ -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) { @@ -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); +} |