/*
- 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.
-*/
-
-/** @file flist.c
- * Generate and receive file lists
+ * Generate and receive file lists.
*
- * @sa http://lists.samba.org/pipermail/rsync/2000-June/002351.html
+ * Copyright (C) 1996 Andrew Tridgell
+ * Copyright (C) 1996 Paul Mackerras
+ * Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
+ * Copyright (C) 2002, 2003, 2004, 2005, 2006 Wayne Davison
*
- **/
+ * 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.,
+ * 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+ */
#include "rsync.h"
extern int preserve_gid;
extern int relative_paths;
extern int implied_dirs;
+extern int ignore_perishable;
+extern int non_perishable_cnt;
extern int prune_empty_dirs;
extern int copy_links;
extern int copy_unsafe_links;
static void start_filelist_progress(char *kind)
{
- rprintf(FINFO, "%s ... ", kind);
+ rprintf(FCLIENT, "%s ... ", kind);
if (verbose > 1 || do_progress)
- rprintf(FINFO, "\n");
+ rprintf(FCLIENT, "\n");
rflush(FINFO);
}
static void emit_filelist_progress(int count)
{
- rprintf(FINFO, " %d files...\r", count);
+ rprintf(FCLIENT, " %d files...\r", count);
}
static void maybe_emit_filelist_progress(int count)
}
}
-/**
- * Stat either a symlink or its referent, depending on the settings of
- * copy_links, copy_unsafe_links, etc.
- *
- * @retval -1 on error
+/* Stat either a symlink or its referent, depending on the settings of
+ * copy_links, copy_unsafe_links, etc. Returns -1 on error, 0 on success.
*
- * @retval 0 for success
+ * If path is the name of a symlink, then the linkbuf buffer (which must hold
+ * MAXPATHLEN chars) will be set to the symlink's target string.
*
- * @post If @p path is a symlink, then @p linkbuf (of size @c
- * MAXPATHLEN) contains the symlink target.
- *
- * @post @p buffer contains information about the link or the
- * referrent as appropriate, if they exist.
- **/
-static int readlink_stat(const char *path, STRUCT_STAT *buffer, char *linkbuf)
+ * The stat structure pointed to by stp will contain information about the
+ * link or the referent as appropriate, if they exist. */
+static int readlink_stat(const char *path, STRUCT_STAT *stp, char *linkbuf)
{
#ifdef SUPPORT_LINKS
- if (copy_links)
- return do_stat(path, buffer);
- if (link_stat(path, buffer, copy_dirlinks) < 0)
+ if (link_stat(path, stp, copy_dirlinks) < 0)
return -1;
- if (S_ISLNK(buffer->st_mode)) {
- int l = readlink((char *)path, linkbuf, MAXPATHLEN - 1);
- if (l == -1)
+ if (S_ISLNK(stp->st_mode)) {
+ int llen = readlink(path, linkbuf, MAXPATHLEN - 1);
+ if (llen < 0)
return -1;
- linkbuf[l] = 0;
+ linkbuf[llen] = '\0';
if (copy_unsafe_links && unsafe_symlink(linkbuf, path)) {
if (verbose > 1) {
rprintf(FINFO,"copying unsafe symlink \"%s\" -> \"%s\"\n",
path, linkbuf);
}
- return do_stat(path, buffer);
+ return do_stat(path, stp);
}
}
return 0;
#else
- return do_stat(path, buffer);
+ return do_stat(path, stp);
#endif
}
-int link_stat(const char *path, STRUCT_STAT *buffer, int follow_dirlinks)
+int link_stat(const char *path, STRUCT_STAT *stp, int follow_dirlinks)
{
#ifdef SUPPORT_LINKS
if (copy_links)
- return do_stat(path, buffer);
- if (do_lstat(path, buffer) < 0)
+ return do_stat(path, stp);
+ if (do_lstat(path, stp) < 0)
return -1;
- if (follow_dirlinks && S_ISLNK(buffer->st_mode)) {
+ if (follow_dirlinks && S_ISLNK(stp->st_mode)) {
STRUCT_STAT st;
if (do_stat(path, &st) == 0 && S_ISDIR(st.st_mode))
- *buffer = st;
+ *stp = st;
}
return 0;
#else
- return do_stat(path, buffer);
+ return do_stat(path, stp);
#endif
}
static int to_wire_mode(mode_t mode)
{
#ifdef SUPPORT_LINKS
- if (S_ISLNK(mode) && (_S_IFLNK != 0120000))
+#if _S_IFLNK != 0120000
+ if (S_ISLNK(mode))
return (mode & ~(_S_IFMT)) | 0120000;
#endif
- return (int)mode;
+#endif
+ return mode;
}
static mode_t from_wire_mode(int mode)
{
- if ((mode & (_S_IFMT)) == 0120000 && (_S_IFLNK != 0120000))
+#if _S_IFLNK != 0120000
+ if ((mode & (_S_IFMT)) == 0120000)
return (mode & ~(_S_IFMT)) | _S_IFLNK;
- return (mode_t)mode;
+#endif
+ return mode;
}
static void send_directory(int f, struct file_list *flist,
char *fbuf, int len);
-static char *flist_dir;
+static const char *flist_dir;
static int flist_dir_len;
flist->malloced);
if (verbose >= 2 && flist->malloced != FLIST_START) {
- rprintf(FINFO, "[%s] expand file_list to %.0f bytes, did%s move\n",
+ rprintf(FCLIENT, "[%s] expand file_list to %.0f bytes, did%s move\n",
who_am_i(),
(double)sizeof flist->files[0] * flist->malloced,
(new_ptr == flist->files) ? " not" : "");
if (!file) {
write_byte(f, 0);
modtime = 0, mode = 0;
- dev = 0, rdev = makedev(0, 0);
+ dev = 0, rdev = MAKEDEV(0, 0);
rdev_major = 0;
uid = 0, gid = 0;
*lastname = '\0';
flags |= XMIT_RDEV_MINOR_IS_SMALL;
}
} else if (protocol_version < 28)
- rdev = makedev(0, 0);
+ rdev = MAKEDEV(0, 0);
if (file->uid == uid)
flags |= XMIT_SAME_UID;
else
flags |= XMIT_TOP_DIR;
if ((flags & 0xFF00) || !flags) {
flags |= XMIT_EXTENDED_FLAGS;
- write_byte(f, flags);
- write_byte(f, flags >> 8);
+ write_shortint(f, flags);
} else
write_byte(f, flags);
} else {
#endif
#ifdef SUPPORT_HARD_LINKS
- if (flags & XMIT_HAS_IDEV_DATA) {
+ if (file->link_u.idev) {
if (protocol_version < 26) {
/* 32-bit dev_t and ino_t */
- write_int(f, dev);
- write_int(f, file->F_INODE);
+ write_int(f, (int32)dev);
+ write_int(f, (int32)file->F_INODE);
} else {
/* 64-bit dev_t and ino_t */
if (!(flags & XMIT_SAME_DEV))
#endif
if (always_checksum && (S_ISREG(mode) || protocol_version < 28)) {
- char *sum;
+ const char *sum;
if (S_ISREG(mode))
sum = file->u.sum;
else {
if (!flist) {
modtime = 0, mode = 0;
- dev = 0, rdev = makedev(0, 0);
+ dev = 0, rdev = MAKEDEV(0, 0);
rdev_major = 0;
uid = 0, gid = 0;
*lastname = '\0';
clean_fname(thisname, 0);
if (sanitize_paths)
- sanitize_path(thisname, thisname, "", 0);
+ sanitize_path(thisname, thisname, "", 0, NULL);
if ((basename = strrchr(thisname, '/')) != NULL) {
dirname_len = ++basename - thisname; /* counts future '\0' */
rdev_minor = read_byte(f);
else
rdev_minor = read_int(f);
- rdev = makedev(rdev_major, rdev_minor);
+ rdev = MAKEDEV(rdev_major, rdev_minor);
}
} else if (protocol_version < 28)
- rdev = makedev(0, 0);
+ rdev = MAKEDEV(0, 0);
#ifdef SUPPORT_LINKS
if (preserve_links && S_ISLNK(mode)) {
file->u.link = bp;
read_sbuf(f, bp, linkname_len - 1);
if (sanitize_paths)
- sanitize_path(bp, bp, "", lastdir_depth);
+ sanitize_path(bp, bp, "", lastdir_depth, NULL);
bp += linkname_len;
}
#endif
* 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 file_list *flist,
+struct file_struct *make_file(const char *fname, struct file_list *flist,
STRUCT_STAT *stp, unsigned short flags,
int filter_level)
{
}
clean_fname(thisname, 0);
if (sanitize_paths)
- sanitize_path(thisname, thisname, "", 0);
+ sanitize_path(thisname, thisname, "", 0, NULL);
memset(sum, 0, SUM_LENGTH);
- if (stp && S_ISDIR(stp->st_mode))
+ if (stp && S_ISDIR(stp->st_mode)) {
st = *stp; /* Needed for "symlink/." with --relative. */
- else if (readlink_stat(thisname, &st, linkname) != 0) {
+ *linkname = '\0'; /* make IBM code checker happy */
+ } else if (readlink_stat(thisname, &st, linkname) != 0) {
int save_errno = errno;
/* See if file is excluded before reporting an error. */
if (filter_level != NO_FILTERS
- && is_excluded(thisname, 0, filter_level))
+ && (is_excluded(thisname, 0, filter_level)
+ || is_excluded(thisname, 1, filter_level))) {
+ if (ignore_perishable && save_errno != ENOENT)
+ non_perishable_cnt++;
return NULL;
+ }
if (save_errno == ENOENT) {
#ifdef SUPPORT_LINKS
/* Avoid "vanished" error if symlink points nowhere. */
return NULL;
}
- /* We only care about directories because we need to avoid recursing
+ /* -x only affects directories because we need to avoid recursing
* into a mount-point directory, not to avoid copying a symlinked
* file if -L (or similar) was specified. */
if (one_file_system && st.st_dev != filesystem_dev
flags |= FLAG_MOUNT_POINT;
}
- if (is_excluded(thisname, S_ISDIR(st.st_mode) != 0, filter_level))
+ if (is_excluded(thisname, S_ISDIR(st.st_mode) != 0, filter_level)) {
+ if (ignore_perishable)
+ non_perishable_cnt++;
return NULL;
+ }
if (lp_ignore_nonreadable(module_id)) {
#ifdef SUPPORT_LINKS
? MD4_SUM_LENGTH : 0;
alloc_len = file_struct_len + dirname_len + basename_len
- + linkname_len + sum_len;
+ + linkname_len + sum_len;
if (flist)
bp = pool_alloc(flist->file_pool, alloc_len, "make_file");
else {
int64 start_write;
int use_ff_fd = 0;
+ rprintf(FLOG, "building file list\n");
if (show_filelist_p())
start_filelist_progress("building file list");
io_start_buffering_out();
if (filesfrom_fd >= 0) {
- if (argv[0] && !push_dir(argv[0])) {
+ if (argv[0] && !push_dir(argv[0], 0)) {
rsyserr(FERROR, errno, "push_dir %s failed",
full_fname(argv[0]));
exit_cleanup(RERR_FILESELECT);
if (use_ff_fd) {
if (read_filesfrom_line(filesfrom_fd, fbuf) == 0)
break;
- sanitize_path(fbuf, fbuf, "", 0);
+ sanitize_path(fbuf, fbuf, "", 0, NULL);
} else {
if (argc-- == 0)
break;
strlcpy(fbuf, *argv++, MAXPATHLEN);
if (sanitize_paths)
- sanitize_path(fbuf, fbuf, "", 0);
+ sanitize_path(fbuf, fbuf, "", 0, NULL);
}
len = strlen(fbuf);
} else
break;
}
+ if (len == 1 && fn[0] == '/')
+ fn[len++] = '.';
fn[len] = '\0';
/* Reject a ".." dir in the active part of the path. */
for (p = fn; (p = strstr(p, "..")) != NULL; p += 2) {
}
if (dir && *dir) {
- static char *lastdir;
+ static const char *lastdir;
static int lastdir_len;
strlcpy(olddir, curr_dir, sizeof olddir);
- if (!push_dir(dir)) {
+ if (!push_dir(dir, 0)) {
io_error |= IOERR_GENERAL;
rsyserr(FERROR, errno, "push_dir %s failed",
full_fname(dir));
unsigned short flags;
int64 start_read;
+ rprintf(FLOG, "receiving file list\n");
if (show_filelist_p())
start_filelist_progress("receiving file list");
if (mid_up > high) {
/* If there's nothing left above us, set high to
* a non-empty entry below us and continue. */
- high = mid - flist->files[mid]->length;
+ high = mid - (int)flist->files[mid]->length;
if (!flist->files[high]->basename) {
do {
- high -= flist->files[high]->length;
+ high -= (int)flist->files[high]->length;
} while (!flist->files[high]->basename);
flist->files[mid]->length = mid - high;
}
memset(flist, 0, sizeof (struct file_list));
- if (!(flist->file_pool = pool_create(FILE_EXTENT, 0,
- out_of_memory, POOL_INTERN)))
+ if (!(flist->file_pool = pool_create(FILE_EXTENT, 0, out_of_memory, POOL_INTERN)))
out_of_memory(msg);
#ifdef SUPPORT_HARD_LINKS
for (i = 0; i < flist->count; i++) {
file = flist->files[i];
if ((am_root || am_sender) && preserve_uid)
- sprintf(uidbuf, " uid=%ld", (long)file->uid);
+ snprintf(uidbuf, sizeof uidbuf, " uid=%ld", (long)file->uid);
else
*uidbuf = '\0';
if (preserve_gid && file->gid != GID_NONE)
- sprintf(gidbuf, " gid=%ld", (long)file->gid);
+ snprintf(gidbuf, sizeof gidbuf, " gid=%ld", (long)file->gid);
else
*gidbuf = '\0';
if (!am_sender)
- sprintf(depthbuf, "%d", file->dir.depth);
+ snprintf(depthbuf, sizeof depthbuf, "%d", file->dir.depth);
rprintf(FINFO, "[%s] i=%d %s %s%s%s%s mode=0%o len=%.0f%s%s flags=%x\n",
who, i, am_sender ? NS(file->dir.root) : depthbuf,
file->dirname ? file->dirname : "",
c1 = (uchar*)"";
} else
state1 = s_BASE;
- } else if (!*c1) {
- type1 = t_path;
- state1 = s_SLASH;
- c1 = (uchar*)"/";
} else {
type1 = t_path;
state1 = s_DIR;
c2 = (uchar*)"";
} else
state2 = s_BASE;
- } else if (!*c2) {
- type2 = t_path;
- state2 = s_SLASH;
- c2 = (uchar*)"/";
} else {
type2 = t_path;
state2 = s_DIR;
if (type1 != type2)
return type1 == t_PATH ? 1 : -1;
- while (1) {
- if ((dif = (int)*c1++ - (int)*c2++) != 0)
- break;
+ do {
if (!*c1) {
switch (state1) {
case s_DIR:
if (type1 != type2)
return type1 == t_PATH ? 1 : -1;
}
- }
+ } while ((dif = (int)*c1++ - (int)*c2++) == 0);
return dif;
}
int len = strlen(f->dirname);
memcpy(fbuf, f->dirname, len);
fbuf[len] = '/';
- strcpy(fbuf + len + 1, f->basename);
+ strlcpy(fbuf + len + 1, f->basename, MAXPATHLEN - (len + 1));
} else
- strcpy(fbuf, f->basename);
+ strlcpy(fbuf, f->basename, MAXPATHLEN);
return fbuf;
}