mirror of
https://github.com/RsyncProject/rsync.git
synced 2026-05-24 23:05:52 -04:00
Compare commits
60 Commits
v2.5.2pre1
...
v2.5.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cd6058f3d4 | ||
|
|
9be3ba223c | ||
|
|
a261989cda | ||
|
|
7b5c3eb05e | ||
|
|
0feec72eee | ||
|
|
be8bd99aa4 | ||
|
|
355b8bcd73 | ||
|
|
d58e4c273c | ||
|
|
a217ad3095 | ||
|
|
3d6feada8a | ||
|
|
5f78da2025 | ||
|
|
a05e4fa512 | ||
|
|
2119a4c462 | ||
|
|
1d5a1da9f8 | ||
|
|
2e7d19945c | ||
|
|
5d2c5c4c73 | ||
|
|
8694312695 | ||
|
|
d9d6bc5278 | ||
|
|
ebed4c3af0 | ||
|
|
172875cf15 | ||
|
|
4d26e9e4f4 | ||
|
|
8f4455f296 | ||
|
|
2e1d43deb2 | ||
|
|
6780f72000 | ||
|
|
39e01d2d4b | ||
|
|
f75502950b | ||
|
|
974f27e7e9 | ||
|
|
af32f69eb0 | ||
|
|
0cd2f40764 | ||
|
|
0d95824995 | ||
|
|
bbc09ffba9 | ||
|
|
a4677968cf | ||
|
|
03b1cddc31 | ||
|
|
9c2dd04993 | ||
|
|
a84a93fafe | ||
|
|
5fdcc397b1 | ||
|
|
5664871e5f | ||
|
|
55d9e0fada | ||
|
|
929e3011c6 | ||
|
|
07d70ff560 | ||
|
|
58c2960960 | ||
|
|
00d943d513 | ||
|
|
71c780da06 | ||
|
|
3b18cba889 | ||
|
|
2974e20550 | ||
|
|
430d841a2c | ||
|
|
31ec50d7da | ||
|
|
5ad0e46f08 | ||
|
|
1b5814e338 | ||
|
|
255810c0d6 | ||
|
|
5d2640376e | ||
|
|
d02984bbb7 | ||
|
|
0f9555207a | ||
|
|
885448d74c | ||
|
|
b14545b3ff | ||
|
|
9a5a86734f | ||
|
|
d1d1505045 | ||
|
|
144ce1dc21 | ||
|
|
aa126974ba | ||
|
|
707de53457 |
@@ -1,14 +1,18 @@
|
||||
testtmp.*
|
||||
ID
|
||||
Makefile
|
||||
config.cache
|
||||
config.h
|
||||
config.log
|
||||
config.status
|
||||
gmon.out
|
||||
rsync
|
||||
shconfig
|
||||
testdir
|
||||
tests-dont-exist
|
||||
testtmp
|
||||
testtmp.*
|
||||
tls
|
||||
zlib/dummy
|
||||
confdefs.h
|
||||
conftest.c
|
||||
conftest.log
|
||||
|
||||
@@ -29,7 +29,8 @@ ZLIBOBJ=zlib/deflate.o zlib/infblock.o zlib/infcodes.o zlib/inffast.o \
|
||||
zlib/inflate.o zlib/inftrees.o zlib/infutil.o zlib/trees.o \
|
||||
zlib/zutil.o zlib/adler32.o
|
||||
OBJS1=rsync.o generator.o receiver.o cleanup.o sender.o exclude.o util.o main.o checksum.o match.o syscall.o log.o backup.o
|
||||
OBJS2=options.o flist.o io.o compat.o hlink.o token.o uidlist.o socket.o fileio.o batch.o
|
||||
OBJS2=options.o flist.o io.o compat.o hlink.o token.o uidlist.o socket.o fileio.o batch.o \
|
||||
clientname.o
|
||||
DAEMON_OBJ = params.o loadparm.o clientserver.o access.o connection.o authenticate.o
|
||||
popt_OBJS=popt/findme.o popt/popt.o popt/poptconfig.o \
|
||||
popt/popthelp.o popt/poptparse.o
|
||||
|
||||
12
NEWS
12
NEWS
@@ -1,4 +1,4 @@
|
||||
rsync 2.5.2 (???)
|
||||
rsync 2.5.2 (26 Jan 2002)
|
||||
|
||||
SECURITY FIXES:
|
||||
|
||||
@@ -15,8 +15,15 @@ rsync 2.5.2 (???)
|
||||
* Better handling of hardlinks and devices on platforms with
|
||||
64-bit dev_t or ino_t.
|
||||
|
||||
* Name resolution on machines supporting IPv6 is improved.
|
||||
|
||||
* Fix for device nodes. (dann frazier) (Debian #129135)
|
||||
|
||||
ENHANCEMENTS:
|
||||
|
||||
* With -v, rsync now shows the command used to initiate an ssh/rsh
|
||||
connection.
|
||||
|
||||
* --statistics now shows memory heap usage on platforms that
|
||||
support mallinfo().
|
||||
|
||||
@@ -27,3 +34,6 @@ rsync 2.5.2 (???)
|
||||
|
||||
* Improvements to batch mode support. This is still experimental
|
||||
but testing would be welcome. (Jos Backus)
|
||||
|
||||
* New --ignore-existing option, patch previously distributed with
|
||||
Vipul's Razor. (Debian #124286)
|
||||
|
||||
16
TODO
16
TODO
@@ -32,6 +32,16 @@ use chroot
|
||||
for people who want to generate the file list using a find(1)
|
||||
command or a script.
|
||||
|
||||
File list structure in memory
|
||||
|
||||
Rather than one big array, perhaps have a tree in memory mirroring
|
||||
the directory tree.
|
||||
|
||||
This might make sorting much faster! (I'm not sure it's a big CPU
|
||||
problem, mind you.)
|
||||
|
||||
It might also reduce memory use in storing repeated directory names
|
||||
-- again I'm not sure this is a problem.
|
||||
|
||||
Performance
|
||||
|
||||
@@ -94,9 +104,6 @@ Memory accounting
|
||||
not sure this makes sense with modern mallocs. At any rate it will
|
||||
make us allocate a huge amount of memory for large file lists.
|
||||
|
||||
We can try using the GNU/SVID/XPG mallinfo() function to get some
|
||||
heap statistics.
|
||||
|
||||
|
||||
Hard-link handling
|
||||
|
||||
@@ -224,6 +231,9 @@ logging
|
||||
monitor progress in a log file can do so more easily. See
|
||||
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=48108
|
||||
|
||||
At the connections that just get a list of modules are not logged,
|
||||
but they should be.
|
||||
|
||||
rsyncd over ssh
|
||||
|
||||
There are already some patches to do this.
|
||||
|
||||
@@ -105,8 +105,8 @@ static int get_secret(int module, char *user, char *secret, int len)
|
||||
|
||||
while (!found) {
|
||||
int i = 0;
|
||||
memset(line, 0, sizeof(line));
|
||||
while (i<(sizeof(line)-1)) {
|
||||
memset(line, 0, sizeof line);
|
||||
while ((size_t) i < (sizeof(line)-1)) {
|
||||
if (read(fd, &line[i], 1) != 1) {
|
||||
memset(line, 0, sizeof(line));
|
||||
close(fd);
|
||||
|
||||
17
batch.c
17
batch.c
@@ -354,7 +354,7 @@ void read_batch_flist_info(struct file_struct **fptr)
|
||||
}
|
||||
}
|
||||
|
||||
void write_batch_csums_file(char *buff, int bytes_to_write)
|
||||
void write_batch_csums_file(void *buff, int bytes_to_write)
|
||||
{
|
||||
|
||||
static int fdb_open = 1;
|
||||
@@ -395,7 +395,7 @@ void close_batch_csums_file()
|
||||
void write_batch_csum_info(int *flist_entry, int flist_count,
|
||||
struct sum_struct *s)
|
||||
{
|
||||
int i;
|
||||
size_t i;
|
||||
unsigned int int_zero = 0;
|
||||
extern int csum_length;
|
||||
|
||||
@@ -403,13 +403,16 @@ void write_batch_csum_info(int *flist_entry, int flist_count,
|
||||
|
||||
/* Write csum info to batch file */
|
||||
|
||||
write_batch_csums_file((char *) flist_entry, sizeof(int));
|
||||
write_batch_csums_file((char *) (s ? &s->count : &int_zero),
|
||||
sizeof(int));
|
||||
/* FIXME: This will break if s->count is ever not exactly an int. */
|
||||
write_batch_csums_file(flist_entry, sizeof(int));
|
||||
if (s)
|
||||
write_batch_csums_file(&s->count, sizeof(int));
|
||||
else
|
||||
write_batch_csums_file(&int_zero, sizeof (int));
|
||||
|
||||
if (s) {
|
||||
for (i = 0; i < s->count; i++) {
|
||||
write_batch_csums_file((char *) &s->sums[i].sum1,
|
||||
sizeof(uint32));
|
||||
write_batch_csums_file(&s->sums[i].sum1, sizeof(uint32));
|
||||
if ((*flist_entry == flist_count - 1)
|
||||
&& (i == s->count - 1)) {
|
||||
fdb_close = 1;
|
||||
|
||||
282
clientname.c
Normal file
282
clientname.c
Normal file
@@ -0,0 +1,282 @@
|
||||
/* -*- c-file-style: "linux" -*-
|
||||
|
||||
rsync -- fast file replication program
|
||||
|
||||
Copyright (C) 1992-2001 by Andrew Tridgell <tridge@samba.org>
|
||||
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 clientname.c
|
||||
*
|
||||
* Functions for looking up the remote name or addr of a socket.
|
||||
*
|
||||
* This file is now converted to use the new-style getaddrinfo()
|
||||
* interface, which supports IPv6 but is also supported on recent
|
||||
* IPv4-only machines. On systems that don't have that interface, we
|
||||
* emulate it using the KAME implementation.
|
||||
**/
|
||||
|
||||
#include "rsync.h"
|
||||
|
||||
static const char default_name[] = "UNKNOWN";
|
||||
|
||||
|
||||
/**
|
||||
* Return the IP addr of the client as a string
|
||||
**/
|
||||
char *client_addr(int fd)
|
||||
{
|
||||
struct sockaddr_storage ss;
|
||||
socklen_t length = sizeof ss;
|
||||
static char addr_buf[100];
|
||||
static int initialised;
|
||||
|
||||
if (initialised) return addr_buf;
|
||||
|
||||
initialised = 1;
|
||||
|
||||
client_sockaddr(fd, &ss, &length);
|
||||
|
||||
getnameinfo((struct sockaddr *)&ss, length,
|
||||
addr_buf, sizeof(addr_buf), NULL, 0, NI_NUMERICHOST);
|
||||
|
||||
return addr_buf;
|
||||
}
|
||||
|
||||
|
||||
static int get_sockaddr_family(const struct sockaddr_storage *ss)
|
||||
{
|
||||
return ((struct sockaddr *) ss)->sa_family;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the DNS name of the client.
|
||||
*
|
||||
* The name is statically cached so that repeated lookups are quick,
|
||||
* so there is a limit of one lookup per customer.
|
||||
*
|
||||
* If anything goes wrong, including the name->addr->name check, then
|
||||
* we just use "UNKNOWN", so you can use that value in hosts allow
|
||||
* lines.
|
||||
**/
|
||||
char *client_name(int fd)
|
||||
{
|
||||
struct sockaddr_storage ss;
|
||||
socklen_t ss_len = sizeof ss;
|
||||
static char name_buf[100];
|
||||
static char port_buf[100];
|
||||
static int initialised;
|
||||
|
||||
if (initialised) return name_buf;
|
||||
|
||||
strcpy(name_buf, default_name);
|
||||
initialised = 1;
|
||||
|
||||
client_sockaddr(fd, &ss, &ss_len);
|
||||
|
||||
if (!lookup_name(fd, &ss, ss_len, name_buf, sizeof name_buf, port_buf, sizeof port_buf))
|
||||
check_name(fd, &ss, name_buf, port_buf);
|
||||
|
||||
return name_buf;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get the sockaddr for the client.
|
||||
*
|
||||
* If it comes in as an ipv4 address mapped into IPv6 format then we
|
||||
* convert it back to a regular IPv4.
|
||||
**/
|
||||
void client_sockaddr(int fd,
|
||||
struct sockaddr_storage *ss,
|
||||
socklen_t *ss_len)
|
||||
{
|
||||
if (getpeername(fd, (struct sockaddr *) ss, ss_len)) {
|
||||
/* FIXME: Can we really not continue? */
|
||||
rprintf(FERROR, RSYNC_NAME ": getpeername on fd%d failed: %s\n",
|
||||
fd, strerror(errno));
|
||||
exit_cleanup(RERR_SOCKETIO);
|
||||
}
|
||||
|
||||
#ifdef INET6
|
||||
if (get_sockaddr_family(ss) == AF_INET6 &&
|
||||
IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)ss)->sin6_addr)) {
|
||||
/* OK, so ss is in the IPv6 family, but it is really
|
||||
* an IPv4 address: something like
|
||||
* "::ffff:10.130.1.2". If we use it as-is, then the
|
||||
* reverse lookup might fail or perhaps something else
|
||||
* bad might happen. So instead we convert it to an
|
||||
* equivalent address in the IPv4 address family. */
|
||||
struct sockaddr_in6 sin6;
|
||||
struct sockaddr_in *sin;
|
||||
|
||||
memcpy(&sin6, ss, sizeof(sin6));
|
||||
sin = (struct sockaddr_in *)ss;
|
||||
memset(sin, 0, sizeof(*sin));
|
||||
sin->sin_family = AF_INET;
|
||||
*ss_len = sizeof(struct sockaddr_in);
|
||||
#ifdef HAVE_SOCKADDR_LEN
|
||||
sin->sin_len = *ss_len;
|
||||
#endif
|
||||
sin->sin_port = sin6.sin6_port;
|
||||
|
||||
/* There is a macro to extract the mapped part
|
||||
* (IN6_V4MAPPED_TO_SINADDR ?), but it does not seem
|
||||
* to be present in the Linux headers. */
|
||||
memcpy(&sin->sin_addr, &sin6.sin6_addr.s6_addr[12],
|
||||
sizeof(sin->sin_addr));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Look up a name from @p ss into @p name_buf.
|
||||
**/
|
||||
int lookup_name(int fd, const struct sockaddr_storage *ss,
|
||||
socklen_t ss_len,
|
||||
char *name_buf, size_t name_buf_len,
|
||||
char *port_buf, size_t port_buf_len)
|
||||
{
|
||||
int name_err;
|
||||
|
||||
/* reverse lookup */
|
||||
name_err = getnameinfo((struct sockaddr *) ss, ss_len,
|
||||
name_buf, name_buf_len,
|
||||
port_buf, port_buf_len,
|
||||
NI_NAMEREQD | NI_NUMERICSERV);
|
||||
if (name_err != 0) {
|
||||
strcpy(name_buf, default_name);
|
||||
rprintf(FERROR, RSYNC_NAME ": name lookup failed for %s: %s\n",
|
||||
client_addr(fd),
|
||||
gai_strerror(name_err));
|
||||
return name_err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Compare an addrinfo from the resolver to a sockinfo.
|
||||
*
|
||||
* Like strcmp, returns 0 for identical.
|
||||
**/
|
||||
int compare_addrinfo_sockaddr(const struct addrinfo *ai,
|
||||
const struct sockaddr_storage *ss)
|
||||
{
|
||||
int ss_family = get_sockaddr_family(ss);
|
||||
const char fn[] = "compare_addrinfo_sockaddr";
|
||||
|
||||
if (ai->ai_family != ss_family) {
|
||||
rprintf(FERROR,
|
||||
"%s: response family %d != %d\n",
|
||||
fn, ai->ai_family, ss_family);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* The comparison method depends on the particular AF. */
|
||||
if (ss_family == AF_INET) {
|
||||
const struct sockaddr_in *sin1, *sin2;
|
||||
|
||||
sin1 = (const struct sockaddr_in *) ss;
|
||||
sin2 = (const struct sockaddr_in *) ai->ai_addr;
|
||||
|
||||
return memcmp(&sin1->sin_addr, &sin2->sin_addr,
|
||||
sizeof sin1->sin_addr);
|
||||
}
|
||||
#ifdef INET6
|
||||
else if (ss_family == AF_INET6) {
|
||||
const struct sockaddr_in6 *sin1, *sin2;
|
||||
|
||||
sin1 = (const struct sockaddr_in6 *) ss;
|
||||
sin2 = (const struct sockaddr_in6 *) ai->ai_addr;
|
||||
|
||||
return memcmp(&sin1->sin6_addr, &sin2->sin6_addr,
|
||||
sizeof sin1->sin6_addr);
|
||||
}
|
||||
#endif /* INET6 */
|
||||
else {
|
||||
/* don't know */
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Do a forward lookup on @p name_buf and make sure it corresponds to
|
||||
* @p ss -- otherwise we may be being spoofed. If we suspect we are,
|
||||
* then we don't abort the connection but just emit a warning, and
|
||||
* change @p name_buf to be "UNKNOWN".
|
||||
**/
|
||||
int check_name(int fd,
|
||||
const struct sockaddr_storage *ss,
|
||||
char *name_buf,
|
||||
const char *port_buf)
|
||||
{
|
||||
struct addrinfo hints, *res, *res0;
|
||||
int error;
|
||||
int ss_family = get_sockaddr_family(ss);
|
||||
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = ss_family;
|
||||
hints.ai_flags = AI_CANONNAME;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
error = getaddrinfo(name_buf, port_buf, &hints, &res0);
|
||||
if (error) {
|
||||
rprintf(FERROR,
|
||||
RSYNC_NAME ": forward name lookup for %s failed: %s\n",
|
||||
name_buf, gai_strerror(error));
|
||||
strcpy(name_buf, default_name);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
/* Given all these results, we expect that one of them will be
|
||||
* the same as ss. The comparison is a bit complicated. */
|
||||
for (res = res0; res; res = res->ai_next) {
|
||||
if (!compare_addrinfo_sockaddr(res, ss))
|
||||
break; /* OK, identical */
|
||||
}
|
||||
|
||||
if (!res0) {
|
||||
/* We hit the end of the list without finding an
|
||||
* address that was the same as ss. */
|
||||
rprintf(FERROR, RSYNC_NAME
|
||||
": no known address for \"%s\": "
|
||||
"spoofed address?\n",
|
||||
name_buf);
|
||||
strcpy(name_buf, default_name);
|
||||
} else if (res == NULL) {
|
||||
/* We hit the end of the list without finding an
|
||||
* address that was the same as ss. */
|
||||
rprintf(FERROR, RSYNC_NAME
|
||||
": %s is not a known address for \"%s\": "
|
||||
"spoofed address?\n",
|
||||
client_addr(fd),
|
||||
name_buf);
|
||||
strcpy(name_buf, default_name);
|
||||
}
|
||||
|
||||
freeaddrinfo(res0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -168,9 +168,9 @@ static int rsync_module(int fd, int i)
|
||||
|
||||
if (!allow_access(addr, host, lp_hosts_allow(i), lp_hosts_deny(i))) {
|
||||
rprintf(FERROR,"rsync denied on module %s from %s (%s)\n",
|
||||
name, client_name(fd), client_addr(fd));
|
||||
name, host, addr);
|
||||
io_printf(fd,"@ERROR: access denied to %s from %s (%s)\n",
|
||||
name, client_name(fd), client_addr(fd));
|
||||
name, host, addr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ AC_CONFIG_SRCDIR([byteorder.h])
|
||||
AC_CONFIG_HEADER(config.h)
|
||||
AC_PREREQ(2.52)
|
||||
|
||||
RSYNC_VERSION=2.5.2pre1
|
||||
RSYNC_VERSION=2.5.2
|
||||
AC_SUBST(RSYNC_VERSION)
|
||||
AC_MSG_NOTICE([Configuring rsync $RSYNC_VERSION])
|
||||
|
||||
@@ -30,8 +30,7 @@ then
|
||||
AC_MSG_WARN([rsync requires an ANSI C compiler and you don't seem to have one])
|
||||
fi
|
||||
|
||||
# compile with optimisation and without debugging by default, unless
|
||||
# --debug is given. We must decide this before testing the compiler.
|
||||
# We must decide this before testing the compiler.
|
||||
|
||||
# Please allow this to default to yes, so that your users have more
|
||||
# chance of getting a useful stack trace if problems occur.
|
||||
@@ -553,3 +552,7 @@ AC_SUBST(BUILD_POPT)
|
||||
|
||||
AC_CONFIG_FILES([Makefile lib/dummy zlib/dummy popt/dummy shconfig])
|
||||
AC_OUTPUT
|
||||
|
||||
AC_MSG_RESULT()
|
||||
AC_MSG_RESULT([ rsync ${RSYNC_VERSION} configuration successful])
|
||||
AC_MSG_RESULT()
|
||||
|
||||
10
fileio.c
10
fileio.c
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
Copyright (C) Andrew Tridgell 1998
|
||||
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
|
||||
@@ -38,7 +39,7 @@ int sparse_end(int f)
|
||||
|
||||
static int write_sparse(int f,char *buf,size_t len)
|
||||
{
|
||||
int l1=0,l2=0;
|
||||
size_t l1=0, l2=0;
|
||||
int ret;
|
||||
|
||||
for (l1=0;l1<len && buf[l1]==0;l1++) ;
|
||||
@@ -56,10 +57,11 @@ static int write_sparse(int f,char *buf,size_t len)
|
||||
if (l1 == len)
|
||||
return len;
|
||||
|
||||
if ((ret=write(f,buf+l1,len-(l1+l2))) != len-(l1+l2)) {
|
||||
if (ret == -1 || ret == 0) return ret;
|
||||
ret = write(f, buf + l1, len - (l1+l2));
|
||||
if (ret == -1 || ret == 0)
|
||||
return ret;
|
||||
else if (ret != (int) (len - (l1+l2)))
|
||||
return (l1+ret);
|
||||
}
|
||||
|
||||
if (l2 > 0)
|
||||
do_lseek(f,l2,SEEK_CUR);
|
||||
|
||||
@@ -31,6 +31,7 @@ extern int am_root;
|
||||
extern int preserve_devices;
|
||||
extern int preserve_hard_links;
|
||||
extern int update_only;
|
||||
extern int opt_ignore_existing;
|
||||
extern int whole_file;
|
||||
extern int block_size;
|
||||
extern int csum_length;
|
||||
@@ -383,6 +384,12 @@ void recv_generator(char *fname,struct file_list *flist,int i,int f_out)
|
||||
return;
|
||||
}
|
||||
|
||||
if (opt_ignore_existing && fnamecmp == fname) {
|
||||
if (verbose > 1)
|
||||
rprintf(FINFO,"%s exists\n",fname);
|
||||
return;
|
||||
}
|
||||
|
||||
if (update_only && cmp_modtime(st.st_mtime,file->modtime)>0 && fnamecmp == fname) {
|
||||
if (verbose > 1)
|
||||
rprintf(FINFO,"%s is newer\n",fname);
|
||||
|
||||
5
io.c
5
io.c
@@ -527,8 +527,7 @@ void io_flush(void)
|
||||
}
|
||||
|
||||
|
||||
/* XXX: fd is ignored, which seems a little strange. */
|
||||
void io_end_buffering(int fd)
|
||||
void io_end_buffering(void)
|
||||
{
|
||||
io_flush();
|
||||
if (!io_multiplexing_out) {
|
||||
@@ -549,7 +548,7 @@ static void writefd(int fd,char *buf,size_t len)
|
||||
}
|
||||
|
||||
while (len) {
|
||||
int n = MIN(len, IO_BUFFER_SIZE-io_buffer_count);
|
||||
int n = MIN((int) len, IO_BUFFER_SIZE-io_buffer_count);
|
||||
if (n > 0) {
|
||||
memcpy(io_buffer+io_buffer_count, buf, n);
|
||||
buf += n;
|
||||
|
||||
17
log.c
17
log.c
@@ -409,6 +409,12 @@ static void log_formatted(enum logcode code,
|
||||
extern int am_daemon;
|
||||
int64 b;
|
||||
|
||||
/* We expand % codes one by one in place in buf. We don't
|
||||
* copy in the terminating nul of the inserted strings, but
|
||||
* rather keep going until we reach the nul of the format.
|
||||
* Just to make sure we don't clobber that nul and therefore
|
||||
* accidentally keep going, we zero the buffer now. */
|
||||
memset(buf, 0, sizeof buf);
|
||||
strlcpy(buf, format, sizeof(buf));
|
||||
|
||||
for (s=&buf[0];
|
||||
@@ -466,7 +472,11 @@ static void log_formatted(enum logcode code,
|
||||
break;
|
||||
}
|
||||
|
||||
if (!n) continue;
|
||||
/* n is the string to be inserted in place of this %
|
||||
* code; l is its length not including the trailing
|
||||
* NUL */
|
||||
if (!n)
|
||||
continue;
|
||||
|
||||
l = strlen(n);
|
||||
|
||||
@@ -476,11 +486,16 @@ static void log_formatted(enum logcode code,
|
||||
exit_cleanup(RERR_MESSAGEIO);
|
||||
}
|
||||
|
||||
/* Shuffle the rest of the string along to make space for n */
|
||||
if (l != 2) {
|
||||
memmove(s+(l-1), s+1, strlen(s+1)+1);
|
||||
}
|
||||
|
||||
/* Copy in n but NOT its nul, because the format sting
|
||||
* probably continues after this. */
|
||||
memcpy(p, n, l);
|
||||
|
||||
/* Skip over inserted string; continue looking */
|
||||
s = p+l;
|
||||
}
|
||||
|
||||
|
||||
1
main.c
1
main.c
@@ -60,6 +60,7 @@ static void report(int f)
|
||||
if (do_stats) {
|
||||
/* These come out from every process */
|
||||
show_malloc_stats();
|
||||
show_flist_stats();
|
||||
}
|
||||
|
||||
if (am_daemon) {
|
||||
|
||||
6
match.c
6
match.c
@@ -71,7 +71,7 @@ static void build_hash_table(struct sum_struct *s)
|
||||
if (!tag_table || !targets)
|
||||
out_of_memory("build_hash_table");
|
||||
|
||||
for (i=0;i<s->count;i++) {
|
||||
for (i=0;i<(int) s->count;i++) {
|
||||
targets[i].i = i;
|
||||
targets[i].t = gettag(s->sums[i].sum1);
|
||||
}
|
||||
@@ -175,7 +175,7 @@ static void hash_search(int f,struct sum_struct *s,
|
||||
|
||||
sum = (s1 & 0xffff) | (s2 << 16);
|
||||
tag_hits++;
|
||||
for (; j<s->count && targets[j].t == t; j++) {
|
||||
for (; j < (int) s->count && targets[j].t == t; j++) {
|
||||
int l, i = targets[j].i;
|
||||
|
||||
if (sum != s->sums[i].sum1) continue;
|
||||
@@ -201,7 +201,7 @@ static void hash_search(int f,struct sum_struct *s,
|
||||
|
||||
/* we've found a match, but now check to see
|
||||
if last_i can hint at a better match */
|
||||
for (j++; j<s->count && targets[j].t == t; j++) {
|
||||
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;
|
||||
|
||||
@@ -65,6 +65,7 @@ int size_only=0;
|
||||
int bwlimit=0;
|
||||
int delete_after=0;
|
||||
int only_existing=0;
|
||||
int opt_ignore_existing=0;
|
||||
int max_delete=0;
|
||||
int ignore_errors=0;
|
||||
#ifdef _WIN32
|
||||
@@ -208,6 +209,7 @@ void usage(enum logcode F)
|
||||
rprintf(F," --rsync-path=PATH specify path to rsync on the remote machine\n");
|
||||
rprintf(F," -C, --cvs-exclude auto ignore files in the same way CVS does\n");
|
||||
rprintf(F," --existing only update files that already exist\n");
|
||||
rprintf(F," --ignore-existing ignore files that already exist on the receiving side\n");
|
||||
rprintf(F," --delete delete files that don't exist on the sending side\n");
|
||||
rprintf(F," --delete-excluded also delete excluded files on the receiving side\n");
|
||||
rprintf(F," --delete-after delete after transferring, not before\n");
|
||||
@@ -262,7 +264,7 @@ enum {OPT_VERSION = 1000, OPT_SUFFIX, OPT_SENDER, OPT_SERVER, OPT_EXCLUDE,
|
||||
OPT_LOG_FORMAT, OPT_PASSWORD_FILE, OPT_SIZE_ONLY, OPT_ADDRESS,
|
||||
OPT_DELETE_AFTER, OPT_EXISTING, OPT_MAX_DELETE, OPT_BACKUP_DIR,
|
||||
OPT_IGNORE_ERRORS, OPT_BWLIMIT, OPT_BLOCKING_IO,
|
||||
OPT_MODIFY_WINDOW, OPT_READ_BATCH, OPT_WRITE_BATCH};
|
||||
OPT_MODIFY_WINDOW, OPT_READ_BATCH, OPT_WRITE_BATCH, OPT_IGNORE_EXISTING};
|
||||
|
||||
static struct poptOption long_options[] = {
|
||||
/* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
|
||||
@@ -276,6 +278,7 @@ static struct poptOption long_options[] = {
|
||||
{"one-file-system", 'x', POPT_ARG_NONE, &one_file_system},
|
||||
{"delete", 0, POPT_ARG_NONE, &delete_mode},
|
||||
{"existing", 0, POPT_ARG_NONE, &only_existing},
|
||||
{"ignore-existing", 0, POPT_ARG_NONE, &opt_ignore_existing},
|
||||
{"delete-after", 0, POPT_ARG_NONE, &delete_after},
|
||||
{"delete-excluded", 0, POPT_ARG_NONE, 0, OPT_DELETE_EXCLUDED},
|
||||
{"force", 0, POPT_ARG_NONE, &force_delete},
|
||||
@@ -691,6 +694,9 @@ void server_options(char **args,int *argc)
|
||||
if (only_existing && am_sender)
|
||||
args[ac++] = "--existing";
|
||||
|
||||
if (opt_ignore_existing && am_sender)
|
||||
args[ac++] = "--ignore-existing";
|
||||
|
||||
if (tmpdir) {
|
||||
args[ac++] = "--temp-dir";
|
||||
args[ac++] = tmpdir;
|
||||
|
||||
@@ -249,7 +249,7 @@ static int receive_data(int f_in,struct map_struct *buf,int fd,char *fname,
|
||||
i = -(i+1);
|
||||
offset2 = i*(OFF_T)n;
|
||||
len = n;
|
||||
if (i == count-1 && remainder != 0)
|
||||
if (i == (int) count-1 && remainder != 0)
|
||||
len = remainder;
|
||||
|
||||
stats.matched_data += len;
|
||||
@@ -265,7 +265,7 @@ static int receive_data(int f_in,struct map_struct *buf,int fd,char *fname,
|
||||
sum_update(map,len);
|
||||
}
|
||||
|
||||
if (fd != -1 && write_file(fd,map,len) != len) {
|
||||
if (fd != -1 && write_file(fd,map,len) != (int) len) {
|
||||
rprintf(FERROR,"write failed on %s : %s\n",
|
||||
fname,strerror(errno));
|
||||
exit_cleanup(RERR_FILEIO);
|
||||
|
||||
7
rsync.h
7
rsync.h
@@ -303,8 +303,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 int64
|
||||
#define DEV64_T int64
|
||||
#define INO64_T unsigned int64
|
||||
#define DEV64_T unsigned int64
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a,b) ((a)<(b)?(a):(b))
|
||||
@@ -422,11 +422,12 @@ static inline int flist_up(struct file_list *flist, int i)
|
||||
}
|
||||
|
||||
#include "byteorder.h"
|
||||
#include "proto.h"
|
||||
#include "lib/mdfour.h"
|
||||
#include "lib/permstring.h"
|
||||
#include "lib/addrinfo.h"
|
||||
|
||||
#include "proto.h"
|
||||
|
||||
/* We have replacement versions of these if they're missing. */
|
||||
#ifndef HAVE_ASPRINTF
|
||||
int asprintf(char **ptr, const char *format, ...);
|
||||
|
||||
7
rsync.yo
7
rsync.yo
@@ -1,5 +1,5 @@
|
||||
mailto(rsync-bugs@samba.org)
|
||||
manpage(rsync)(1)(14 Dec 2001)()()
|
||||
manpage(rsync)(1)(25 Jan 2002)()()
|
||||
manpagename(rsync)(faster, flexible replacement for rcp)
|
||||
manpagesynopsis()
|
||||
|
||||
@@ -245,6 +245,7 @@ verb(
|
||||
--rsync-path=PATH specify path to rsync on the remote machine
|
||||
-C, --cvs-exclude auto ignore files in the same way CVS does
|
||||
--existing only update files that already exist
|
||||
--ignore-existing ignore files that already exist on the receiving side
|
||||
--delete delete files that don't exist on the sending side
|
||||
--delete-excluded also delete excluded files on the receiving side
|
||||
--delete-after delete after transferring, not before
|
||||
@@ -452,6 +453,10 @@ contents of only one filesystem.
|
||||
dit(bf(--existing)) This tells rsync not to create any new files -
|
||||
only update files that already exist on the destination.
|
||||
|
||||
dit(bf(--ignore-existing))
|
||||
This tells rsync not to update files that already exist on
|
||||
the destination.
|
||||
|
||||
dit(bf(--max-delete=NUM)) This tells rsync not to delete more than NUM
|
||||
files or directories. This is useful when mirroring very large trees
|
||||
to prevent disasters.
|
||||
|
||||
4
sender.c
4
sender.c
@@ -55,14 +55,14 @@ static struct sum_struct *receive_sums(int f)
|
||||
s->sums = (struct sum_buf *)malloc(sizeof(s->sums[0])*s->count);
|
||||
if (!s->sums) out_of_memory("receive_sums");
|
||||
|
||||
for (i=0;i<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,csum_length);
|
||||
|
||||
s->sums[i].offset = offset;
|
||||
s->sums[i].i = i;
|
||||
|
||||
if (i == s->count-1 && s->remainder != 0) {
|
||||
if (i == (int) s->count-1 && s->remainder != 0) {
|
||||
s->sums[i].len = s->remainder;
|
||||
} else {
|
||||
s->sums[i].len = s->n;
|
||||
|
||||
155
socket.c
155
socket.c
@@ -33,6 +33,7 @@
|
||||
|
||||
#include "rsync.h"
|
||||
|
||||
|
||||
/* Establish a proxy connection on an open socket to a web roxy by
|
||||
* using the CONNECT method. */
|
||||
static int establish_proxy_connection(int fd, char *host, int port)
|
||||
@@ -41,7 +42,7 @@ static int establish_proxy_connection(int fd, char *host, int port)
|
||||
char *cp;
|
||||
|
||||
snprintf(buffer, sizeof(buffer), "CONNECT %s:%d HTTP/1.0\r\n\r\n", host, port);
|
||||
if (write(fd, buffer, strlen(buffer)) != strlen(buffer)) {
|
||||
if (write(fd, buffer, strlen(buffer)) != (int) strlen(buffer)) {
|
||||
rprintf(FERROR, "failed to write to proxy: %s\n",
|
||||
strerror(errno));
|
||||
return -1;
|
||||
@@ -565,136 +566,6 @@ void become_daemon(void)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the IP addr of the client as a string
|
||||
**/
|
||||
char *client_addr(int fd)
|
||||
{
|
||||
struct sockaddr_storage ss;
|
||||
socklen_t length = sizeof ss;
|
||||
static char addr_buf[100];
|
||||
static int initialised;
|
||||
|
||||
if (initialised) return addr_buf;
|
||||
|
||||
initialised = 1;
|
||||
|
||||
if (getpeername(fd, (struct sockaddr *)&ss, &length)) {
|
||||
exit_cleanup(RERR_SOCKETIO);
|
||||
}
|
||||
|
||||
getnameinfo((struct sockaddr *)&ss, length,
|
||||
addr_buf, sizeof(addr_buf), NULL, 0, NI_NUMERICHOST);
|
||||
return addr_buf;
|
||||
}
|
||||
|
||||
|
||||
static int get_sockaddr_family(const struct sockaddr_storage *ss)
|
||||
{
|
||||
return ((struct sockaddr *) ss)->sa_family;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the DNS name of the client
|
||||
**/
|
||||
char *client_name(int fd)
|
||||
{
|
||||
struct sockaddr_storage ss;
|
||||
socklen_t length = sizeof ss;
|
||||
static char name_buf[100];
|
||||
static char port_buf[100];
|
||||
char *def = "UNKNOWN";
|
||||
static int initialised;
|
||||
struct addrinfo hints, *res, *res0;
|
||||
int error;
|
||||
|
||||
if (initialised) return name_buf;
|
||||
|
||||
initialised = 1;
|
||||
|
||||
strcpy(name_buf,def);
|
||||
|
||||
if (getpeername(fd, (struct sockaddr *)&ss, &length)) {
|
||||
/* FIXME: Can we really not continue? */
|
||||
rprintf(FERROR, RSYNC_NAME ": getpeername on fd%d failed: %s\n",
|
||||
fd, strerror(errno));
|
||||
exit_cleanup(RERR_SOCKETIO);
|
||||
}
|
||||
|
||||
#ifdef INET6
|
||||
if (get_sockaddr_family(&ss) == AF_INET6 &&
|
||||
IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)&ss)->sin6_addr)) {
|
||||
/* OK, so ss is in the IPv6 family, but it is really
|
||||
* an IPv4 address: something like
|
||||
* "::ffff:10.130.1.2". If we use it as-is, then the
|
||||
* reverse lookup might fail or perhaps something else
|
||||
* bad might happen. So instead we convert it to an
|
||||
* equivalent address in the IPv4 address family. */
|
||||
struct sockaddr_in6 sin6;
|
||||
struct sockaddr_in *sin;
|
||||
|
||||
memcpy(&sin6, &ss, sizeof(sin6));
|
||||
sin = (struct sockaddr_in *)&ss;
|
||||
memset(sin, 0, sizeof(*sin));
|
||||
sin->sin_family = AF_INET;
|
||||
length = sizeof(struct sockaddr_in);
|
||||
#ifdef HAVE_SOCKADDR_LEN
|
||||
sin->sin_len = length;
|
||||
#endif
|
||||
sin->sin_port = sin6.sin6_port;
|
||||
/* FIXME: Isn't there a macro we can use here rather
|
||||
* than grovelling through the struct? It might be
|
||||
* wrong on some systems. */
|
||||
memcpy(&sin->sin_addr, &sin6.sin6_addr.s6_addr[12],
|
||||
sizeof(sin->sin_addr));
|
||||
}
|
||||
#endif
|
||||
|
||||
/* reverse lookup */
|
||||
if (getnameinfo((struct sockaddr *)&ss, length,
|
||||
name_buf, sizeof(name_buf), port_buf, sizeof(port_buf),
|
||||
NI_NAMEREQD | NI_NUMERICSERV) != 0) {
|
||||
strcpy(name_buf, def);
|
||||
rprintf(FERROR, "reverse name lookup failed\n");
|
||||
}
|
||||
|
||||
/* forward lookup */
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = PF_UNSPEC;
|
||||
hints.ai_flags = AI_CANONNAME;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
error = getaddrinfo(name_buf, port_buf, &hints, &res0);
|
||||
if (error) {
|
||||
strcpy(name_buf, def);
|
||||
rprintf(FERROR,
|
||||
RSYNC_NAME ": forward name lookup for %s failed: %s\n",
|
||||
port_buf,
|
||||
gai_strerror(error));
|
||||
return name_buf;
|
||||
}
|
||||
|
||||
/* XXX sin6_flowinfo and other fields */
|
||||
for (res = res0; res; res = res->ai_next) {
|
||||
if (res->ai_family != get_sockaddr_family(&ss))
|
||||
continue;
|
||||
if (res->ai_addrlen != length)
|
||||
continue;
|
||||
if (memcmp(res->ai_addr, &ss, res->ai_addrlen) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (res == NULL) {
|
||||
strcpy(name_buf, def);
|
||||
rprintf(FERROR, RSYNC_NAME ": "
|
||||
"reverse name lookup for \"%s\" failed on fd%d - spoofed address? \n",
|
||||
name_buf, fd);
|
||||
}
|
||||
|
||||
freeaddrinfo(res0);
|
||||
return name_buf;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
this is like socketpair but uses tcp. It is used by the Samba
|
||||
@@ -763,16 +634,20 @@ static int socketpair_tcp(int fd[2])
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
run a program on a local tcp socket, this is used to launch smbd
|
||||
when regression testing
|
||||
the return value is a socket which is attached to a subprocess
|
||||
running "prog". stdin and stdout are attached. stderr is left
|
||||
attached to the original stderr
|
||||
******************************************************************/
|
||||
|
||||
/**
|
||||
* Run a program on a local tcp socket, so that we can talk to it's
|
||||
* stdin and stdout. This is used to fake a connection to a daemon
|
||||
* for testing -- not for the normal case of running SSH.
|
||||
*
|
||||
* @return a socket which is attached to a subprocess running
|
||||
* "prog". stdin and stdout are attached. stderr is left attached to
|
||||
* the original stderr
|
||||
**/
|
||||
int sock_exec(const char *prog)
|
||||
{
|
||||
int fd[2];
|
||||
|
||||
if (socketpair_tcp(fd) != 0) {
|
||||
rprintf (FERROR, RSYNC_NAME
|
||||
": socketpair_tcp failed (%s)\n",
|
||||
@@ -785,10 +660,12 @@ int sock_exec(const char *prog)
|
||||
close(1);
|
||||
dup(fd[1]);
|
||||
dup(fd[1]);
|
||||
if (verbose > 3)
|
||||
if (verbose > 3) {
|
||||
/* Can't use rprintf because we've forked. */
|
||||
fprintf (stderr,
|
||||
RSYNC_NAME ": execute socket program \"%s\"\n",
|
||||
prog);
|
||||
}
|
||||
exit (system (prog));
|
||||
}
|
||||
close (fd[1]);
|
||||
|
||||
29
testsuite/devices.test
Normal file
29
testsuite/devices.test
Normal file
@@ -0,0 +1,29 @@
|
||||
#! /bin/sh
|
||||
|
||||
# Copyright (C) 2002 by Martin Pool <mbp@samba.org>
|
||||
|
||||
# This program is distributable under the terms of the GNU GPL (see
|
||||
# COPYING).
|
||||
|
||||
# Test rsync handling of devices. This can only run if you're root.
|
||||
|
||||
. $srcdir/testsuite/rsync.fns
|
||||
|
||||
set -x
|
||||
|
||||
# Build some hardlinks
|
||||
|
||||
fromdir="$scratchdir/from"
|
||||
todir="$scratchdir/to"
|
||||
|
||||
# TODO: Need to test whether hardlinks are possible on this OS/filesystem
|
||||
|
||||
mkdir "$fromdir"
|
||||
mknod "$fromdir/char" c 42 69 || test_skipped "Can't create char device node?"
|
||||
mknod "$fromdir/block" b 42 69 || test_skipped "Can't create block device node?"
|
||||
|
||||
checkit "rsync -aHvv \"$fromdir/\" \"$todir/\"" "$fromdir" "$todir"
|
||||
|
||||
exit 0
|
||||
# last [] may have failed but if we get here then we've won
|
||||
|
||||
@@ -150,7 +150,11 @@ checkit() {
|
||||
echo "-------------"
|
||||
echo "check how the files compare with diff:"
|
||||
echo ""
|
||||
diff -cr $2 $3 || failed=YES
|
||||
for f in `cd "$2"; find . -type f -print `
|
||||
do
|
||||
diff -u "$2"/"$f" "$3"/"$f" || failed=YES
|
||||
done
|
||||
|
||||
echo "-------------"
|
||||
echo "check how the directory listings compare with diff:"
|
||||
echo ""
|
||||
@@ -222,6 +226,11 @@ test_fail() {
|
||||
exit 1
|
||||
}
|
||||
|
||||
test_skipped() {
|
||||
echo "$@" >&2
|
||||
exit 77
|
||||
}
|
||||
|
||||
# It failed, but we expected that. don't dump out error logs,
|
||||
# because most users won't want to see them. But do leave
|
||||
# the working directory around.
|
||||
|
||||
@@ -18,11 +18,11 @@ build_symlinks || test_fail "failed to build symlinks"
|
||||
# should be missing.
|
||||
"$rsync_bin" -r "$fromdir/" "$todir" || test_fail "rsync returned $?"
|
||||
|
||||
[ -f "$todir/referent" ] || test_fail "referent was not copied"
|
||||
[ -d "$todir/from" ] && test_fail "extra level of directories"
|
||||
[ -L "$todir/dangling" ] && test_fail "dangling symlink was copied"
|
||||
[ -L "$todir/relative" ] && test_fail "relative symlink was copied"
|
||||
[ -L "$todir/absolute" ] && test_fail "absolute symlink was copied"
|
||||
[ -f "${todir}/referent" ] || test_fail "referent was not copied"
|
||||
[ -d "${todir}/from" ] && test_fail "extra level of directories"
|
||||
[ -L "${todir}/dangling" ] && test_fail "dangling symlink was copied"
|
||||
[ -L "${todir}/relative" ] && test_fail "relative symlink was copied"
|
||||
[ -L "${todir}/absolute" ] && test_fail "absolute symlink was copied"
|
||||
|
||||
exit 0
|
||||
# last [] may have failed but if we get here then we've one
|
||||
|
||||
116
util.c
116
util.c
@@ -84,6 +84,26 @@ int fd_pair(int fd[2])
|
||||
}
|
||||
|
||||
|
||||
void print_child_argv(char **cmd)
|
||||
{
|
||||
rprintf(FINFO, RSYNC_NAME ": open connection using ");
|
||||
for (; *cmd; cmd++) {
|
||||
/* Look for characters that ought to be quoted. This
|
||||
* is not a great quoting algorithm, but it's
|
||||
* sufficient for a log message. */
|
||||
if (strspn(*cmd, "abcdefghijklmnopqrstuvwxyz"
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"0123456789"
|
||||
",.-_=+@/") != strlen(*cmd)) {
|
||||
rprintf(FINFO, "\"%s\" ", *cmd);
|
||||
} else {
|
||||
rprintf(FINFO, "%s ", *cmd);
|
||||
}
|
||||
}
|
||||
rprintf(FINFO, "\n");
|
||||
}
|
||||
|
||||
|
||||
/* this is derived from CVS code
|
||||
|
||||
note that in the child STDIN is set to blocking and STDOUT
|
||||
@@ -94,59 +114,63 @@ int fd_pair(int fd[2])
|
||||
used to cope with badly broken rsh implementations like the one on
|
||||
solaris.
|
||||
*/
|
||||
pid_t piped_child(char **command,int *f_in,int *f_out)
|
||||
pid_t piped_child(char **command, int *f_in, int *f_out)
|
||||
{
|
||||
pid_t pid;
|
||||
int to_child_pipe[2];
|
||||
int from_child_pipe[2];
|
||||
extern int blocking_io;
|
||||
pid_t pid;
|
||||
int to_child_pipe[2];
|
||||
int from_child_pipe[2];
|
||||
extern int blocking_io;
|
||||
|
||||
if (verbose > 0) {
|
||||
print_child_argv(command);
|
||||
}
|
||||
|
||||
if (fd_pair(to_child_pipe) < 0 ||
|
||||
fd_pair(from_child_pipe) < 0) {
|
||||
rprintf(FERROR,"pipe: %s\n",strerror(errno));
|
||||
exit_cleanup(RERR_IPC);
|
||||
}
|
||||
if (fd_pair(to_child_pipe) < 0 || fd_pair(from_child_pipe) < 0) {
|
||||
rprintf(FERROR, "pipe: %s\n", strerror(errno));
|
||||
exit_cleanup(RERR_IPC);
|
||||
}
|
||||
|
||||
|
||||
pid = do_fork();
|
||||
if (pid == -1) {
|
||||
rprintf(FERROR,"fork: %s\n",strerror(errno));
|
||||
exit_cleanup(RERR_IPC);
|
||||
}
|
||||
pid = do_fork();
|
||||
if (pid == -1) {
|
||||
rprintf(FERROR, "fork: %s\n", strerror(errno));
|
||||
exit_cleanup(RERR_IPC);
|
||||
}
|
||||
|
||||
if (pid == 0)
|
||||
{
|
||||
extern int orig_umask;
|
||||
if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 ||
|
||||
close(to_child_pipe[1]) < 0 ||
|
||||
close(from_child_pipe[0]) < 0 ||
|
||||
dup2(from_child_pipe[1], STDOUT_FILENO) < 0) {
|
||||
rprintf(FERROR,"Failed to dup/close : %s\n",strerror(errno));
|
||||
exit_cleanup(RERR_IPC);
|
||||
}
|
||||
if (to_child_pipe[0] != STDIN_FILENO) close(to_child_pipe[0]);
|
||||
if (from_child_pipe[1] != STDOUT_FILENO) close(from_child_pipe[1]);
|
||||
umask(orig_umask);
|
||||
set_blocking(STDIN_FILENO);
|
||||
if (blocking_io) {
|
||||
set_blocking(STDOUT_FILENO);
|
||||
}
|
||||
execvp(command[0], command);
|
||||
rprintf(FERROR,"Failed to exec %s : %s\n",
|
||||
command[0],strerror(errno));
|
||||
exit_cleanup(RERR_IPC);
|
||||
}
|
||||
if (pid == 0) {
|
||||
extern int orig_umask;
|
||||
if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 ||
|
||||
close(to_child_pipe[1]) < 0 ||
|
||||
close(from_child_pipe[0]) < 0 ||
|
||||
dup2(from_child_pipe[1], STDOUT_FILENO) < 0) {
|
||||
rprintf(FERROR, "Failed to dup/close : %s\n",
|
||||
strerror(errno));
|
||||
exit_cleanup(RERR_IPC);
|
||||
}
|
||||
if (to_child_pipe[0] != STDIN_FILENO)
|
||||
close(to_child_pipe[0]);
|
||||
if (from_child_pipe[1] != STDOUT_FILENO)
|
||||
close(from_child_pipe[1]);
|
||||
umask(orig_umask);
|
||||
set_blocking(STDIN_FILENO);
|
||||
if (blocking_io) {
|
||||
set_blocking(STDOUT_FILENO);
|
||||
}
|
||||
execvp(command[0], command);
|
||||
rprintf(FERROR, "Failed to exec %s : %s\n",
|
||||
command[0], strerror(errno));
|
||||
exit_cleanup(RERR_IPC);
|
||||
}
|
||||
|
||||
if (close(from_child_pipe[1]) < 0 ||
|
||||
close(to_child_pipe[0]) < 0) {
|
||||
rprintf(FERROR,"Failed to close : %s\n",strerror(errno));
|
||||
exit_cleanup(RERR_IPC);
|
||||
}
|
||||
if (close(from_child_pipe[1]) < 0 || close(to_child_pipe[0]) < 0) {
|
||||
rprintf(FERROR, "Failed to close : %s\n", strerror(errno));
|
||||
exit_cleanup(RERR_IPC);
|
||||
}
|
||||
|
||||
*f_in = from_child_pipe[0];
|
||||
*f_out = to_child_pipe[1];
|
||||
*f_in = from_child_pipe[0];
|
||||
*f_out = to_child_pipe[1];
|
||||
|
||||
return pid;
|
||||
return pid;
|
||||
}
|
||||
|
||||
pid_t local_child(int argc, char **argv,int *f_in,int *f_out)
|
||||
@@ -535,7 +559,7 @@ static void glob_expand_one(char *s, char **argv, int *argc, int maxargs)
|
||||
globfree(&globbuf);
|
||||
return;
|
||||
}
|
||||
for (i=0; i<(maxargs - (*argc)) && i<globbuf.gl_pathc;i++) {
|
||||
for (i=0; i<(maxargs - (*argc)) && i < (int) globbuf.gl_pathc;i++) {
|
||||
if (i == 0) free(argv[*argc]);
|
||||
argv[(*argc) + i] = strdup(globbuf.gl_pathv[i]);
|
||||
if (!argv[(*argc) + i]) out_of_memory("glob_expand");
|
||||
|
||||
Reference in New Issue
Block a user