Compare commits

...

461 Commits

Author SHA1 Message Date
Wayne Davison
d8195637d4 Additional testing confirmed the limited scope of the sources affected
by the -R sorting bug.
2004-04-30 19:14:52 +00:00
Wayne Davison
c8d771a0fb Preparing for release of 2.6.2 2004-04-30 18:03:33 +00:00
Wayne Davison
9130776c4e Mention the last few tweaks that made it into 2.6.2. 2004-04-30 17:53:51 +00:00
Wayne Davison
9eac94a4dd Improved the program that checks for broken large-file locking. 2004-04-30 17:38:22 +00:00
Wayne Davison
6e06d2f31a Don't rely on the local shell's wildcard expansion to make the test
work right -- it might not be quite as compatible as we need.
2004-04-30 17:24:49 +00:00
Wayne Davison
6a6d21136a Only refer to AI_NUMERICHOST if it is defined. 2004-04-30 16:10:45 +00:00
Wayne Davison
f28bd83346 Fixed a few typos. 2004-04-30 15:46:41 +00:00
Wayne Davison
96fb478eae Mention the desire to improve how a daemon returns errors. 2004-04-29 21:12:46 +00:00
Wayne Davison
8752b3fcd8 Describe the changes for 2.6.2. 2004-04-29 21:09:33 +00:00
Wayne Davison
55ffed7e42 Preparing for release of 2.6.2pre1 2004-04-29 20:36:22 +00:00
Wayne Davison
e00df64bae Got rid of unused check for sys/sysctl.h. 2004-04-29 19:40:17 +00:00
Wayne Davison
080ddf58ae Fixed a sorting problem when an entry has an empty (but not NULL)
dirname (which I had thought impossible, but it appears to occur
with --relative in some instances).
2004-04-29 19:37:15 +00:00
Wayne Davison
4ce48a5bfd Restore old behavior of logging most daemon errors instead of sending
them to the user.  This should eventually be improved to duplicate
some of these messages to the user to keep them informed about what
went wrong.
2004-04-29 19:34:31 +00:00
Wayne Davison
20bf7f847f Undefined __attribute__ in some circumstances. 2004-04-28 17:35:08 +00:00
Wayne Davison
b66d00853b Fixed the use of an uninitialized variable in map_uid() and map_gid(). 2004-04-28 17:31:31 +00:00
Wayne Davison
8b602edda4 In copy_file(), check len < 0 before checking the close() return values. 2004-04-27 19:59:37 +00:00
Wayne Davison
9f27cd8ca6 Check the return code from close() and output an error if it
fails.
2004-04-27 19:51:33 +00:00
Wayne Davison
b084f9e092 Got rid of a debug-output statement. 2004-04-27 16:41:33 +00:00
Wayne Davison
4220e1098e Preparing for release of 2.6.1 2004-04-27 03:55:37 +00:00
Wayne Davison
c30468169a - Tweaked the bullet char so that vim can auto-format the items more
easily (and then used vim to re-flow the items).
- Added a mention about the daemon security fix.
- Added the 2.6.1 release date.
2004-04-27 03:53:28 +00:00
Wayne Davison
c0d9e8c76b - Changed XFLG_NO_PREFIXES to XFLG_WORDS_ONLY.
- Got rid of HP-UX kludge (since it didn't help).
2004-04-27 01:36:16 +00:00
Wayne Davison
90a973fe8a Changed XFLG_NO_PREFIXES to XFLG_WORDS_ONLY. 2004-04-27 01:36:10 +00:00
Wayne Davison
7f0feb4dd6 - Changed XFLG_NO_PREFIXES to XFLG_WORDS_ONLY.
- Don't parse comment lines in add_exclude_file() when XFLG_WORD_SPLIT
  is set.
2004-04-27 01:36:06 +00:00
Wayne Davison
33a5432ea6 Got rid of HP-UX kludge (since it didn't help). 2004-04-27 01:36:00 +00:00
Wayne Davison
968ff560d2 Made a comment clearer. 2004-04-27 01:00:58 +00:00
Wayne Davison
cd59be1d5e One more try at getting the HP-UX system in the build farm to compile
popt.
2004-04-25 20:36:41 +00:00
Wayne Davison
8b2869c0d2 Don't use __attribute__((__unused__)) on HP-UX w/o gcc. 2004-04-25 16:10:09 +00:00
Wayne Davison
82a51ea53d Improved the debug string for the local_exclude_list. 2004-04-24 08:00:39 +00:00
Wayne Davison
20af605eba Improved the EXCLUDE PATTERNS section some more. 2004-04-24 06:16:04 +00:00
Wayne Davison
a6536635e3 Fixed a comment. 2004-04-23 08:09:13 +00:00
Wayne Davison
adddd075eb Mention how --update behaves when the type of the file differs on
the source and destination systems.
2004-04-23 05:14:39 +00:00
Wayne Davison
a0c823b22b Recently added caveat is no longer true. 2004-04-23 01:33:35 +00:00
Wayne Davison
9fdb334e85 Restore the old include behavior where a command-line include could
override a .cvsignore exclude.
2004-04-22 22:17:15 +00:00
Wayne Davison
f89e890b87 Got rid of a wrong paragraph. 2004-04-22 21:35:45 +00:00
Wayne Davison
1c666c3fcb Got rid of a bunch of cruft. 2004-04-22 21:17:58 +00:00
Wayne Davison
2a383be0f1 Updated the default list of cvs-excluded files and added some extra
info on how the option interacts with other include/exclude rules.
2004-04-22 18:17:30 +00:00
Wayne Davison
ac1d2d3384 Added "debug_type" to the exclude_list_struct. 2004-04-22 09:58:24 +00:00
Wayne Davison
acfcfa7053 No need to pass a debug string to check_exclude() anymore. 2004-04-22 09:58:21 +00:00
Wayne Davison
8ef81dd452 No need to pass a debug string to check_exclude() anymore. When we
free an exclude list, make sure we don't clear the debug_type string.
2004-04-22 09:58:18 +00:00
Wayne Davison
67340e9523 Initialize the new debug_type string in each exclude list and output
it in a couple extra debug messages.  When we free an exclude list,
make sure we don't clear the debug_type string.
2004-04-22 09:58:15 +00:00
Wayne Davison
a7ceddae34 Changed check_exclude()'s prototype. 2004-04-22 09:58:11 +00:00
Wayne Davison
24e1569f8b The debug output for add_exclude() now needs to limit the pattern to
print only "pat_len" chars.
2004-04-22 08:41:03 +00:00
Wayne Davison
de31639fff A couple minor text improvements. 2004-04-19 17:52:39 +00:00
Wayne Davison
8b46340924 Mentioned the better handling of option paths when a daemon is not
running with chroot enabled.
2004-04-18 06:29:06 +00:00
Wayne Davison
d008bcb5cd Made the device-changes section agree with the latest code. 2004-04-17 19:58:12 +00:00
Wayne Davison
0484b5b0b7 Preparing for release of 2.6.1pre-2 2004-04-17 18:40:16 +00:00
Wayne Davison
f01b6368a5 Mention that --from0 does not affect --cvs-exclude's reading of the
.cvsignore files.
2004-04-17 18:12:33 +00:00
Wayne Davison
40d38dc0be In add_exclude_file(), if we're word-splitting, stop reading a "line"
at any whitespace (so that we don't overflow the line buffer).
2004-04-17 17:55:45 +00:00
Wayne Davison
33a2361cc2 The inode and dev values in the idev struct are now uint64. 2004-04-17 17:14:16 +00:00
Wayne Davison
4124540d61 Changed the dev handling for -H back to using an opaque 64-bit
integer instead of trying to transfer it as separate major & minor
values.  Since the value is not interpreted by the receiving side
(just compared for equality), this is a safer way to go.
2004-04-17 17:14:12 +00:00
Wayne Davison
5f38126817 Use "uint64" instead of INO64_T (which is now gone). 2004-04-17 17:07:23 +00:00
Wayne Davison
b05b3c9b48 Fixed alloc_sanitize_path()'s handling of a rootdir == "/" (the old
code would generate a string that started with "//" instead of "/").
2004-04-17 17:06:03 +00:00
Wayne Davison
a03a9f4efe Don't say "skipped" if the file is just not being transferred (i.e.
when other updates, such as owner/permissions/etc. might be made).
2004-04-15 18:32:24 +00:00
Wayne Davison
3e55030372 Mention exclude improvements. 2004-04-15 18:23:52 +00:00
Wayne Davison
273c0420d0 Got rid of a couple useless lines. 2004-04-15 18:22:56 +00:00
Wayne Davison
5774786fa5 Moved some externs. 2004-04-15 16:55:23 +00:00
Wayne Davison
1a9ec1fd1c Got rid of zlib/dummy ("dummy" is in the zlib .cvsignore, where it
should be).
2004-04-15 06:54:14 +00:00
Wayne Davison
b2aa573b1c Our exclude lists are now comprised of a base structure with a head
and a tail pointer pointing to a linked list of items (rather than
an array of pointers that has to be reallocated all the time).
2004-04-14 23:33:40 +00:00
Wayne Davison
63d0331991 Added a "next" pointer to "exclude_struct" and added a new structure
for exclude lists, exclude_list_struct, that holds the head/tail
pointers for the list.
2004-04-14 23:33:37 +00:00
Wayne Davison
bf6dcd1713 Updated the exclude-list code to handle the new linked-list
structure format.
2004-04-14 23:33:34 +00:00
Wayne Davison
495723bb26 Updated the exclude-list code to handle the new linked-list
structure format.
2004-04-14 23:33:34 +00:00
Wayne Davison
911cb0662c Updated stub version of check_exclude(). 2004-04-14 22:49:54 +00:00
Wayne Davison
5387514eaf Added a description arg to check_exclude(). 2004-04-14 21:59:45 +00:00
Wayne Davison
61414c83ce The check_exclude() and report_exclude_result() functions now take a
description string that describes what kind of an include/exclude is
happening (which only gets output when verbose is set to 2 or more).
2004-04-14 21:59:41 +00:00
Wayne Davison
43a9d0e7c2 Improved the exclude testing by adding tests that exercise --cvs-exclude
and --delete-excluded.
2004-04-14 20:50:32 +00:00
Wayne Davison
df5cd107a5 Moved (and expanded) a verbose message from clientserver.c to socket.c
to solve an old FIXME comment.
2004-04-14 16:51:48 +00:00
Wayne Davison
abca4eba67 Fixed a potential problem parsing the "!" token from a word-split string. 2004-04-13 19:07:21 +00:00
Wayne Davison
96d3590a08 A few more improvements to get_exclude_tok() and add_exclude(). 2004-04-13 18:35:08 +00:00
Wayne Davison
8429aa9e0e Added an example for --link-dest. 2004-04-13 00:32:58 +00:00
Wayne Davison
79d4053048 Updated with latest news and some spelling mistakes corrected. 2004-04-12 18:03:08 +00:00
Wayne Davison
753b6b4692 Replaced MISSING_OK, MISSING_FATAL, ADD_INCLUDE, and ADD_EXCLUDE with
some new XFLG_* values (for the add_exclude*() function).
2004-04-12 17:42:35 +00:00
Wayne Davison
f8f726449b - add_exclude() now takes a flag int and can optionally word-split
items and/or ignore +/- prefixes.
- add_exclude_file() changed to take the same flags as add_exclude().
- add_exclude_line() was removed since add_exclude() can now do its job.
- make_exclude() now takes a size-limited string without a +/- prefix.
- add_cvs_excludes() was changed to word-split the items that come from
  a .cvsignore file, and to ignore all +/- prefixes in all the ignore
  sources.  Since CVS doesn't check if its ignore items are directories,
  the dir-names (e.g. SCCS, CVS, etc.) no longer have a trailing slash
  (making our excludes match CVS's ignores more exactly).
2004-04-12 17:42:32 +00:00
Wayne Davison
357406ecb2 Use the new XFLG_* flags to call the add_exclude*() functions. 2004-04-12 17:42:29 +00:00
Wayne Davison
3915fd7583 No need to cast st.st_rdev to DEV64_T anymore. 2004-04-12 16:52:43 +00:00
Wayne Davison
9c5e91f848 - Use dev_t instead of DEV64_T.
- Changed rdev_high to rdev_major.
- Use major(), minor(), and makedev() to manipulate device numbers.
- Send the major and minor values separately in protocol 28 and beyond.
2004-04-12 16:52:40 +00:00
Wayne Davison
af107f6c08 - Got rid of DEV64_T and changed the internal device variables to dev_t.
- Changed XMIT_SAME_HIGH_RDEV to XMIT_SAME_RDEV_MAJOR.
- Added XMIT_RDEV_MINOR_IS_SMALL.
2004-04-12 16:52:37 +00:00
Wayne Davison
a3dbb20a0e Fixed a bug where an exclude name that got sent over the wire could get
an extra "- " or "+ " parsed off the start of the name (i.e. we have to
quote excluded names that start with those strings with an extra "- "
at the start).
2004-04-10 10:31:11 +00:00
Wayne Davison
a3779426b6 UNUSED() misbehaves on HP-UX, not AIX. 2004-04-09 22:25:33 +00:00
Wayne Davison
2f5ca63d92 AIX doesn't like our UNUSED() macro, so let's eliminate it for them. 2004-04-09 21:51:34 +00:00
Wayne Davison
0e1d98ae92 Silence compiler warnings on Solaris. 2004-04-09 20:22:44 +00:00
Wayne Davison
04575bcab5 Missed one void-pointer-arithmetic case. 2004-04-09 20:17:01 +00:00
Wayne Davison
71b291d71b AIX's cc was complaining about the void* arithmetic. 2004-04-09 19:53:50 +00:00
Wayne Davison
decba3ae73 Removed debug code. 2004-04-09 19:18:34 +00:00
Wayne Davison
f8ed564c9f Changed sysmacros.h to sys/sysmacros.h. 2004-04-09 19:04:03 +00:00
Wayne Davison
47ba39bef6 Added some test code to assist in the remote debugging of the build
farm's Solaris machines.
2004-04-09 18:36:01 +00:00
Wayne Davison
71f7051489 Use MAJOR_IN_MKDEV and MAJOR_IN_SYSMACROS. 2004-04-09 18:10:03 +00:00
Wayne Davison
3c3791e8be Use AC_HEADER_MAJOR for better makedev/major/minor determination. 2004-04-09 18:09:16 +00:00
Wayne Davison
c39d6514ab Include <sys/mkdev.h> if it exists. 2004-04-09 17:59:50 +00:00
Wayne Davison
1cb6f3bf4d Added sys/mkdev.h to the searched-for headers. 2004-04-09 17:56:58 +00:00
Wayne Davison
f09dc86ab6 Added a couple extra character devices to be copied. 2004-04-09 00:36:45 +00:00
Wayne Davison
f26ac1e8cb If we're listing a device, output the major and minor device numbers. 2004-04-09 00:33:34 +00:00
Wayne Davison
84a3efa0ab Simplify the setting of rdev & rdev_high in send_file_entry(). 2004-04-08 23:15:39 +00:00
Wayne Davison
00ed4b5bf3 Fixed a bug in the sending of rdev when the high-bits match. 2004-04-08 23:05:36 +00:00
Wayne Davison
e2e053bbd7 Explicitly cast our ~0xFF mask using ~(DEV64_T)0xFF, just to be sure
(sign-extention would have probably made the former work OK).
2004-04-08 21:51:49 +00:00
Wayne Davison
f8b33ab379 Mention the rsync-daemon fix for --sufix=''. 2004-04-07 23:13:02 +00:00
Wayne Davison
5df1fcf245 If --daemon was specified, exit the option-parsing code before
adjusting various default values (the real defaults will get
set when the client's options arrive).
2004-04-07 23:09:14 +00:00
Wayne Davison
b1ad6a3260 Added a couple missing items. 2004-04-05 15:05:46 +00:00
Wayne Davison
6442ccc606 Decided against "Source root" in the exclude/include examples. 2004-04-03 20:47:54 +00:00
Wayne Davison
b21813060c Mentioned the CoW improvement and got rid of a bug-fix mention that
was for a bug introduced during the 2.6.1 developement.
2004-04-03 18:13:51 +00:00
Wayne Davison
706c75307a Use getaddrinfo() to figure out if a numeric address is IPv4 or IPv6. 2004-04-01 21:39:35 +00:00
Wayne Davison
2b284ee33d Last of the cleanup before the patching starts. 2004-04-01 21:08:24 +00:00
Wayne Davison
4cfa6156e3 A couple more minor twiddles. 2004-04-01 20:56:50 +00:00
Wayne Davison
c1e7217fcb Updated the sizeof syntax and trimmed some trailing whitespace. 2004-04-01 20:53:39 +00:00
Wayne Davison
4b2f6a7c37 Decided to use "nobody" instead of "guest". 2004-04-01 18:05:40 +00:00
Wayne Davison
a8726d2a06 Some more IOERR_VANISHED support. 2004-04-01 18:04:59 +00:00
Wayne Davison
b5ebe6d9c7 Improved the include/exclude example section some more. Document
the new username default of "guest" if neither USER or LOGNAME is
set in the environment.
2004-03-31 18:53:57 +00:00
Wayne Davison
ef383c0d32 The auth_client function must not return without outputting something
on the socket, so a NULL or empty username now defaults to "guest".
2004-03-31 18:52:38 +00:00
Wayne Davison
8dcf93356e Don't complain about a null --suffix if we're the server/sender (since
we might not have received the --backup-dir path from the client).
2004-03-31 17:02:22 +00:00
Martin Pool
ce5f2732e4 I'm no longer maintaining this. Tell people to use the lists instead. 2004-03-31 02:48:47 +00:00
Wayne Davison
3e89da86df The --files-from option needs to allow a server-sender to sometimes
have just 1 arg on the command-line.
2004-03-30 02:08:07 +00:00
Wayne Davison
f5450e791d Try to avoid running on a system that allows us to create devices
without being root (like cygwin) because rsync won't copy the
devices if it is not root.
2004-03-29 17:02:31 +00:00
Wayne Davison
cb984e620e In sigchild_handler(), finish with waitpid() before reinitializing
the SIGCHLD handling.
2004-03-29 16:30:53 +00:00
Wayne Davison
be92ac6c36 Added one more example to the new include/exclude section to show how
--relative works with a non-absolute path.
2004-03-27 20:04:04 +00:00
Wayne Davison
5dc6e9c9ca Mention that certain options treat an absolute path as relative to the
module's "path" dir, even when chroot is off.
2004-03-27 19:47:27 +00:00
Wayne Davison
0b79c324ca Improved the "relative to the destination dir" description for
several options.
2004-03-27 19:46:28 +00:00
Wayne Davison
f39b6638f6 Got rid of debug-output statement. 2004-03-27 19:42:13 +00:00
Wayne Davison
a4b6f30579 Try to make the complexities of includes/excludes a little more clear. 2004-03-27 18:25:41 +00:00
Wayne Davison
7be73df4e7 Optionally sanitize the args in parse_arguments() using the new
alloc_sanitize_path() function.
2004-03-27 09:46:42 +00:00
Wayne Davison
14b61c63f0 Added alloc_sanitize_path(). 2004-03-27 09:44:49 +00:00
Wayne Davison
75a64762c2 The args are now sanitized in parse_arguments() instead of here. 2004-03-27 09:44:01 +00:00
Wayne Davison
028fdddb49 Fixed a crash bug when hlink_list is NULL and a link_u.links
pointer in one of the file_struct nodes is not.
2004-03-26 16:46:20 +00:00
Wayne Davison
f86b0f2e7b Fixed a typo and made a sentence read better. 2004-03-26 15:51:51 +00:00
Wayne Davison
285fba0759 Preparing for release of 2.6.1pre-1 2004-03-24 21:59:07 +00:00
Wayne Davison
92b9eb978e Moved a few externs and made a couple formatting tweaks. 2004-03-23 16:50:40 +00:00
Wayne Davison
1e82e2cea6 Got rid of an ancient (and no longer relevant) comment. 2004-03-23 16:36:00 +00:00
Wayne Davison
a7ed6ca618 A few formatting tweaks in delete_file(). 2004-03-23 16:16:15 +00:00
Wayne Davison
b4b90120ff Fixed the test for sin_len as noted by Shinichi Maruyama. Changed
the define name generated for this test and the sa_len test.
2004-03-16 01:26:39 +00:00
Wayne Davison
16f72adc49 Changed HAVE_SOCKADDR_SIN_LEN to HAVE_SOCKADDR_IN_LEN. 2004-03-16 01:26:31 +00:00
Wayne Davison
3d06165389 Check robust_rename()'s return value using < 0. 2004-03-13 20:18:03 +00:00
Wayne Davison
fd4893155d Mention the changes in the "patches" dir. 2004-03-10 08:32:38 +00:00
Wayne Davison
67e78a8231 Use CHMOD_BITS instead of ~_S_IFMT. 2004-03-07 20:29:59 +00:00
Wayne Davison
6b320e4045 Improved an entry. 2004-03-06 20:07:24 +00:00
Wayne Davison
7e5cb90983 Other files use S_IWUSR instead of S_IWRITE, so use S_IWUSR and S_IRUSR. 2004-03-06 07:45:52 +00:00
Wayne Davison
8120a98f47 Define S_IRUSR if it doesn't already exist. 2004-03-06 07:43:55 +00:00
Wayne Davison
8f3f8eec08 Updated to version from autoconf 2.59 (2003-10-03). 2004-03-06 07:00:47 +00:00
Wayne Davison
386b93dc60 Updated to version from autoconf 2.59 (2003-08-18). 2004-03-06 07:00:16 +00:00
Wayne Davison
b3bc31102c Moved out the old news and improved the new. 2004-03-04 19:36:28 +00:00
Wayne Davison
0f1aa0d3e5 Moved the previous release's NEWS here. 2004-03-04 19:35:57 +00:00
Wayne Davison
7a08ae31d2 Progress improvement. 2004-02-28 02:02:37 +00:00
Wayne Davison
304f127f56 Improved the progress reporting/E.T.A. using a (slightly modifed)
patch from Timo Sirainen.
2004-02-28 02:00:57 +00:00
Wayne Davison
c338460d66 Got rid of some superfluous parens. 2004-02-27 08:03:49 +00:00
Wayne Davison
48d704af52 Tru64 fix. 2004-02-27 07:37:43 +00:00
Wayne Davison
ac7aa92290 Use new HAVE_SOCKADDR_SIN_LEN define (replaces HAVE_SOCKADDR_LEN). 2004-02-27 07:22:40 +00:00
Wayne Davison
0042f81894 We now set HAVE_SOCKADDR_SA_LEN and HAVE_SOCKADDR_SIN_LEN based on
sockaddr.sa_len and sockaddr.sin_len, respectively (replacing
HAVE_SOCKADDR_LEN).
2004-02-27 07:22:39 +00:00
Wayne Davison
2c836acb37 No longer needed. 2004-02-26 04:03:44 +00:00
Wayne Davison
a1d8f29a3d A couple AC_DEFINE() changes so that we can do without acconfig.h. 2004-02-26 04:03:35 +00:00
Wayne Davison
a174e1ed0f Tweaked some comments and some whitespace. 2004-02-25 21:20:59 +00:00
Wayne Davison
530adb7625 Configure addition. 2004-02-23 20:09:14 +00:00
Wayne Davison
cd3fe9fb03 Allow the default (system) rsyncd.conf file to be specified via configure. 2004-02-23 20:00:20 +00:00
Wayne Davison
a8edfd53d1 Trivial whitespace tweak. 2004-02-23 19:23:53 +00:00
Wayne Davison
dbb665180c Shouldn't ignore .cvsignore. 2004-02-23 18:19:13 +00:00
Wayne Davison
9d78ed31a7 A couple fixes from Shinichi Maruyama. 2004-02-23 07:03:03 +00:00
Wayne Davison
89afe532d7 Mentioned the recent change in slash handling. 2004-02-23 02:28:04 +00:00
Wayne Davison
c67d13866b Changed the literal 9000 into "OPT_REFUSED_BASE". 2004-02-22 08:56:43 +00:00
Wayne Davison
3b98b08c4d Another bug fix. 2004-02-21 21:39:54 +00:00
Wayne Davison
9c15534511 Got rid of the "refuse options" section. 2004-02-21 21:37:14 +00:00
Wayne Davison
55afbb522c Complain in the daemon log file if there is an unknown option in the
"refuse options" value.  Also changed the idiom used to mark refused
options in the popt struct.
2004-02-21 21:36:55 +00:00
Wayne Davison
27ed20f7a0 Fixed the "refuse options" setting in the daemon after Fabrice Bellet
identified what was wrong.
2004-02-21 21:12:49 +00:00
Wayne Davison
f567e9b3d7 - Guard against and out-of-memory condition.
- Don't use the NGROUPS_MAX define.
2004-02-20 17:09:30 +00:00
Wayne Davison
40ae4f93a0 Don't use NGROUPS_MAX define. 2004-02-20 17:01:33 +00:00
Wayne Davison
7a27e9b599 Don't use ENOMSG -- it's not portable. 2004-02-18 22:33:21 +00:00
Wayne Davison
62c9e6b3a5 Moved the EXDEV handling into robust_rename(). 2004-02-17 23:13:10 +00:00
Wayne Davison
cfeed4da95 - If we return an error because of dry_run being set, we now set errno.
- The do_mkstemp() routine now preserves the errno value from fchmod()
  if that call fails.
- Improved the CHECK_RO macro stuff.
2004-02-17 23:00:00 +00:00
Wayne Davison
4068d8617d We no longer munge a double-leading slash in do_open() because we
shouldn't generate a path with a double-leading slash anymore.
2004-02-17 22:49:19 +00:00
Wayne Davison
421c2a2448 Don't create a pathname that has two leading slashes (which we used
to do when the root of the transfer was "/").
2004-02-17 21:57:44 +00:00
J.W. Schultz
d1e7726460 Remove "Conditional -z for old protocols" because those old
protocols are no longer supported.
2004-02-14 01:43:24 +00:00
Wayne Davison
0596df00b3 Reordered the items inside the file_struct so that alignment padding
should be minimized.
2004-02-11 08:01:21 +00:00
Wayne Davison
417c99f637 If --backup was specified, the links we remove are backed up. 2004-02-11 05:03:04 +00:00
Wayne Davison
de0e225076 - Revised and optimized the directory-making code.
- Optimized the keep_backup() code.
2004-02-11 05:02:21 +00:00
Wayne Davison
e0391f8149 Added backup_dir_buf and backup_dir_remainder. 2004-02-11 04:30:41 +00:00
Wayne Davison
7de2483fbd Fixed a crash bug when keep_backup() calls make_file() and the lastdir
pointer is no longer valid.
2004-02-11 02:48:58 +00:00
Wayne Davison
65d6212d03 Got rid of hard-link message (since I don't think it was ever
output in older rsync versions).
2004-02-11 02:33:17 +00:00
Wayne Davison
4d4df3cd2b Another attempt at measuring the minimum alignment for a system. 2004-02-10 23:35:12 +00:00
J.W. Schultz
62125b10c9 Simplified test for hardlink in make_backup debug message to
avoid core-dump.
2004-02-10 23:23:09 +00:00
Wayne Davison
81c3a3a86e Got rid of useless extern. 2004-02-10 22:56:16 +00:00
Wayne Davison
61d35e1844 Trying a different MINALIGN because of core dumps on the sparc-64
build-farm machines.
2004-02-10 22:28:36 +00:00
J.W. Schultz
15f85b1f63 Revert pool_alloc's use of bomb if pool == NULL. 2004-02-10 21:11:24 +00:00
J.W. Schultz
5bf63a11f4 Keep in sync with protocol if idev data on stream but no hlink_pool. 2004-02-10 21:11:24 +00:00
Wayne Davison
97a67bdfa9 If XMIT_HAS_IDEV_DATA is set in receive_file_entry(), we now bomb out
if flist->hlink_pool isn't set (instead of neglecting to read the idev
info).
2004-02-10 17:53:52 +00:00
Wayne Davison
aa0b9ca174 If we call pool_alloc() on a NULL pool, bomb out with an error. 2004-02-10 17:52:31 +00:00
Wayne Davison
b96efc2f67 Empty-line tweaks. 2004-02-10 17:35:04 +00:00
Wayne Davison
be20dc3448 Changed a while loop to a for loop. 2004-02-10 17:34:05 +00:00
Wayne Davison
cb869c26d9 Tweaked an if. 2004-02-10 17:28:59 +00:00
Wayne Davison
7cf8e8d05d Changed flist_init() to use offsetof(). 2004-02-10 17:28:31 +00:00
Wayne Davison
54fd3e5020 Added lib/pool_alloc.h to the HEADERS. 2004-02-10 17:06:11 +00:00
J.W. Schultz
3e4916822d Dropped support for protocol versions less than 20 (2.3.0
released 15 Mar 1999) and activated warnings for protocols
less than 25 (2.5.0 released 23 Aug 2001)
2004-02-10 03:54:47 +00:00
J.W. Schultz
7efdcf3218 Added allocation pool code. 2004-02-10 03:26:41 +00:00
J.W. Schultz
9935066b70 Make idev, hlink and file_struct + strings use allocation
pools.
2004-02-10 03:23:37 +00:00
Wayne Davison
6c2e5b56e4 Die if we overflowed the args[] array when building up the remote
command in do_cmd().
2004-02-09 21:22:59 +00:00
Wayne Davison
2289bf64cc The batch-options now set checksum_seed to the appropriate fixed value. 2004-02-09 18:32:54 +00:00
Wayne Davison
b1bf649cba Set checksum_seed only if it is still zero. 2004-02-09 18:32:53 +00:00
Wayne Davison
8ee6eb7134 Made checksum_seed an extern. 2004-02-09 18:32:52 +00:00
Wayne Davison
f98c60bfa8 Use asprintf() in server_options() (plus a few more whitespace tweaks). 2004-02-09 18:10:57 +00:00
Wayne Davison
a5c1113971 Updated the sizeof syntax and tweaked some whitespace. 2004-02-09 17:45:22 +00:00
Wayne Davison
736f46d1d9 Got rid of unused true/false defines. 2004-02-07 18:40:52 +00:00
Wayne Davison
a8f7e4b835 Made a couple comments a little clearer. 2004-02-07 00:12:40 +00:00
Wayne Davison
9352b0649b Got rid of unused string_area struct. 2004-02-06 15:33:15 +00:00
J.W. Schultz
a85906c756 Start flist with a more reasonable size, grow it linearly
once it reaches a largish size (16 million files) and make it
actually match the comments so it may be used to initialize
flists of known size (create_flist_from_batch()).
2004-02-06 10:00:33 +00:00
J.W. Schultz
8aa81e06e6 Update TODO to reflect recent changes.
Hardlink handling is improved.

	String area code is gone for other reasons.
2004-02-06 07:26:15 +00:00
Wayne Davison
1f9ae80a3e Fixed the indentation in init_flist(). 2004-02-06 07:19:57 +00:00
J.W. Schultz
71020fc3aa Correct sizeof usage and other whitespace. 2004-02-06 04:51:09 +00:00
J.W. Schultz
7b74bba15e Added a total memory allocated (allmem) line to
show_malloc_stats.
2004-02-06 01:56:25 +00:00
J.W. Schultz
e5fbaa713a Cause all three processes to report memory stats when -vv --stats 2004-02-05 03:27:54 +00:00
Wayne Davison
6609a9f17e Mention a couple more changes. 2004-02-05 02:56:57 +00:00
Wayne Davison
5204e853e1 Now that the long-standing chgrp bug is fixed, go back to -vvv from -vvvv. 2004-02-05 01:37:08 +00:00
Wayne Davison
01363a24e2 Fixed a problem handling GID_NONE in match_gid(). 2004-02-05 01:32:38 +00:00
Wayne Davison
d49def4832 - Fixed a bug using --numeric-ids as non-root when the receiver
does not have permissions to set one or more of the gids.
- If the add_[ug]id() routine couldn't find a name for an ID, we
  still note the ID in our list of IDs so that we don't try to
  look it up again (and again).  (The name-less IDs are stripped
  when sending the IDs from the sender to the receiver.)
- Created a better add_to_list() function that handles the linking
  of the new node into the list (rather than the caller doing it).
- Added new internal functions for some receiver-side work that
  needed to be done in multiple places (the recv_add_[ug]id()
  functions).
- We output debug info even for ID mappings that have no names.
  This make the list complete and also notes which gids get
  mapped to -1 (GID_NONE).
- Turned several while loops into for loops.
2004-02-05 01:07:23 +00:00
Wayne Davison
4836c3eece Added new extern. 2004-02-05 00:46:32 +00:00
Wayne Davison
9f7b8c3b8f Only call add_uid() or add_gid() if numeric_ids is not set. 2004-02-05 00:44:11 +00:00
Wayne Davison
ade7292aee Moved a function. 2004-02-04 20:09:21 +00:00
Wayne Davison
dbd8811b85 If a gid doesn't have a name on the originating system, the receiver
won't see it in the list of IDs to remap.  That means that we need to
call the is_in_group() function from inside match_gid() to know if we
can set the group or not (if we're not root).
2004-02-04 19:25:11 +00:00
Wayne Davison
05118158f4 Improved the trailing comment. 2004-02-04 18:24:41 +00:00
Wayne Davison
1df395f7c2 Use the new HAVE_GETGROUPS define. 2004-02-04 17:49:36 +00:00
Wayne Davison
5fdf2e7063 Added function check for getgroups. 2004-02-04 17:21:48 +00:00
Wayne Davison
6fe05820ff Use MY_UID() instead of getuid(). 2004-02-04 17:06:07 +00:00
Wayne Davison
670d8abf80 Use MY_GID() instead of getgid(). 2004-02-04 17:05:44 +00:00
Wayne Davison
b2bffbb2ca Added two defines: MY_UID() and MY_GID(). 2004-02-04 17:04:58 +00:00
Wayne Davison
13a6d667d2 Added getegid to the functions we check. 2004-02-04 16:45:26 +00:00
Wayne Davison
1be77f8336 Added geteuid to the functions to check. 2004-02-04 16:33:34 +00:00
Wayne Davison
187e9c24f1 Another improvement to the debug info we output. 2004-02-04 16:27:47 +00:00
Wayne Davison
eddeaf76f8 Set the "max verbosity" global to 9. 2004-02-04 07:32:48 +00:00
Wayne Davison
33e9d10d2a Use the new lp_max_verbosity() value to limit the server's "verbose"
value.
2004-02-04 07:32:12 +00:00
Wayne Davison
46f7dc3bf6 Added "max verbosity" global parameter that allows you to configure
a higher debug level instead of the default of level-l verbosity.
2004-02-04 07:31:29 +00:00
Wayne Davison
555b0e20f7 Tweaked the new debug-logging strings. 2004-02-04 07:24:13 +00:00
Wayne Davison
a57dfe710d Turned on 4 -v options for some build-farm testing. 2004-02-04 06:15:24 +00:00
Wayne Davison
53adbd7a3d If we encounter an error, output the rsyncd.log file, if it exists. 2004-02-04 05:34:29 +00:00
Wayne Davison
17f033b725 Temporarily switch to 4 -v options. 2004-02-04 03:58:19 +00:00
Wayne Davison
cefed3e8dc Delay the output the (verbose > 3) list of files until we've had a
chance to map the uid/gid info in the receiver.
2004-02-04 03:52:51 +00:00
Wayne Davison
84fa865c0c Output some debug info if verbose > 3. 2004-02-04 03:50:16 +00:00
Wayne Davison
f05f993eb7 If we're dumping the file list (i.e. verbose > 3), mention the uid and/or
gid (depending on applicability).
2004-02-04 03:28:22 +00:00
Wayne Davison
e90cdb8adf Changed the -x code to allow -L to copy a file on another filesystem
that is pointed to by a symlink on our exclusive filesystem.
2004-02-04 03:25:18 +00:00
Wayne Davison
4250941710 Fixed a dropped '-'. 2004-02-04 03:01:32 +00:00
Wayne Davison
a2687b64a2 Added a little more compatibility code for non-standard systems. 2004-02-03 23:28:19 +00:00
Wayne Davison
c284f34a49 Some indentation fixes and the removal of some superfluous parens. 2004-02-03 23:04:25 +00:00
Wayne Davison
5f5be796b0 Changed a couple sizeof calls and improved some string handling in
the {send,recv}_exclude_list() calls.
2004-02-03 23:01:58 +00:00
Wayne Davison
5cb374364b Modified sizeof usage and eliminated trailing whitespace. 2004-02-03 22:48:32 +00:00
Wayne Davison
f15256e156 Added some temporary code to try to figure out what is going wrong
on one NetBSD box in our build farm.
2004-02-03 20:01:26 +00:00
Wayne Davison
ce37eb2d83 If verbose > 2, mention it if we're setting the uid or the gid. 2004-02-03 20:00:35 +00:00
J.W. Schultz
0d6e308b51 correct sizeof usage. 2004-02-03 06:21:56 +00:00
Wayne Davison
b1dab2363a Made hard-link sending compatible with pre-28 protocols again. 2004-02-03 04:21:15 +00:00
J.W. Schultz
bd6abc4939 Corrected sizeof usage:
sizeof obj
	sizeof (type)
2004-02-03 03:42:49 +00:00
Wayne Davison
96eeda0324 Fix for memset bug found by buildfarm. 2004-02-02 22:35:07 +00:00
Wayne Davison
4c4266d9c9 Change to try to debug a failure on the build farm. 2004-02-02 22:18:23 +00:00
Wayne Davison
54e87b4b06 Don't warn about lack of -l support if we're the sender -- we just won't
send the receiver any symlinks.
2004-02-02 21:33:10 +00:00
Wayne Davison
44e9e221f3 - Call init_flist().
- Got rid of the symbolic-links-warning code (it was not right, and it is
  now handled in options.c).
2004-02-02 21:33:06 +00:00
Wayne Davison
61dec11ae0 - Use as little memory as possible for the file_struct (saves another 3
bytes per file).
- Made the idev struct allocated by the group-malloc again (J.W. suggested
  the proper way to align it for all systems).
- Added init_flist().
2004-02-02 21:33:03 +00:00
Wayne Davison
5009de7d2d Added comment about the position of file_list's "flags" var. 2004-02-02 21:32:56 +00:00
Wayne Davison
67f3feebcb Don't free link_u.idev. 2004-02-02 21:32:52 +00:00
Wayne Davison
b22260749f Use "%H:%M:%S" instead of "%T" in strftime() call since it looks to be
more portable.
2004-02-02 21:02:13 +00:00
Wayne Davison
06d76beb28 Clarify the safe/unsafe symlink options in the usage text. 2004-02-02 18:25:37 +00:00
Wayne Davison
7af4227ac2 Clarify the various safe/unsafe symlink options. 2004-02-02 18:23:09 +00:00
Wayne Davison
9312b7325e Go back to using malloc() for the hard-link data structure (for now
at least).
2004-02-02 07:06:54 +00:00
Wayne Davison
c6edb381f5 Free the hlink data again. 2004-02-02 07:06:50 +00:00
Wayne Davison
a1d55ad095 Make sure that the idev struct's data is 4-byte aligned. 2004-02-02 06:52:49 +00:00
Wayne Davison
a289addd96 - Changed the file-list allocation to alloc all the memory we need
with one call, not with several mallocs and strdups.
- Got rid of string_area() stuff (as suggested in the "@todo").
- Enhanced free_file() to optionally free the whole struct or to
  clear it (since we don't need to do both).
- Don't zero out the other flist data when we're about to free it.
2004-02-02 05:06:36 +00:00
Wayne Davison
13c5b46361 Don't free the hlink data (it is not separately allocated anymore). 2004-02-02 05:06:35 +00:00
Wayne Davison
f3af206d8d Changed args to make_file() and free_file(). 2004-02-02 05:06:34 +00:00
Wayne Davison
df0054ab13 Added CLEAR_STRUCT and FREE_STRUCT defines. 2004-02-02 05:06:33 +00:00
Wayne Davison
0d162bd17c Added some missing #if SUPPORT_HARD_LINK and #if SUPPORT_LINK directives. 2004-02-01 17:37:14 +00:00
Wayne Davison
e1add89334 - Fixed the bug where the --daemon option would squelch all option errors
for later parameters.
- Complain if someone passes us -l and we don't support symlinks.
2004-02-01 17:29:41 +00:00
Wayne Davison
22d49dc429 Changed the rdev code to have both an "rdev" variable (which always
has the full device value) and an "rdev_high" variable (which zeros
the lower byte in the last rdev value).
2004-02-01 16:28:31 +00:00
Wayne Davison
1aa4caf318 One more improvement to the 0-flag-byte avoidance algorithm. 2004-01-31 22:40:55 +00:00
Wayne Davison
306ffb8c71 A small optimization to the symlink-send code, and an extra sanity
check to the symlink-receive code.
2004-01-31 21:01:01 +00:00
Wayne Davison
0a98201164 Fixed the test to ensure that we don't send a flag-byte of 0 to the
receiver when transferring the file list.
2004-01-31 20:24:52 +00:00
Wayne Davison
e0870f1d7a One more minor variable-name change. 2004-01-31 11:36:03 +00:00
Wayne Davison
1923b1fce4 Switched a buffer name in make_file() to make the code a little more
similar to what is in receive_file_entry().
2004-01-31 11:32:30 +00:00
Wayne Davison
5dc4003e63 Fixed the optional sanitization of the files_from arg. 2004-01-30 16:14:46 +00:00
Wayne Davison
37c817eb81 OK, "find ... -print0 | xargs -0 ..." wasn't portable. This is. 2004-01-28 01:39:29 +00:00
Wayne Davison
284d628a7c Got rid of indeterminacy in the overlapping-files. 2004-01-28 00:37:55 +00:00
Wayne Davison
ff3184ca1e A couple more unsigned char changes to silence compiler warnings
on signed-char systems (like Solaris).
2004-01-28 00:04:57 +00:00
Wayne Davison
12865a9762 New test to make sure that merging files from multiple directories
continues to work.
2004-01-27 23:56:00 +00:00
Wayne Davison
ea847c6232 Use who_am_i() to qualify some debug messages. 2004-01-27 23:13:15 +00:00
Wayne Davison
b695f2423d Set the am_generator flag. Use who_am_i(). 2004-01-27 23:13:14 +00:00
Wayne Davison
c3e5e5851b New function: who_am_i() returns "sender", "receiver", or "generator". 2004-01-27 23:13:13 +00:00
Wayne Davison
4337c8f856 Added "am_generator". 2004-01-27 23:13:12 +00:00
Wayne Davison
4c7e46079d Don't free lastdir! It is still needed by the flist basedir pointers.
Also, output the basedir pointer when dumping the flist for debugging.
2004-01-27 23:00:47 +00:00
Wayne Davison
72a6e63136 Relocated the externs. 2004-01-27 22:35:15 +00:00
Wayne Davison
37101856a6 Silenced some compiler warnings. 2004-01-27 16:27:05 +00:00
Wayne Davison
65fc84b32e Better pid handling. 2004-01-27 08:14:33 +00:00
Wayne Davison
45e08edb08 Cast getpid() to a long for output. 2004-01-27 08:02:31 +00:00
Wayne Davison
05b7bab8e1 Better pid handling. 2004-01-27 07:57:12 +00:00
Wayne Davison
904817552d Fixed a comment. 2004-01-27 07:48:57 +00:00
Wayne Davison
6e195fe975 Tweaked the externs. 2004-01-27 07:48:19 +00:00
Wayne Davison
3eaf615f40 Percentage of file-count output was off by one. 2004-01-27 06:51:39 +00:00
J.W. Schultz
6156e72f85 EXCLUDE PATTERNS is not just about syntax. 2004-01-27 05:00:43 +00:00
Wayne Davison
73a4bdfd77 Mention the latest -x improvement. Also improved the description of
one of my previous fixes.
2004-01-27 03:49:54 +00:00
Wayne Davison
4844449a5d Optimized the -x option by removing the skip_filesystem() call and using the
new FLAG_MOUNT_POINT flag.
2004-01-27 01:47:41 +00:00
Wayne Davison
ae289aec1e Added FLAG_MOUNT_POINT. 2004-01-27 01:47:40 +00:00
Wayne Davison
9e4c32ea54 Tweaked a comment. 2004-01-27 01:27:37 +00:00
Wayne Davison
a5f9cff256 Improved the differentiation of the transmit flags from the live flags
by naming the transmit flags with an XMIT_ prefix.  Improved the names
of two other flags, got rid of the LIVE_FLAGS mask, and shortened the
flag storage in the flist struct (to save memory).
2004-01-27 01:05:14 +00:00
Wayne Davison
d01d15e096 Use the new names for the transmit-flag defines. We also make sure
that the FLAG_TOP_DIR flag doesn't get set in the live data for a
non-directory (when it's used as a kluge to prevent a 0x00 byte being
sent over the wire for the flag data).
2004-01-27 01:05:13 +00:00
Wayne Davison
a53426441b Use the new names for the transmit-flag defines. 2004-01-27 01:05:12 +00:00
Wayne Davison
5d1966948e Fixed reference to -u that should have been -o. 2004-01-26 22:35:04 +00:00
J.W. Schultz
f673ea84b2 Back out bad refactor (thanks Wayne) 2004-01-26 20:54:02 +00:00
Wayne Davison
64f21c31bf Mention new hard-link optimization. 2004-01-26 04:21:59 +00:00
Wayne Davison
520cf41711 Added defines (FLAG_HLINK_EOL, HL_CHECK_MASTER, and HL_SKIP) and changed
the struct hlink to have an index into the hlink_list[] array instead of
a head pointer.
2004-01-25 22:32:11 +00:00
Wayne Davison
d38fc30563 We now link the hard-linked flist entries into a circular list, mark
the last item with FLAG_HLINK_EOL, and save off an index for our
master entry in the hlink_list[] array.  Added the hard_link_check()
function.
2004-01-25 22:32:10 +00:00
Wayne Davison
6dff599288 Use the new hard_link_check() function to figure out which one of the
hard-linked files to send (when -H was specified, of course).  Moved
the call to do_hard_links() and the final directory-permissions scan
into generate_files() from recv_files().
2004-01-25 22:32:09 +00:00
Wayne Davison
f746dda0a0 Moved the call to do_hard_links() and the final directory-permissions
scan from recv_files() into generate_files().
2004-01-25 22:32:08 +00:00
Wayne Davison
91a1e147ae Changed F_HEAD to F_HLINDEX. 2004-01-25 22:32:07 +00:00
Wayne Davison
40da904230 Tweaked a comment. 2004-01-25 22:32:05 +00:00
J.W. Schultz
34fada3012 Tightened up code in skip_filesystem() 2004-01-25 22:11:09 +00:00
Wayne Davison
f91e01d9a5 Replaced an snprintf() call with pathjoin(). 2004-01-24 22:12:58 +00:00
Wayne Davison
3048b0a8ea The static last_in value in match_gid() needed to default to -2 so
that we don't accidentally return a GID of 0 when we don't have the
permissions to set it.
2004-01-24 18:36:36 +00:00
Wayne Davison
d99b4ccf93 Another improvement in the "use chroot" section. 2004-01-24 01:48:12 +00:00
Wayne Davison
58811a0a38 Refer to I/O (not IO), ID (not id), and "an rsync" (not "a rsync"). 2004-01-23 16:58:24 +00:00
Wayne Davison
cb290916be Improved the "use chroot" discussion on ID mapping. 2004-01-23 16:55:40 +00:00
Wayne Davison
a2b0471f1d More changes to make the --owner and --group items clearer. 2004-01-23 16:40:17 +00:00
Wayne Davison
bb18e7550c Use "an" in front of rsync, not "a". 2004-01-23 09:34:04 +00:00
Wayne Davison
db2b5cb75f Tweaked the --help text to refer to I/O (not IO) and use "an" in
front of rsync (not "a").
2004-01-23 09:32:50 +00:00
Wayne Davison
fa8c787d8b Improved the "use chroot" section to mention how to get user/group
preservation by name (getting rid of the erroneous bit about the
--numeric-ids option being implied).
2004-01-23 09:30:45 +00:00
Wayne Davison
ec40899bb9 Improved comments on --owner and --groups, and removed misinformation
on a chroot daemon (it does not imply --numeric-ids).
2004-01-23 09:29:16 +00:00
Wayne Davison
b5accabaa7 Properly punctuate "etc." and changed all occurrences of "IO" to "I/O". 2004-01-23 08:59:19 +00:00
Wayne Davison
4e308a9526 Fixed two more misspelled words. 2004-01-23 02:02:51 +00:00
Wayne Davison
4d88810810 Some spelling corrections and other simple fixes. 2004-01-23 01:36:59 +00:00
Wayne Davison
f321922214 When setting an flist entry's flags, mask it with LIVE_FLAGS. 2004-01-22 18:39:32 +00:00
Wayne Davison
cab13afe8d A couple comment tweaks. 2004-01-22 18:37:26 +00:00
Wayne Davison
72fc7ec59b Made the getgroups() code a little more portable. This will hopefully
make the chgrp test work on the NetBSD and OpenBSD systems where it is
failing.
2004-01-22 09:16:21 +00:00
Wayne Davison
58743a87b8 Improved to add the default gid if it is missing from the list. 2004-01-22 09:13:36 +00:00
Wayne Davison
54bf456e85 Removed an obsolete comment. 2004-01-22 09:05:09 +00:00
Wayne Davison
a24639bb36 Tweaked an argv-type variable so that it's a little clearer what
the code is doing.  Also added a comment.
2004-01-22 04:40:33 +00:00
Wayne Davison
3fef53645d Use the new f_name_to() calling syntax. 2004-01-22 04:38:18 +00:00
Wayne Davison
882e689312 - Ensure in make_file() that we can't make a name that overflows
our buffers (note that receive_file_entry() already does this).
- Changed f_name_to() to not do any length checking since it is
  now redundant.
2004-01-22 04:38:17 +00:00
Wayne Davison
b0a93231cf Added more missing news. 2004-01-22 02:02:00 +00:00
Wayne Davison
0c819b76d6 New news. 2004-01-22 01:23:43 +00:00
Wayne Davison
ce58b1b479 Size-check the --temp-dir string so we don't have to worry about it
overflowing elsewhere in the code.
2004-01-22 01:20:24 +00:00
Wayne Davison
a16d8f2b25 Improved a couple comments. 2004-01-21 02:45:10 +00:00
Wayne Davison
59187666b9 Use new push_dir() syntax. 2004-01-20 17:46:31 +00:00
Wayne Davison
808c57c343 - Use the new push_dir() and pop_dir() calling syntax.
- The "olddir" handling changed to accommodate the above, and to
  avoid using malloc()/free().
2004-01-20 17:46:30 +00:00
Wayne Davison
4af8fe4e78 - Changed push_dir() to not take a "save" arg and to return 1 or 0
for success or failure instead of a string pointer.  The function
  also ensures that we don't overflow the curr_dir[] buffer.
- Changed pop_dir() to not free() anything and to return 1 or 0
  for success or failure.
2004-01-20 17:46:29 +00:00
Wayne Davison
4034cb3f71 Use new stringjoin() function. 2004-01-20 05:35:57 +00:00
Wayne Davison
6fc048f438 Find last '@' in the user@site string, just in case the username has
a '@' in it.
2004-01-20 05:27:09 +00:00
Wayne Davison
5d2a707139 Use new stringjoin() and pathjoin() functions. 2004-01-20 05:24:07 +00:00
Wayne Davison
81d2b0ef9d Use new pathjoin() function. 2004-01-20 05:15:14 +00:00
Wayne Davison
248ed45fc6 Use new pathjoin() function. 2004-01-20 05:09:36 +00:00
Wayne Davison
893c4cc056 Use new stringjoin() function. 2004-01-20 04:56:20 +00:00
Wayne Davison
a7725e6df9 Use new pathjoin() function. 2004-01-20 04:53:59 +00:00
Wayne Davison
368ad70e05 Added stringjoin() and pathjoin(). 2004-01-20 04:43:49 +00:00
J.W. Schultz
b7cee9498b Eliminate unneeded strlen after strlcpy. 2004-01-20 03:37:04 +00:00
Wayne Davison
72d45525d2 Make sure that strlcpy() returns the right value when the bufsize is 0. 2004-01-20 00:59:26 +00:00
Wayne Davison
1fb8ec4b0d Fixed a bug in strlcat() where it would not properly detect a no-change
condition if called with an initial string longer than the specified
size limit (due to an unsigned var's inability to go negative).
2004-01-20 00:29:49 +00:00
Wayne Davison
beb9368481 Make sure that the batch-prefix string isn't overly long (avoiding
a potential problem in the batch-filename code).
2004-01-19 23:33:02 +00:00
Wayne Davison
981555bddb Actually, let's avoid snprintf() where possible. 2004-01-19 23:28:57 +00:00
Wayne Davison
9c7527085c Use snprintf() instead of strlcpy()+strlcat(). 2004-01-18 21:22:49 +00:00
Wayne Davison
eddd5d129e A few minor string optimizations and a new complaint if we try to
send a truncated filename.
2004-01-17 19:45:26 +00:00
Wayne Davison
26f76b7912 Got rid of an extra call to io_start_buffering_out(). 2004-01-17 05:04:04 +00:00
Wayne Davison
32eda0961e Unified the externs. 2004-01-17 04:58:24 +00:00
Wayne Davison
66964002df A fix for --cvs-exclude. 2004-01-17 01:23:41 +00:00
Wayne Davison
57469f6c31 Items read from a per-directory .cvsignore file should be added to the
local_exclude_list, not the exclude_list.
2004-01-17 01:16:49 +00:00
Wayne Davison
13c7bcbb2b Output an error before we die if we get a wacko message from the receiver. 2004-01-16 16:31:47 +00:00
Wayne Davison
d48c806560 Clarified the --delete-after descriptions. 2004-01-15 17:45:53 +00:00
Wayne Davison
ad1a09a509 Clarified the --delete-after help text. 2004-01-15 17:43:34 +00:00
Wayne Davison
d6631cf3a5 If we're a daemon talking with a pre-28 protocol, use FERROR for a
vanished-file message (not FINFO).
2004-01-15 08:56:33 +00:00
Wayne Davison
5a8543b8b8 In two places: needed to use protocol_version, not PROTOCOL_VERSION. 2004-01-15 08:39:25 +00:00
Wayne Davison
19119cbd35 Changed version to "2.6.1cvs". 2004-01-15 08:16:40 +00:00
Wayne Davison
442743b83c Improved receiver/generator communications. 2004-01-15 07:51:37 +00:00
Wayne Davison
419896af47 - Define FULL_FLUSH and NORMAL_FLUSH.
- Got rid of FNONE from logcode enum.
- Created msgcode enum with MSG_DATA, MSG_REDO, MSG_DONE, etc.
2004-01-15 07:42:27 +00:00
Wayne Davison
0569a1339d - Got rid of the f_gen pipe.
- Use new send_msg() call with MSG_DONE or MSG_REDO.
2004-01-15 07:42:25 +00:00
Wayne Davison
f1e3656ee2 - Call io_flush() with its new FULL_FLUSH/NORMAL_FLUSH arg.
- Got rid of the recv_pipe between the receiver and the generator.
- Use new send_msg(MSG_DONE,...) call to signal the generator
  when the receiver is done.
- Use the new get_redo_num() call in the generator to read the
  final -1 from the receiver.
2004-01-15 07:42:21 +00:00
Wayne Davison
a644fc3cc4 - Moved err_list* stuff to io.c and renamed them to msg_list*.
- Call the new send_msg() function to send a remote log message.
2004-01-15 07:42:19 +00:00
Wayne Davison
d17e1dd2da - Moved the err_list* stuff here from log.c and renamed them msg_list*.
- Renamed log_error_fd to msg_fd_out, and io_error_fd to msg_fd_in.
- Added a redo_list* to keep track of any redo items that come over
  the message channel from the receiver to the generator.
- The io_flush() and msg_list_push() functions now take an arg:
  NORMAL_FLUSH or FULL_FLUSH.  The latter ensures that we don't lose
  any log messages that haven't gotten written from the msg_list.
- Added a send_msg() function that log.c calls to send any remote
  log messages.  It is also called to send the new MSG_REDO and
  MSG_DONE messages.
2004-01-15 07:42:17 +00:00
Wayne Davison
b9b15fb165 We now call get_redo_num() instead of reading f_recv (which was removed). 2004-01-15 07:42:15 +00:00
Wayne Davison
ef732c3b54 Call io_flush() with its new FULL_FLUSH option. 2004-01-15 07:42:12 +00:00
Wayne Davison
baa4212ae1 If the do_lchown() fails and we weren't trying to change the user,
the error now says that chgrp failed, not chown.
2004-01-15 07:08:00 +00:00
Wayne Davison
0be976ec0a Fixed a bug when a non-root user copies a GID=0 file with -g set
and no permissions to set group 0.
2004-01-15 07:06:45 +00:00
Wayne Davison
f7f10340d6 The HAS_INODE_DATA flag is no longer a part of the LIVE_FLAGS define. 2004-01-15 02:25:38 +00:00
Wayne Davison
68f9910d94 Explain the --progress output. 2004-01-13 18:50:40 +00:00
Wayne Davison
fb6e0ea120 Give the user an idea of how far along in the transfer we are
when using --progress.
2004-01-13 18:25:03 +00:00
Wayne Davison
97feb557ed Set stats.current_file_index. 2004-01-13 18:22:43 +00:00
Wayne Davison
dc8293ff73 Added current_file_index. 2004-01-13 18:22:13 +00:00
Wayne Davison
785db4ced0 Merged a couple more f != -1 if sections. 2004-01-13 06:27:30 +00:00
Wayne Davison
5562deb169 Moved a couple externs. 2004-01-13 05:13:57 +00:00
Wayne Davison
983b1ed321 Merged some "if (f != -1)" checks, put the clean_flist() call in the
right spot, and moved some externs.
2004-01-13 05:11:56 +00:00
Wayne Davison
548abf96ce Relocated some externs. 2004-01-13 04:50:45 +00:00
Wayne Davison
f8ebdf9265 More hard-link stuff. 2004-01-12 03:59:53 +00:00
Wayne Davison
aa23c22004 Changed the hard-link check. 2004-01-12 03:50:07 +00:00
Wayne Davison
1d5cda2265 Updated to perform a much more efficient hlink algorithm that doesn't
require any binary searching of hlink data.
2004-01-12 03:49:47 +00:00
Wayne Davison
fe70ad26d3 Added F_HEAD and F_NEXT defines. 2004-01-12 03:48:43 +00:00
Wayne Davison
0a00748901 Mention more of the latest changes. 2004-01-11 22:39:34 +00:00
Wayne Davison
03979352b4 More cleanup, fixing an error in the fatal-message strings that tried
to output the "filename" value when it might not be initialized.
2004-01-11 22:11:25 +00:00
Wayne Davison
cb7fb45e42 Updated a questioning comment. 2004-01-11 08:17:19 +00:00
Wayne Davison
92cc9dd7c2 Use the new dev+inode union in the flist_struct. 2004-01-11 07:56:14 +00:00
Wayne Davison
88a7fb3edd Moved the inode & dev items out of the flist_struct. Based on a
preliminary patch by J.W.
2004-01-11 07:55:53 +00:00
Wayne Davison
728d092201 Use the new union-ified flist_struct values. 2004-01-11 07:28:45 +00:00
Wayne Davison
80707c983c Put 3 flist_struct items into a union: rdev, sum, and link (all
mutually exclusive based on mode).  Based on an idea by J.W.
2004-01-11 07:28:23 +00:00
Wayne Davison
5911fee567 A slightly better reset mechanism for send_file_entry() and
receive_file_entry().
2004-01-10 22:13:19 +00:00
Wayne Davison
a09f6f55da Use the new LIVE_FLAGS define to fix a potential flag problem. 2004-01-10 21:10:04 +00:00
Wayne Davison
caf5cc9152 Added LIVE_FLAGS define. 2004-01-10 21:09:06 +00:00
Wayne Davison
58422e8393 Changed the call to write_batch_csum_info() to the latest syntax. 2004-01-10 20:16:18 +00:00
Wayne Davison
e8d3168e3a Massive rewrite to replace the file-list read/write code with calls to
send_file_entry() and receive_file_entry().  Other cleanups too.
2004-01-10 20:16:13 +00:00
Wayne Davison
7b1a0c19b8 Allow the send_file_entry() and receive_file_entry() routines to be
called by the batch processor.
2004-01-10 20:15:55 +00:00
Wayne Davison
536492752b Support the recent changes in the flist_struct. 2004-01-10 08:39:57 +00:00
Wayne Davison
7c4f063b13 Got rid of tmpsum[]. 2004-01-09 18:35:41 +00:00
Wayne Davison
1a62c49d31 Note latest changes. 2004-01-09 18:27:15 +00:00
Wayne Davison
fea4db62bd - Never allocate a useless sum array for a non-regular flist item.
- Don't transmit the sum array for non-regular files (p28 onward).
- Tweaked a couple comments.
2004-01-09 18:19:32 +00:00
Wayne Davison
4499c0eebd A couple minor code improvements. 2004-01-09 18:10:31 +00:00
Wayne Davison
0c42946536 Added an extra comment. 2004-01-09 16:53:55 +00:00
J.W. Schultz
ab264c9e79 Added a few more devices to the devices.test to hopefully
test same, same high and different device numbers.
2004-01-09 14:02:00 +00:00
J.W. Schultz
dd7fb70f6e Finished the last_* renameing and fixed a cast.. 2004-01-09 13:55:56 +00:00
Wayne Davison
30f337c9ef Updated the send_file_name() and receive_file_entry() functions to make
some of the variable names more logical in the new program flow.  Also
improved the setting of the new last_rdev value that only remembers the
high 3 bytes.
2004-01-08 22:45:12 +00:00
Wayne Davison
9d35271938 Changed the OLD_SAME_RDEV define to SAME_RDEV_pre28. 2004-01-08 22:45:07 +00:00
Wayne Davison
bbfb1d016b Added explicit call to AC_PROG_EGREP. 2004-01-08 18:33:38 +00:00
Wayne Davison
c4b4df4fb4 Optimized the sending of dev+inode data for hard-linking support
(but only when speaking protocol 28).
2004-01-08 11:29:50 +00:00
Wayne Davison
a6d89d18bf - Added flags HAS_INODE_DATA and SAME_DEV.
- Changed PROTOCOL_VERSION to 28 now.
2004-01-08 11:28:07 +00:00
Wayne Davison
75bc860093 Implemented an extended-flag-byte in the transfer protocol by moving
the SAME_RDEV bit into the next 8 bits and adding an EXTENDED_FLAG
bit.  Also modified the meaning of this bit for protocol 28 and above:
SAME_HIGH_RDEV indicates that all but the lowest byte matches.  The
older protocols get OLD_SAME_RDEV set (with the old semantics) for
compatibility.  Note also that protocol 28 isn't turned on yet.
2004-01-08 11:08:30 +00:00
Wayne Davison
02a279a75f Added EXTENDED_FLAGS and SAME_HIGH_RDEV. Changed SAME_RDEV to OLD_SAME_RDEV. 2004-01-08 11:08:30 +00:00
Wayne Davison
584c7bf76d Pass the $srcdir/wildtest.txt file on the command-line to wildtest. 2004-01-08 09:00:14 +00:00
Wayne Davison
c4cd2ca6bf We now take a TESTFILE arg on the command-line. 2004-01-08 08:59:52 +00:00
Wayne Davison
1ef00d2072 Improved the code in send_file_entry() and receive_file_entry() to
make it a little easier to read and a little more optimized.  Also
made the flag size in our function calls match the size of the flags
in the flist_struct.  These changes will make it easier for me to
optimize the sending of the hard-link data in a future commit.
2004-01-08 04:56:27 +00:00
Wayne Davison
4dd4c72790 Made the flags in the file_struct a little smaller. 2004-01-08 04:53:16 +00:00
Wayne Davison
6aae748ea7 - No need to check S_ISREG() on files already in the hlink_list.
- The realloc in init_hard_links() might fail if the list is empty
  (which can happen if there are no regular files in the transfer).
  I changed the code to free the list in that case.
2004-01-08 03:17:07 +00:00
Wayne Davison
aa953c3201 Old-protocols. 2004-01-08 00:47:17 +00:00
Wayne Davison
3f55bd5dad Got rid of support for protocols 17 and 18. 2004-01-08 00:45:41 +00:00
J.W. Schultz
279b1c1ebb Noted hardlink memory footprint reduction. 2004-01-07 11:38:23 +00:00
J.W. Schultz
fa45cda1aa Cosmetic changes to file_compare() for readability and to
match hlink_compare()
2004-01-07 09:11:56 +00:00
J.W. Schultz
11dc274054 Change hlink_list so we only have a list of pointers to
file_struct instead of a copy of the file_struct list.
2004-01-07 09:06:37 +00:00
Wayne Davison
e7bef92205 Batch-mode fix. 2004-01-06 05:35:55 +00:00
Wayne Davison
4a1991d7c5 Fixed a byte-order problem for batch-file processing on big-endian
systems (reported by Jay Fenlason).
2004-01-06 05:33:02 +00:00
Wayne Davison
13aefa1365 Some whitespace tweaks. 2004-01-05 03:57:15 +00:00
Wayne Davison
addf0c4a1c A few formatting tweaks. 2004-01-05 03:56:19 +00:00
Wayne Davison
25bfc8cea1 Use new recv_generator() calling syntax. 2004-01-04 19:18:37 +00:00
Wayne Davison
dfd5ba6ab7 Changed recv_generator() to take a "struct file_struct *" instead of
a "struct file_list *", which allows us to call it with a copy of the
current file_struct entry that we've modified.  This is better than
modifying the entry directly because the latter causes the shared
memory between the generator and the receiver to slowly vanish as
the in-memory changes happen.
2004-01-04 18:43:18 +00:00
Wayne Davison
393ba2214d Try using "id -un" before "whoami" since the latter doesn't exist on
SunOS systems (and I hope the former works -- we'll see).
2004-01-04 07:07:08 +00:00
Wayne Davison
f358487f8e Silence a compiler warning on Sun OS systems. 2004-01-04 07:06:05 +00:00
Wayne Davison
a18381aca6 Improved the text. 2004-01-03 20:50:51 +00:00
Wayne Davison
f6e54812b7 Fixed autom4te*.cache entry. 2004-01-03 19:49:52 +00:00
Wayne Davison
31e7451aa5 Mention more INTERNALS work. 2004-01-03 19:28:17 +00:00
Wayne Davison
0e36d9da42 More variable-size cleanup. 2004-01-03 19:28:03 +00:00
Wayne Davison
da9d12f5d9 Made the types used in the sum_buf and sum_struct structures consistent
with the variables in the code that manipulates these values.
2004-01-03 18:37:41 +00:00
J.W. Schultz
a60e2dca6b Create GID_NONE for use gid test readability. 2004-01-03 13:17:32 +00:00
Wayne Davison
86c4601e12 Fixed a name. 2004-01-03 09:48:52 +00:00
Wayne Davison
173f5bf8cf Fixed a size check in the new code. 2004-01-03 09:44:20 +00:00
Wayne Davison
823edc686f Document the latest changes. 2004-01-03 09:36:30 +00:00
Wayne Davison
a3a841073e Added support for "Basic" authentication to our proxy, based on a
patch by Bardur Arantsson.
2004-01-03 09:19:06 +00:00
Wayne Davison
57385128c3 Made base64_encode() non-static. 2004-01-03 08:53:36 +00:00
Wayne Davison
2990e06f29 Silence a compiler warning. 2004-01-03 01:12:10 +00:00
Wayne Davison
2ef2e822d1 Added missing '[]'s to AC_CHECK_FUNCS() calls so that this works
with autoconf 2.58 and above.
2004-01-03 00:40:55 +00:00
Wayne Davison
b7736c797c Some cosmetic tweaks. 2004-01-02 23:41:32 +00:00
Wayne Davison
9b9c8aaf4d Improved flush_write_file(). 2004-01-02 18:42:33 +00:00
Wayne Davison
b0fd253afc Applied a slightly-tweaked version of Oliver Braun's patch that
implements listening on multiple addresses and a fix for IPv6-only
systems.
2004-01-02 18:05:51 +00:00
Wayne Davison
e028b9ff53 Call bind() with the right ai_addr/ai_addrlen info. 2004-01-02 17:47:44 +00:00
Wayne Davison
9c07d25345 Tidied up a few things in preparation for changes. 2004-01-02 17:20:21 +00:00
Wayne Davison
7352b8736b Moved the is_in_group() function to uidlist.c. 2004-01-02 16:52:29 +00:00
Wayne Davison
5b540e86a4 Set the file's gid to -1 if we don't have permissions to set it. 2004-01-02 16:51:54 +00:00
Wayne Davison
6744b62ddd Fixed --link-dest's check for identicalness to ignore the uid if
non-root, and to ignore a gid of -1.
2004-01-02 16:50:06 +00:00
Wayne Davison
e90b8acec3 Silence some compiler warnings. 2004-01-02 08:50:25 +00:00
Wayne Davison
925c517f19 Improved the setting of cleanup_got_literal so that we know if the
current file received some literal data yet or not.
2004-01-02 08:38:35 +00:00
Wayne Davison
cc964a518c Use the new f_name_to() call instead of strlcat() an f_name(). 2004-01-02 08:36:58 +00:00
Wayne Davison
3309507dd3 Some minor changes to some if statements. 2004-01-02 08:33:57 +00:00
Wayne Davison
5e7dbaca50 Use buffered I/O to read the exclude list. 2004-01-02 08:31:12 +00:00
Wayne Davison
76c2194714 Applying my updated version of Craig Barratt's buffered I/O patch. 2004-01-02 08:29:49 +00:00
Wayne Davison
968c8030cf Some name tweaks. 2004-01-02 08:19:26 +00:00
Wayne Davison
446e239e2c Use the f_name_to() function to avoid having to strdup() the name that
f_name() returns.  Also used in a call to recv_generator() to keep the
name safe for the duration of the call.
2004-01-02 08:18:53 +00:00
Wayne Davison
e7bc9b64a3 Use f_name_to() when producing a name for the recv_generator() call.
This prevents things like the hard-link code from losing the name
before we're finished with it.
2004-01-02 08:05:20 +00:00
Wayne Davison
8018edd3aa Optimized f_name(), generating: (1) f_name_cmp(), which optimizes
comparing two file_struct elements without copying them first, and
(2) f_name_to() which lets us supply the destination buffer for a
f_name() call (to allow it to persist without an extra copy).
2004-01-02 07:57:02 +00:00
Wayne Davison
64c3523a6f Got rid of /* dw */ comments. 2004-01-02 07:42:20 +00:00
Wayne Davison
310c9f30f0 Optimized hard_link_one() to not call f_name() so many times. 2004-01-02 07:34:49 +00:00
Wayne Davison
5c1b7bfd2a No need to conditionally-compile EINTR code -- no other files do this. 2004-01-02 07:31:02 +00:00
Wayne Davison
faf11086d8 More twiddling of the wildcard verbage. 2004-01-02 07:11:32 +00:00
Wayne Davison
52fa4d7893 Improved the itemized discussion under the wildcard changes. 2004-01-01 22:37:13 +00:00
Wayne Davison
de0551020b Allow function return values to start with "const". 2004-01-01 21:10:50 +00:00
75 changed files with 4924 additions and 3601 deletions

View File

@@ -1,6 +1,6 @@
ID
Makefile
autom4te.cache
autom4te*.cache
confdefs.h
config.cache
config.h
@@ -21,4 +21,3 @@ tls
trimslash
t_unsafe
wildtest
zlib/dummy

View File

@@ -25,9 +25,9 @@ VERSION=@VERSION@
.SUFFIXES:
.SUFFIXES: .c .o
HEADERS=byteorder.h config.h errcode.h proto.h rsync.h
HEADERS=byteorder.h config.h errcode.h proto.h rsync.h lib/pool_alloc.h
LIBOBJ=lib/wildmatch.o lib/compat.o lib/snprintf.o lib/mdfour.o \
lib/permstring.o @LIBOBJS@
lib/permstring.o lib/pool_alloc.o @LIBOBJS@
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

333
NEWS
View File

@@ -1,134 +1,229 @@
NEWS for rsync 2.6.0 (1 Jan 2004)
Protocol: 27 (changed)
Changes since 2.5.7:
ENHANCEMENTS:
* "ssh" is now the default remote shell for rsync. If you want to
change this, configure like this: "./configure --with-rsh=rsh".
* Added --files-from, --no-relative, --no-implied-dirs, and --from0.
Note that --from0 affects the line-ending character for all the
files read by the --*-from options. (Wayne Davison)
* Length of csum2 is now per-file starting with protocol version
27. (J.W. Schultz)
* Per-file dynamic block size is now sqrt(file length). The
per-file checksum size is determined according to an algorithm
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.
* Added a new error/warning code for when files vanish from the
sending side. Made vanished source files not interfere with the
file-deletion pass when --delete-after was specified.
* Various trailing-info sections are now preceded by a newline.
NEWS for rsync 2.6.2 (30 Apr 2004)
Protocol: 28 (unchanged)
Changes since 2.6.1:
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)
- Fixed a major bug in the sorting of the filenames when --relative
is used for some sources (just sources such as "/" and "/*" were
affected). This fix ensures that we ask for the right file-list
item when requesting changes from the sender.
- A pattern with a "**" no longer causes a "*" to match slashes.
For example, with "/*/foo/**", "foo" must be 2 levels deep.
- Rsync now checks the return value of the close() function to
better report disk-full problems on an NFS file system.
- "**/foo" now matches at the base of the transfer (i.e. /foo).
- Restored the old daemon-server behavior of logging error messages
rather than returning them to the user. (A better long-term fix
will be sought in the future.)
- 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.
- An obscure uninitialized-variable bug was fixed in the uid/gid
code. (This bug probably had no ill effects.)
- 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" (unlike before).
- Got rid of the configure check for sys/sysctl.h (it wasn't used
and was causing a problem on some systems). Also improved the
broken-largefile-locking test to try to avoid failure due to an
NFS build-dir.
* 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)
- Fixed a compile problem on systems that don't define
AI_NUMERICHOST.
* For protocol version >= 27, mdfour_tail() is called when the
block size (including checksum_seed) is a multiple of 64.
Previously it was not called, giving the wrong MD4 checksum.
(Craig Barratt)
* For protocol version >= 27, a 64 bit bit counter is used in
mdfour.c as required by the RFC. Previously only a 32 bit bit
counter was used, causing incorrect MD4 file checksums for
file sizes >= 512MB - 4. (Craig Barratt)
* Fixed a crash bug when interacting with older rsync versions and
multiple files of the same name are destined for the same dir.
(Wayne Davison)
* Keep tmp names from overflowing MAXPATHLEN.
* Make --link-dest honor the absence of -p, -o, and -g.
* Made rsync treat a trailing slash in the destination in a more
consistent manner.
* Fixed file I/O error detection. (John Van Essen)
* Fixed bogus "malformed address {hostname}" message in rsyncd log
when checking IP address against hostnames from "hosts allow"
and "hosts deny" parameters in config file.
* Print heap statistics when verbose >= 2 instead of when >= 1.
* 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.
* When the backup code makes new directories, create them with mode
0700 instead of 0755 (since the directory permissions in the
backup tree are not yet copied from the main tree).
* 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)
* Added a fix that should give ssh time to restore the tty settings
if the user presses Ctrl-C at an ssh password prompt.
- Fixed a compile problem in the popt source for compilers that
don't support __attribute__.
INTERNAL:
* Eliminated vestigial support for old versions that we stopped
supporting. (J.W. Schultz)
- Improved the testsuite's "merge" test to work on OSF1.
* Simplified some of the option-parsing code. (Wayne Davison)
- Two new diffs were added to the patches dir.
* Some cleanup made to the exclude code, as well as some new
defines added to enhance readability. (Wayne Davison)
NEWS for rsync 2.6.1 (26 Apr 2004)
Protocol: 28 (changed)
Changes since 2.6.0:
* 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)
SECURITY FIXES:
- Paths sent to an rsync daemon are more thoroughly sanitized when
chroot is not used. If you're running a non-read-only rsync
daemon with chroot disabled, *please upgrade*, ESPECIALLY if the
user privs you run rsync under is anything above "nobody".
ENHANCEMENTS:
- Lower memory use, more optimal transfer of data over the socket,
and lower CPU usage (see the INTERNAL section for details).
- The RSYNC_PROXY environment variable can now contain a
"USER:PASS@" prefix before the "HOST:PORT" information.
(Bardur Arantsson)
- The --progress output now mentions how far along in the transfer
we are, including both a count of files transferred and a
percentage of the total file-count that we've processed. It also
shows better current-rate-of-transfer and remaining-transfer-time
values.
- The configure script now accepts --with-rsyncd-conf=PATH to
override the default value of the /etc/rsyncd.conf file.
- Added a couple extra diffs in the "patches" dir, removed the ones
that got applied, and rebuilt the rest.
- Documentation changes now attempt to describe some often mis-
understood features more clearly.
BUG FIXES:
- When -x (--one-file-system) is combined with -L (--copy-links) or
--copy-unsafe-links, no symlinked files are skipped, even if the
referent file is on a different filesystem.
- The --link-dest code now works properly for a non-root user when
(1) the UIDs of the source and destination differ and -o was
specified, or (2) when the group of the source can't be used on
the destination and -g was specified.
- Fixed a bug in the handling of -H (hard-links) that might cause
the expanded PATH/NAME value of the current item to get
overwritten (due to an expanded-name caching bug).
- We now reset the "new data has been sent" flag at the start of
each file we send. This makes sure that an interrupted transfer
with the --partial option set doesn't keep a shorter temp file
than the current basis file when no new data has been transfered
over the wire for that file.
- Fixed a byte-order problem in --batch-mode on big-endian machines.
(Jay Fenlason)
- Fixed configure bug when running "./configure --disable-ipv6".
- Fixed "make test" bug when build dir is not the source dir.
- When using --cvs-exclude, the exclude items we get from a
per-directory's .cvsignore file once again only affect that one
directory (not all following directories too). The items are also
now properly word-split and parsed without any +/- prefix parsing.
- When specifying the USER@HOST: prefix for a file, the USER part
can now contain an '@', if needed (i.e. the last '@' is used to
find the HOST, not the first).
- Fixed some bugs in the handling of group IDs for non-root users:
(1) It properly handles a group that the sender didn't have a name
for (it would previously skip changing the group on any files in
that group). (2) If --numeric-ids is used, rsync no longer
attempts to set groups that the user doesn't have the permission
to set.
- Fixed the "refuse options" setting in the rsyncd.conf file.
- Improved the -x (--one-file-system) flag's handling of any mount-
point directories we encounter. It is both more optimal (in that
it no longer does a useless scan of the contents of the mount-
point dirs) and also fixes a bug where a remapped mount of the
original filesystem could get discovered in a subdir we should be
ignoring.
- Rsync no longer discards a double-slash at the start of a filename
when trying to open the file. It also no longer constructs names
that start with a double slash (unless the user supplied them).
- Path-specifying options to a daemon should now work the same with
or without chroot turned on. Previously, such a option (such as
--link-dest) would get its absolute path munged into a relative
one if chroot was not on, making that setting fairly useless.
Rsync now transforms the path into one that is based on the
module's base dir when chroot is not enabled.
- Fixed compilation problem on Tru64 Unix (having to do with
sockaddr.sa_len and sockaddr.sin_len).
- Fixed a compatibility problem interacting with older rsync
versions that might send us an empty --suffix value without
telling us that --backup-dir was specified.
- The "hosts allow" option for a daemon-over-remote-shell process
now has improved support for IPv6 addresses and a fix for systems
that have a length field in their socket structs.
- Fixed the ability to request an empty backup --suffix when sending
files to an rsync daemon.
INTERNAL:
- Most of the I/O is now buffered, which results in a pretty large
speedup when running under MS Windows. (Craig Barratt)
- Optimizations to the name-handling/comparing code have made some
significant reductions in user-CPU time for large file sets.
- Some cleanup of the variable types make the code more consistent.
- Reduced memory requirements of hard link preservation.
(J.W. Schultz)
- Implemented a new algorithm for hard-link handling that speeds up
the code significantly. (J.W. Schultz and Wayne Davison)
- The --hard-link option now uses the first existing file in the
group of linked files as the basis for the transfer. This
prevents the sub-optimal transfer of a file's data when a new
hardlink is added on the sending side and it sorts alphabetically
earlier in the list than the files that are already present on the
receiving side.
- Dropped support for protocol versions less than 20 (2.3.0 released
15 Mar 1999) and activated warnings for protocols less than 25
(2.5.0 released 23 Aug 2001). (Wayne Davison and J.W. Schultz,
severally)
- More optimal data transmission for --hard-links (protocol 28).
- More optimal data transmission for --checksum (protocol 28).
- Less memory is used when --checksum is specified.
- Less memory is used in the file list (a per-file savings).
- The generator is now better about not modifying the file list
during the transfer in order to avoid a copy-on-write memory
bifurcation (on systems where fork() uses shared memory).
Previously, rsync's shared memory would slowly become unshared,
resulting in real memory usage nearly doubling on the receiving
side by the end of the transfer. Now, as long as permissions
are being preserved, the shared memory should remain that way
for the entire transfer.
- Changed hardlink info and file_struct + strings to use allocation
pools. This reduces memory use for large file-sets and permits
freeing memory to the OS. (J.W. Schultz)
- The 2 pipes used between the receiver and generator processes
(which are forked on the same machine) were reduced to 1 pipe and
the protocol improved so that (1) it is now impossible to have the
"redo" pipe fill up and hang rsync, and (2) trailing messages from
the receiver don't get lost on their way through the generator
over to the sender (which mainly affected hard-link messages and
verbose --stats output).
- Improved the internal uid/gid code to be more portable and a
little more optimized.
- The device numbers sent when using --devices are now sent as
separate major/minor values with 32-bit accuracy (protocol 28).
Previously, the copied devices were sent as a single 32-bit
number. This will make inter-operation of 64-bit binaries more
compatible with their 32-bit brethren (with both ends of the
connection are using protocol 28). Note that optimizations in the
binary protocol for sending the device numbers often results in
fewer bytes being used than before, even though more precision is
now available.
- Some cleanup of the exclude/include structures and its code made
things clearer (internally), simpler, and more efficient.
- The reading & writing of the file-list in batch-mode is now
handled by the same code that sends & receives the list over the
wire. This makes it much easier to maintain. (Note that the
batch code is still considered to be experimental.)

142
OLDNEWS
View File

@@ -1,3 +1,145 @@
NEWS for rsync 2.6.0 (1 Jan 2004)
Protocol: 27 (changed)
Changes since 2.5.7:
ENHANCEMENTS:
* "ssh" is now the default remote shell for rsync. If you want to
change this, configure like this: "./configure --with-rsh=rsh".
* Added --files-from, --no-relative, --no-implied-dirs, and --from0.
Note that --from0 affects the line-ending character for all the
files read by the --*-from options. (Wayne Davison)
* Length of csum2 is now per-file starting with protocol version
27. (J.W. Schultz)
* Per-file dynamic block size is now sqrt(file length). The
per-file checksum size is determined according to an algorithm
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.
* Added a new error/warning code for when files vanish from the
sending side. Made vanished source files not interfere with the
file-deletion pass when --delete-after was specified.
* Various trailing-info sections are now preceded by a newline.
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.
[If your string has BOTH "*" and "**" wildcards, changing the
"*" wildcards to "**" will provide the old behavior in all
versions.]
- "**/foo" now matches at the base of the transfer (like /foo
does). [Use "/**/foo" to get the old behavior in all versions.]
- A 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. [Use "/CVS/R*"
to get the old behavior in all versions.]
- 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" (unlike before). [Use "foo*bar" to get the
old behavior in all versions.]
* The exclude list specified in the daemon's config file is now
properly applied to the pulled items no matter how deep the
user's file-args are in the source tree. (Wayne Davison)
* For protocol version >= 27, mdfour_tail() is called when the
block size (including checksum_seed) is a multiple of 64.
Previously it was not called, giving the wrong MD4 checksum.
(Craig Barratt)
* For protocol version >= 27, a 64 bit bit counter is used in
mdfour.c as required by the RFC. Previously only a 32 bit bit
counter was used, causing incorrect MD4 file checksums for
file sizes >= 512MB - 4. (Craig Barratt)
* Fixed a crash bug when interacting with older rsync versions and
multiple files of the same name are destined for the same dir.
(Wayne Davison)
* Keep tmp names from overflowing MAXPATHLEN.
* Make --link-dest honor the absence of -p, -o, and -g.
* Made rsync treat a trailing slash in the destination in a more
consistent manner.
* Fixed file I/O error detection. (John Van Essen)
* Fixed bogus "malformed address {hostname}" message in rsyncd log
when checking IP address against hostnames from "hosts allow"
and "hosts deny" parameters in config file.
* Print heap statistics when verbose >= 2 instead of when >= 1.
* 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.
* When the backup code makes new directories, create them with mode
0700 instead of 0755 (since the directory permissions in the
backup tree are not yet copied from the main tree).
* 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 filesystem issues and truncated
files. (David Norwood, Michael Brown, J.W. Schultz)
* Added a fix that should give ssh time to restore the tty settings
if the user presses Ctrl-C at an ssh password prompt.
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)
NEWS for rsync 2.5.7 (4 Dec 2003)
Protocol: 26 (unchanged)
Changes since 2.5.6:

114
TODO
View File

@@ -16,7 +16,6 @@ Handling IPv6 on old machines
Other IPv6 stuff:
Add ACL support 2001/12/02
Lazy directory creation
Conditional -z for old protocols
proxy authentication 2002/01/23
SOCKS 2002/01/23
FAT support
@@ -58,10 +57,8 @@ Add machines to build farm
PERFORMANCE ----------------------------------------------------------
File list structure in memory
Traverse just one directory at a time
Hard-link handling
Allow skipping MD4 file_sum 2002/04/08
Accelerate MD4
String area code
TESTING --------------------------------------------------------------
Torture test
@@ -74,7 +71,6 @@ If tests are skipped, say why.
Test daemon feature to disallow particular options.
Create pipe program for testing
Create test makefile target for some tests
Test "refuse options" works
RELATED PROJECTS -----------------------------------------------------
rsyncsh
@@ -257,21 +253,6 @@ Lazy directory creation
-- --
Conditional -z for old protocols
After we get the @RSYNCD greeting from the server, we know it's
version but we have not yet sent the command line, so we could just
remove the -z option if the server is too old.
For ssh invocation it's not so simple, because we actually use the
command line to start the remote process. However, we only actually
do compression in token.c, and we could therefore once we discover
the remote version emit an error if it's too old. I'm not sure if
that's a good tradeoff or not.
-- --
proxy authentication 2002/01/23
Allow RSYNC_PROXY to be http://user:pass@proxy.foo:3128/, and do
@@ -444,7 +425,9 @@ Improve error messages
our load? (Debian #28416) Probably fixed now, but a test case would
be good.
When running as a daemon, some errors should both be returned to the
user and logged. This will make interacting with a daemon less
cryptic.
-- --
@@ -708,76 +691,6 @@ Traverse just one directory at a time
-- --
Hard-link handling
At the moment hardlink handling is very expensive, so it's off by
default. It does not need to be so.
Since most of the solutions are rather intertwined with the file
list it is probably better to fix that first, although fixing
hardlinks is possibly simpler.
We can rule out hardlinked directories since they will probably
screw us up in all kinds of ways. They simply should not be used.
At the moment rsync only cares about hardlinks to regular files. I
guess you could also use them for sockets, devices and other beasts,
but I have not seen them.
When trying to reproduce hard links, we only need to worry about
files that have more than one name (nlinks>1 && !S_ISDIR).
The basic point of this is to discover alternate names that refer to
the same file. All operations, including creating the file and
writing modifications to it need only to be done for the first name.
For all later names, we just create the link and then leave it
alone.
If hard links are to be preserved:
Before the generator/receiver fork, the list of files is received
from the sender (recv_file_list), and a table for detecting hard
links is built.
The generator looks for hard links within the file list and does
not send checksums for them, though it does send other metadata.
The sender sends the device number and inode with file entries, so
that files are uniquely identified.
The receiver goes through and creates hard links (do_hard_links)
after all data has been written, but before directory permissions
are set.
At the moment device and inum are sent as 4-byte integers, which
will probably cause problems on large filesystems. On Linux the
kernel uses 64-bit ino_t's internally, and people will soon have
filesystems big enough to use them. We ought to follow NFS4 in
using 64-bit device and inode identification, perhaps with a
protocol version bump.
Once we've seen all the names for a particular file, we no longer
need to think about it and we can deallocate the memory.
We can also have the case where there are links to a file that are
not in the tree being transferred. There's nothing we can do about
that. Because we rename the destination into place after writing,
any hardlinks to the old file are always going to be orphaned. In
fact that is almost necessary because otherwise we'd get really
confused if we were generating checksums for one name of a file and
modifying another.
At the moment the code seems to make a whole second copy of the file
list, which seems unnecessary.
We should have a test case that exercises hard links. Since it
might be hard to compare ./tls output where the inodes change we
might need a little program to check whether several names refer to
the same file.
-- --
Allow skipping MD4 file_sum 2002/04/08
If we're doing a local transfer, or using -W, then perhaps don't
@@ -806,14 +719,6 @@ Accelerate MD4
-- --
String area code
Test whether this is actually faster than just using malloc(). If
it's not (anymore), throw it out.
-- --
TESTING --------------------------------------------------------------
Torture test
@@ -905,19 +810,6 @@ Create test makefile target for some tests
-- --
Test "refuse options" works
What about for --recursive?
If you specify an unrecognized option here, you should get an error.
We need a test case for this...
Was this broken when we changed to popt?
-- --
RELATED PROJECTS -----------------------------------------------------
rsyncsh

View File

@@ -1,11 +0,0 @@
#undef ino_t
#undef HAVE_CONNECT
#undef HAVE_SHORT_INO_T
#undef HAVE_GETOPT_LONG
#undef REPLACE_INET_NTOA
#undef REPLACE_INET_ATON
#undef HAVE_GETTIMEOFDAY_TZ
#undef ENABLE_IPV6
#undef HAVE_SOCKADDR_LEN
#undef HAVE_SOCKADDR_IN6_SCOPE_ID
#undef HAVE_SOCKETPAIR

View File

@@ -24,7 +24,7 @@
encode a buffer using base64 - simple and slow algorithm. null terminates
the result.
***************************************************************************/
static void base64_encode(char *buf, int len, char *out)
void base64_encode(char *buf, int len, char *out)
{
char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
int bit_offset, byte_offset, idx, i;
@@ -33,7 +33,7 @@ static void base64_encode(char *buf, int len, char *out)
memset(out, 0, bytes+1);
for (i=0;i<bytes;i++) {
for (i = 0; i < bytes; i++) {
byte_offset = (i*6)/8;
bit_offset = (i*6)%8;
if (bit_offset < 3) {
@@ -269,7 +269,8 @@ void auth_client(int fd, char *user, char *challenge)
char pass2[30];
extern char *password_file;
if (!user || !*user) return;
if (!user || !*user)
user = "nobody";
if (!(pass=getpassf(password_file)) && !(pass=getenv("RSYNC_PASSWORD"))) {
/* XXX: cyeoh says that getpass is deprecated, because

262
backup.c
View File

@@ -1,16 +1,16 @@
/*
/*
Copyright (C) Andrew Tridgell 1999
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.
@@ -23,6 +23,8 @@
extern int verbose;
extern int backup_suffix_len;
extern int backup_dir_len;
extern unsigned int backup_dir_remainder;
extern char backup_dir_buf[MAXPATHLEN];
extern char *backup_suffix;
extern char *backup_dir;
@@ -30,17 +32,19 @@ extern int am_root;
extern int preserve_devices;
extern int preserve_links;
extern int preserve_hard_links;
extern int orig_umask;
/* simple backup creates a backup with a suffix in the same directory */
static int make_simple_backup(char *fname)
{
char fnamebak[MAXPATHLEN];
if (strlen(fname) + backup_suffix_len > MAXPATHLEN-1) {
if (stringjoin(fnamebak, sizeof fnamebak, fname, backup_suffix, NULL)
>= sizeof fnamebak) {
rprintf(FERROR, "backup filename too long\n");
return 0;
}
snprintf(fnamebak, sizeof(fnamebak), "%s%s", fname, backup_suffix);
if (do_rename(fname, fnamebak) != 0) {
/* cygwin (at least version b19) reports EINVAL */
if (errno != ENOENT && errno != EINVAL) {
@@ -54,151 +58,99 @@ static int make_simple_backup(char *fname)
}
/* recursively make a directory path */
static int make_dir(char *name, int mask)
{
char newdir [MAXPATHLEN];
char *p, *d;
/* copy pathname over, look for last '/' */
for (p = d = newdir; *name; *d++ = *name++)
if (*name == '/')
p = d;
if (p == newdir)
return 0;
*p = 0;
/* make the new directory, if that fails then make its parent */
while (do_mkdir (newdir, mask) != 0)
if ((errno != ENOENT) || !make_dir (newdir, mask))
return 0;
return 1;
} /* make_dir */
/****************************************************************************
Create a directory given an absolute path, perms based upon another directory
path
****************************************************************************/
static int make_bak_dir(char *fname, char *bak_path)
static int make_bak_dir(char *fullpath)
{
STRUCT_STAT st;
STRUCT_STAT *st2;
char fullpath[MAXPATHLEN];
extern int orig_umask;
char *p;
char *q;
char *rel = fullpath + backup_dir_len;
char *end = rel + strlen(rel);
char *p = end;
while(strncmp(bak_path, "./", 2) == 0) bak_path += 2;
while (strncmp(fullpath, "./", 2) == 0)
fullpath += 2;
if(bak_path[strlen(bak_path)-1] != '/') {
snprintf(fullpath, sizeof(fullpath), "%s/", bak_path);
} else {
snprintf(fullpath, sizeof(fullpath), "%s", bak_path);
/* Try to find an existing dir, starting from the deepest dir. */
while (1) {
if (--p == fullpath) {
p += strlen(p);
goto failure;
}
if (*p == '/') {
*p = '\0';
if (do_mkdir(fullpath, 0777 & ~orig_umask) == 0)
break;
if (errno != ENOENT) {
rprintf(FERROR,
"make_bak_dir mkdir %s failed: %s\n",
full_fname(fullpath), strerror(errno));
goto failure;
}
}
}
p = fullpath;
q = &fullpath[strlen(fullpath)]; /* End of bak_path string */
strcat(fullpath, fname);
/* Make the directories */
while ((p = strchr(p, '/'))) {
*p = 0;
if(do_lstat(fullpath, &st) != 0) {
do_mkdir(fullpath, 0777 & ~orig_umask);
if(p>q) {
if(do_lstat(q, &st) != 0) {
rprintf(FERROR, "make_bak_dir stat %s failed: %s\n",
full_fname(fullpath), strerror(errno));
} else {
st2 = &st;
set_modtime(fullpath, st2->st_mtime);
if(do_lchown(fullpath, st2->st_uid, st2->st_gid) != 0) {
rprintf(FERROR, "make_bak_dir chown %s failed: %s\n",
full_fname(fullpath), strerror(errno));
}
if(do_chmod(fullpath, st2->st_mode) != 0) {
rprintf(FERROR, "make_bak_dir failed to set permissions on %s: %s\n",
full_fname(fullpath), strerror(errno));
}
}
/* Make all the dirs that we didn't find on the way here. */
while (1) {
if (p >= rel) {
/* Try to transfer the directory settings of the
* actual dir that the files are coming from. */
if (do_lstat(rel, &st) != 0) {
rprintf(FERROR,
"make_bak_dir stat %s failed: %s\n",
full_fname(rel), strerror(errno));
} else {
set_modtime(fullpath, st.st_mtime);
do_lchown(fullpath, st.st_uid, st.st_gid);
do_chmod(fullpath, st.st_mode);
}
}
*p = '/';
p++;
p += strlen(p);
if (p == end)
break;
if (do_mkdir(fullpath, 0777 & ~orig_umask) < 0) {
rprintf(FERROR,
"make_bak_dir mkdir %s failed: %s\n",
full_fname(fullpath), strerror(errno));
goto failure;
}
}
return 0;
failure:
while (p != end) {
*p = '/';
p += strlen(p);
}
return -1;
}
/* robustly move a file, creating new directory structures if necessary */
static int robust_move(char *src, char *dst)
{
int keep_trying = 4;
int keep_path_extfs = 0;
int failed;
while (keep_trying) {
if (keep_path_extfs) {
failed = copy_file(src, dst, 0755);
if (!failed) {
do_unlink(src);
}
} else {
failed = robust_rename (src, dst);
}
if (failed) {
if (verbose > 2)
rprintf (FERROR, "robust_move failed: %s(%d)\n",
strerror (errno), errno);
switch (errno) {
/* external filesystem */
case EXDEV:
keep_path_extfs = 1;
keep_trying--;
break;
/* no directory to write to */
case ENOENT:
make_dir(dst, 0700);
keep_trying--;
break;
default:
keep_trying = 0;
} /* switch */
} else
keep_trying = 0;
} /* while */
return (!failed);
} /* robust_move */
if (robust_rename(src, dst, 0755) < 0 && (errno != ENOENT
|| make_bak_dir(dst) < 0 || robust_rename(src, dst, 0755) < 0))
return -1;
return 0;
}
/* if we have a backup_dir, then we get here from make_backup().
We will move the file to be deleted into a parallel directory tree */
/* If we have a --backup-dir, then we get here from make_backup().
* We will move the file to be deleted into a parallel directory tree. */
static int keep_backup(char *fname)
{
static int initialised;
char keep_name [MAXPATHLEN];
STRUCT_STAT st;
struct file_struct *file;
int kept = 0;
int ret_code;
if (!initialised) {
if (backup_dir_len && backup_dir[backup_dir_len - 1] == '/')
backup_dir[--backup_dir_len] = '\0';
if (verbose > 0)
rprintf (FINFO, "backup_dir is %s\n", backup_dir);
initialised = 1;
}
/* return if no file to keep */
#if SUPPORT_LINKS
if (do_lstat (fname, &st)) return 1;
if (do_lstat(fname, &st)) return 1;
#else
if (do_stat (fname, &st)) return 1;
if (do_stat(fname, &st)) return 1;
#endif
file = make_file(fname, NULL, NO_EXCLUDES);
@@ -207,24 +159,24 @@ static int keep_backup(char *fname)
if (!file) return 1;
/* make a complete pathname for backup file */
if (backup_dir_len+strlen(fname)+backup_suffix_len > MAXPATHLEN-1) {
rprintf (FERROR, "keep_backup filename too long\n");
if (stringjoin(backup_dir_buf + backup_dir_len, backup_dir_remainder,
fname, backup_suffix, NULL) >= backup_dir_remainder) {
rprintf(FERROR, "keep_backup filename too long\n");
return 0;
}
snprintf(keep_name, sizeof (keep_name), "%s/%s%s",
backup_dir, fname, backup_suffix);
#ifdef HAVE_MKNOD
/* Check to see if this is a device file, or link */
if(IS_DEVICE(file->mode)) {
if(am_root && preserve_devices) {
make_bak_dir(fname, backup_dir);
if(do_mknod(keep_name, file->mode, file->rdev) != 0) {
if (IS_DEVICE(file->mode)) {
if (am_root && preserve_devices) {
make_bak_dir(backup_dir_buf);
if (do_mknod(backup_dir_buf, file->mode, file->u.rdev) != 0) {
rprintf(FERROR, "mknod %s failed: %s\n",
full_fname(keep_name), strerror(errno));
} else if(verbose>2) {
rprintf(FINFO, "make_backup: DEVICE %s successful.\n", fname);
full_fname(backup_dir_buf), strerror(errno));
} else if (verbose > 2) {
rprintf(FINFO,
"make_backup: DEVICE %s successful.\n",
fname);
}
}
kept = 1;
@@ -232,13 +184,13 @@ static int keep_backup(char *fname)
}
#endif
if(!kept && S_ISDIR(file->mode)) {
if (!kept && S_ISDIR(file->mode)) {
/* make an empty directory */
make_bak_dir(fname, backup_dir);
do_mkdir(keep_name, file->mode);
make_bak_dir(backup_dir_buf);
do_mkdir(backup_dir_buf, file->mode);
ret_code = do_rmdir(fname);
if(verbose>2) {
if (verbose > 2) {
rprintf(FINFO, "make_backup: RMDIR %s returns %i\n",
full_fname(fname), ret_code);
}
@@ -246,56 +198,50 @@ static int keep_backup(char *fname)
}
#if SUPPORT_LINKS
if(!kept && preserve_links && S_ISLNK(file->mode)) {
if (!kept && preserve_links && S_ISLNK(file->mode)) {
extern int safe_symlinks;
if (safe_symlinks && unsafe_symlink(file->link, keep_name)) {
if (safe_symlinks && unsafe_symlink(file->u.link, backup_dir_buf)) {
if (verbose) {
rprintf(FINFO, "ignoring unsafe symlink %s -> %s\n",
full_fname(keep_name), file->link);
full_fname(backup_dir_buf), file->u.link);
}
kept = 1;
}
make_bak_dir(fname, backup_dir);
if(do_symlink(file->link, keep_name) != 0) {
make_bak_dir(backup_dir_buf);
if (do_symlink(file->u.link, backup_dir_buf) != 0) {
rprintf(FERROR, "link %s -> %s : %s\n",
full_fname(keep_name), file->link, strerror(errno));
full_fname(backup_dir_buf), file->u.link, strerror(errno));
}
do_unlink(fname);
kept = 1;
}
#endif
if(!kept && preserve_hard_links && check_hard_link(file)) {
if(verbose > 1)
rprintf(FINFO, "%s is a hard link\n", f_name(file));
}
if(!kept && !S_ISREG(file->mode)) {
if (!kept && !S_ISREG(file->mode)) {
rprintf(FINFO, "make_bak: skipping non-regular file %s\n",
fname);
fname);
}
/* move to keep tree if a file */
if(!kept) {
if (!robust_move (fname, keep_name)) {
if (!kept) {
if (robust_move(fname, backup_dir_buf) != 0) {
rprintf(FERROR, "keep_backup failed: %s -> \"%s\": %s\n",
full_fname(fname), keep_name, strerror(errno));
full_fname(fname), backup_dir_buf, strerror(errno));
}
}
set_perms (keep_name, file, NULL, 0);
free_file (file);
free (file);
set_perms(backup_dir_buf, file, NULL, 0);
free(file);
if (verbose > 1)
rprintf (FINFO, "keep_backup %s -> %s\n", fname, keep_name);
rprintf(FINFO, "keep_backup %s -> %s\n", fname, backup_dir_buf);
return 1;
} /* keep_backup */
}
/* main backup switch routine */
int make_backup(char *fname)
{
if (backup_dir)
return (keep_backup(fname));
else
return (make_simple_backup(fname));
return keep_backup(fname);
return make_simple_backup(fname);
}

526
batch.c
View File

@@ -1,5 +1,5 @@
/* -*- c-file-style: "linux" -*-
Weiss 1/1999
Batch utilities for rsync.
@@ -9,6 +9,9 @@
#include <time.h>
extern char *batch_prefix;
extern int csum_length;
extern int protocol_version;
extern struct stats stats;
struct file_list *batch_flist;
@@ -17,122 +20,60 @@ static char rsync_csums_file[] = ".rsync_csums";
static char rsync_delta_file[] = ".rsync_delta";
static char rsync_argvs_file[] = ".rsync_argvs";
static int fdb;
static int fdb_delta;
static int fdb_open;
static int fdb_close;
static int f_csums = -1;
static int f_delta = -1;
void write_batch_flist_file(char *buff, int bytes_to_write)
void write_batch_flist_info(int flist_count, struct file_struct **files)
{
char filename[MAXPATHLEN];
int i, f, save_pv;
int64 save_written;
if (fdb_open) {
/* Set up file extension */
strlcpy(filename, batch_prefix, sizeof(filename));
strlcat(filename, rsync_flist_file, sizeof(filename));
stringjoin(filename, sizeof filename,
batch_prefix, rsync_flist_file, NULL);
/*
* Open batch flist file for writing;
* create it if it doesn't exist
*/
fdb = do_open(filename, O_WRONLY | O_CREAT | O_TRUNC,
S_IREAD | S_IWRITE);
if (fdb == -1) {
rprintf(FERROR, "Batch file %s open error: %s\n",
filename, strerror(errno));
close(fdb);
exit_cleanup(1);
}
fdb_open = 0;
}
/* Write buffer to batch flist file */
if (write(fdb, buff, bytes_to_write) == -1) {
rprintf(FERROR, "Batch file %s write error: %s\n",
filename, strerror(errno));
close(fdb);
f = do_open(filename, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
if (f < 0) {
rprintf(FERROR, "Batch file %s open error: %s\n",
filename, strerror(errno));
exit_cleanup(1);
}
if (fdb_close) {
close(fdb);
}
}
void write_batch_flist_info(int flist_count, struct file_struct **fptr)
{
int i;
int bytes_to_write;
/* Write flist info to batch file */
bytes_to_write =
sizeof(unsigned) +
sizeof(time_t) +
sizeof(OFF_T) +
sizeof(mode_t) +
sizeof(INO64_T) +
sizeof(DEV64_T) +
sizeof(DEV64_T) +
sizeof(uid_t) +
sizeof(gid_t);
fdb_open = 1;
fdb_close = 0;
save_written = stats.total_written;
save_pv = protocol_version;
protocol_version = PROTOCOL_VERSION;
write_int(f, protocol_version);
write_int(f, flist_count);
for (i = 0; i < flist_count; i++) {
write_batch_flist_file((char *) fptr[i], bytes_to_write);
write_char_bufs(fptr[i]->basename);
write_char_bufs(fptr[i]->dirname);
write_char_bufs(fptr[i]->basedir);
write_char_bufs(fptr[i]->link);
if (i == flist_count - 1) {
fdb_close = 1;
}
write_char_bufs(fptr[i]->sum);
send_file_entry(files[i], f,
files[i]->flags & FLAG_TOP_DIR ? XMIT_TOP_DIR : 0);
}
send_file_entry(NULL, f, 0);
protocol_version = save_pv;
stats.total_written = save_written;
close(f);
}
void write_char_bufs(char *buf)
{
/* Write the size of the string which will follow */
char b[4];
SIVAL(b, 0, buf != NULL ? strlen(buf) : 0);
write_batch_flist_file(b, sizeof(int));
/* Write the string if there is one */
if (buf != NULL) {
write_batch_flist_file(buf, strlen(buf));
}
}
void write_batch_argvs_file(int argc, char *argv[])
{
int fdb;
int f;
int i;
char buff[256]; /* XXX */
char buff2[MAXPATHLEN + 6];
char filename[MAXPATHLEN];
/* Set up file extension */
strlcpy(filename, batch_prefix, sizeof(filename));
strlcat(filename, rsync_argvs_file, sizeof(filename));
stringjoin(filename, sizeof filename,
batch_prefix, rsync_argvs_file, NULL);
/*
* Open batch argvs file for writing;
* create it if it doesn't exist
*/
fdb = do_open(filename, O_WRONLY | O_CREAT | O_TRUNC,
S_IREAD | S_IWRITE | S_IEXEC);
if (fdb == -1) {
f = do_open(filename, O_WRONLY | O_CREAT | O_TRUNC,
S_IRUSR | S_IWUSR | S_IEXEC);
if (f < 0) {
rprintf(FERROR, "Batch file %s open error: %s\n",
filename, strerror(errno));
close(fdb);
filename, strerror(errno));
exit_cleanup(1);
}
buff[0] = '\0';
@@ -141,281 +82,135 @@ void write_batch_argvs_file(int argc, char *argv[])
for (i = 0; i < argc; ++i) {
if (i == argc - 2) /* Skip source directory on cmdline */
continue;
continue;
/*
* FIXME:
* I think directly manipulating argv[] is probably bogus
*/
if (!strncmp(argv[i], "--write-batch",
strlen("--write-batch"))) {
strlen("--write-batch"))) {
/* Safer to change it here than script */
/*
* Change to --read-batch=prefix
* to get ready for remote
*/
strlcat(buff, "--read-batch=", sizeof(buff));
strlcat(buff, batch_prefix, sizeof(buff));
strlcat(buff, "--read-batch=", sizeof buff);
strlcat(buff, batch_prefix, sizeof buff);
} else
if (i == argc - 1) {
snprintf(buff2, sizeof(buff2), "${1:-%s}", argv[i]);
strlcat(buff, buff2, sizeof(buff));
snprintf(buff2, sizeof buff2, "${1:-%s}", argv[i]);
strlcat(buff, buff2, sizeof buff);
}
else {
strlcat(buff, argv[i], sizeof(buff));
strlcat(buff, argv[i], sizeof buff);
}
if (i < (argc - 1)) {
strlcat(buff, " ", sizeof(buff));
strlcat(buff, " ", sizeof buff);
}
}
strlcat(buff, "\n", sizeof(buff));
if (!write(fdb, buff, strlen(buff))) {
strlcat(buff, "\n", sizeof buff);
if (!write(f, buff, strlen(buff))) {
rprintf(FERROR, "Batch file %s write error: %s\n",
filename, strerror(errno));
close(fdb);
filename, strerror(errno));
close(f);
exit_cleanup(1);
}
close(fdb);
close(f);
}
struct file_list *create_flist_from_batch(void)
{
unsigned char flags;
char filename[MAXPATHLEN];
unsigned short flags;
int i, f, save_pv;
int64 save_read;
fdb_open = 1;
fdb_close = 0;
stringjoin(filename, sizeof filename,
batch_prefix, rsync_flist_file, NULL);
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 = new_array(struct file_struct *,
batch_flist->malloced);
if (!batch_flist->files) {
out_of_memory("create_flist_from_batch");
f = do_open(filename, O_RDONLY, 0);
if (f < 0) {
rprintf(FERROR, "Batch file %s open error: %s\n",
filename, strerror(errno));
exit_cleanup(1);
}
for (flags = read_batch_flags(); flags; flags = read_batch_flags()) {
batch_flist = flist_new(WITH_HLINK, "create_flist_from_batch");
int i = batch_flist->count;
save_read = stats.total_read;
save_pv = protocol_version;
protocol_version = read_int(f);
if (i >= batch_flist->malloced) {
if (batch_flist->malloced < 1000)
batch_flist->malloced += 1000;
else
batch_flist->malloced *= 2;
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");
}
read_batch_flist_info(&batch_flist->files[i]);
batch_flist->files[i]->flags = flags;
batch_flist->count = read_int(f);
flist_expand(batch_flist);
batch_flist->count++;
for (i = 0; (flags = read_byte(f)) != 0; i++) {
if (protocol_version >= 28 && (flags & XMIT_EXTENDED_FLAGS))
flags |= read_byte(f) << 8;
receive_file_entry(&batch_flist->files[i], flags, batch_flist, f);
}
receive_file_entry(NULL, 0, NULL, 0); /* Signal that we're done. */
protocol_version = save_pv;
stats.total_read = save_read;
return batch_flist;
}
int read_batch_flist_file(char *buff, int len)
{
int bytes_read;
char filename[MAXPATHLEN];
if (fdb_open) {
/* Set up file extension */
strlcpy(filename, batch_prefix, sizeof(filename));
strlcat(filename, rsync_flist_file, sizeof(filename));
/* Open batch flist file for reading */
fdb = do_open(filename, O_RDONLY, 0);
if (fdb == -1) {
rprintf(FERROR, "Batch file %s open error: %s\n",
filename, strerror(errno));
close(fdb);
exit_cleanup(1);
}
fdb_open = 0;
}
/* Read flist batch file */
switch (bytes_read = read(fdb, buff, len)) {
case -1:
rprintf(FERROR, "Batch file %s read error: %s\n",
filename, strerror(errno));
close(fdb);
exit_cleanup(1);
break;
case 0: /* EOF */
close(fdb);
}
return bytes_read;
}
unsigned char read_batch_flags(void)
{
int flags;
if (read_batch_flist_file((char *) &flags, 4)) {
return 1;
} else {
return 0;
}
}
void read_batch_flist_info(struct file_struct **fptr)
{
int int_str_len;
char char_str_len[4];
char buff[256];
struct file_struct *file;
file = new(struct file_struct);
if (!file)
out_of_memory("read_batch_flist_info");
memset((char *) file, 0, sizeof(*file));
*fptr = file;
/*
* Keep these in sync with bytes_to_write assignment
* in write_batch_flist_info()
*/
read_batch_flist_file((char *) &file->modtime, sizeof(time_t));
read_batch_flist_file((char *) &file->length, sizeof(OFF_T));
read_batch_flist_file((char *) &file->mode, sizeof(mode_t));
read_batch_flist_file((char *) &file->inode, sizeof(INO64_T));
read_batch_flist_file((char *) &file->dev, sizeof(DEV64_T));
read_batch_flist_file((char *) &file->rdev, sizeof(DEV64_T));
read_batch_flist_file((char *) &file->uid, sizeof(uid_t));
read_batch_flist_file((char *) &file->gid, sizeof(gid_t));
read_batch_flist_file(char_str_len, sizeof(char_str_len));
int_str_len = IVAL(char_str_len, 0);
if (int_str_len > 0) {
read_batch_flist_file(buff, int_str_len);
buff[int_str_len] = '\0';
file->basename = strdup(buff);
} else {
file->basename = NULL;
}
read_batch_flist_file(char_str_len, sizeof(char_str_len));
int_str_len = IVAL(char_str_len, 0);
if (int_str_len > 0) {
read_batch_flist_file(buff, int_str_len);
buff[int_str_len] = '\0';
file[0].dirname = strdup(buff);
} else {
file[0].dirname = NULL;
}
read_batch_flist_file(char_str_len, sizeof(char_str_len));
int_str_len = IVAL(char_str_len, 0);
if (int_str_len > 0) {
read_batch_flist_file(buff, int_str_len);
buff[int_str_len] = '\0';
file[0].basedir = strdup(buff);
} else {
file[0].basedir = NULL;
}
read_batch_flist_file(char_str_len, sizeof(char_str_len));
int_str_len = IVAL(char_str_len, 0);
if (int_str_len > 0) {
read_batch_flist_file(buff, int_str_len);
buff[int_str_len] = '\0';
file[0].link = strdup(buff);
} else {
file[0].link = NULL;
}
read_batch_flist_file(char_str_len, sizeof(char_str_len));
int_str_len = IVAL(char_str_len, 0);
if (int_str_len > 0) {
read_batch_flist_file(buff, int_str_len);
buff[int_str_len] = '\0';
file[0].sum = strdup(buff);
} else {
file[0].sum = NULL;
}
}
void write_batch_csums_file(void *buff, int bytes_to_write)
{
static int fdb_open = 1;
char filename[MAXPATHLEN];
if (fdb_open) {
/* Set up file extension */
strlcpy(filename, batch_prefix, sizeof(filename));
strlcat(filename, rsync_csums_file, sizeof(filename));
/*
* Open batch csums file for writing;
* create it if it doesn't exist
*/
fdb = do_open(filename, O_WRONLY | O_CREAT | O_TRUNC,
S_IREAD | S_IWRITE);
if (fdb == -1) {
rprintf(FERROR, "Batch file %s open error: %s\n",
filename, strerror(errno));
close(fdb);
exit_cleanup(1);
}
fdb_open = 0;
}
/* Write buffer to batch csums file */
if (write(fdb, buff, bytes_to_write) == -1) {
rprintf(FERROR, "Batch file %s write error: %s\n",
filename, strerror(errno));
close(fdb);
if (write(f_csums, buff, bytes_to_write) < 0) {
rprintf(FERROR, "Batch file write error: %s\n",
strerror(errno));
close(f_csums);
exit_cleanup(1);
}
}
void close_batch_csums_file(void)
{
close(fdb);
close(f_csums);
f_csums = -1;
}
/**
* Write csum info to batch file
* Write csum info to batch file
*
* @todo This will break if s->count is ever larger than maxint. The
* batch code should probably be changed to consistently use the
* variable-length integer routines, which is probably a compatible
* change.
**/
void write_batch_csum_info(int *flist_entry, int flist_count,
struct sum_struct *s)
void write_batch_csum_info(int *flist_entry, struct sum_struct *s)
{
size_t i;
int int_count;
extern int csum_length;
char filename[MAXPATHLEN];
fdb_open = 1;
if (f_csums < 0) {
stringjoin(filename, sizeof filename,
batch_prefix, rsync_csums_file, NULL);
write_batch_csums_file(flist_entry, sizeof(int));
f_csums = do_open(filename, O_WRONLY | O_CREAT | O_TRUNC,
S_IRUSR | S_IWUSR);
if (f_csums < 0) {
rprintf(FERROR, "Batch file %s open error: %s\n",
filename, strerror(errno));
close(f_csums);
exit_cleanup(1);
}
}
write_batch_csums_file(flist_entry, sizeof (int));
int_count = s ? (int) s->count : 0;
write_batch_csums_file(&int_count, sizeof int_count);
if (s) {
for (i = 0; i < s->count; i++) {
write_batch_csums_file(&s->sums[i].sum1, sizeof(uint32));
if ((*flist_entry == flist_count - 1)
&& (i == s->count - 1)) {
fdb_close = 1;
}
write_batch_csums_file(&s->sums[i].sum1,
sizeof (uint32));
write_batch_csums_file(s->sums[i].sum2, csum_length);
}
}
@@ -423,37 +218,13 @@ void write_batch_csum_info(int *flist_entry, int flist_count,
int read_batch_csums_file(char *buff, int len)
{
static int fdb_open = 1;
int bytes_read;
char filename[MAXPATHLEN];
if (fdb_open) {
/* Set up file extension */
strlcpy(filename, batch_prefix, sizeof(filename));
strlcat(filename, rsync_csums_file, sizeof(filename));
/* Open batch flist file for reading */
fdb = do_open(filename, O_RDONLY, 0);
if (fdb == -1) {
rprintf(FERROR, "Batch file %s open error: %s\n",
filename, strerror(errno));
close(fdb);
exit_cleanup(1);
}
fdb_open = 0;
}
/* Read csums batch file */
bytes_read = read(fdb, buff, len);
if (bytes_read == -1) {
rprintf(FERROR, "Batch file %s read error: %s\n",
filename, strerror(errno));
close(fdb);
if ((bytes_read = read(f_csums, buff, len)) < 0) {
rprintf(FERROR, "Batch file read error: %s\n", strerror(errno));
close(f_csums);
exit_cleanup(1);
}
return bytes_read;
}
@@ -465,104 +236,97 @@ void read_batch_csum_info(int flist_entry, struct sum_struct *s,
int file_chunk_ct;
uint32 file_sum1;
char file_sum2[SUM_LENGTH];
extern int csum_length;
char filename[MAXPATHLEN];
read_batch_csums_file((char *) &file_flist_entry, sizeof(int));
if (f_csums < 0) {
stringjoin(filename, sizeof filename,
batch_prefix, rsync_csums_file, NULL);
f_csums = do_open(filename, O_RDONLY, 0);
if (f_csums < 0) {
rprintf(FERROR, "Batch file %s open error: %s\n",
filename, strerror(errno));
close(f_csums);
exit_cleanup(1);
}
}
read_batch_csums_file((char *) &file_flist_entry, sizeof (int));
if (file_flist_entry != flist_entry) {
rprintf(FINFO, "file_flist_entry (%d) != flist_entry (%d)\n",
file_flist_entry, flist_entry);
close(fdb);
file_flist_entry, flist_entry);
close(f_csums);
exit_cleanup(1);
} else {
read_batch_csums_file((char *) &file_chunk_ct,
sizeof(int));
read_batch_csums_file((char *) &file_chunk_ct, sizeof (int));
*checksums_match = 1;
for (i = 0; i < file_chunk_ct; i++) {
read_batch_csums_file((char *) &file_sum1,
sizeof(uint32));
sizeof (uint32));
read_batch_csums_file(file_sum2, csum_length);
if ((s->sums[i].sum1 != file_sum1) ||
(memcmp(s->sums[i].sum2, file_sum2, csum_length)
!= 0)) {
if ((s->sums[i].sum1 != file_sum1)
|| memcmp(s->sums[i].sum2, file_sum2, csum_length))
*checksums_match = 0;
}
} /* end for */
}
}
void write_batch_delta_file(char *buff, int bytes_to_write)
{
static int fdb_delta_open = 1;
char filename[MAXPATHLEN];
if (fdb_delta_open) {
/* Set up file extension */
strlcpy(filename, batch_prefix, sizeof(filename));
strlcat(filename, rsync_delta_file, sizeof(filename));
if (f_delta < 0) {
stringjoin(filename, sizeof filename,
batch_prefix, rsync_delta_file, NULL);
/*
* Open batch delta file for writing;
* create it if it doesn't exist
*/
fdb_delta = do_open(filename, O_WRONLY | O_CREAT | O_TRUNC,
S_IREAD | S_IWRITE);
if (fdb_delta == -1) {
f_delta = do_open(filename, O_WRONLY | O_CREAT | O_TRUNC,
S_IRUSR | S_IWUSR);
if (f_delta < 0) {
rprintf(FERROR, "Batch file %s open error: %s\n",
filename, strerror(errno));
close(fdb_delta);
exit_cleanup(1);
}
fdb_delta_open = 0;
}
/* Write buffer to batch delta file */
if (write(fdb_delta, buff, bytes_to_write) == -1) {
if (write(f_delta, buff, bytes_to_write) < 0) {
rprintf(FERROR, "Batch file %s write error: %s\n",
filename, strerror(errno));
close(fdb_delta);
filename, strerror(errno));
close(f_delta);
exit_cleanup(1);
}
}
void close_batch_delta_file(void)
{
close(fdb_delta);
close(f_delta);
f_delta = -1;
}
int read_batch_delta_file(char *buff, int len)
{
static int fdb_delta_open = 1;
int bytes_read;
char filename[MAXPATHLEN];
if (fdb_delta_open) {
/* Set up file extension */
strlcpy(filename, batch_prefix, sizeof(filename));
strlcat(filename, rsync_delta_file, sizeof(filename));
if (f_delta < 0) {
stringjoin(filename, sizeof filename,
batch_prefix, rsync_delta_file, NULL);
/* Open batch flist file for reading */
fdb_delta = do_open(filename, O_RDONLY, 0);
if (fdb_delta == -1) {
f_delta = do_open(filename, O_RDONLY, 0);
if (f_delta < 0) {
rprintf(FERROR, "Batch file %s open error: %s\n",
filename, strerror(errno));
close(fdb_delta);
filename, strerror(errno));
close(f_delta);
exit_cleanup(1);
}
fdb_delta_open = 0;
}
/* Read delta batch file */
bytes_read = read(fdb_delta, buff, len);
if (bytes_read == -1) {
bytes_read = read(f_delta, buff, len);
if (bytes_read < 0) {
rprintf(FERROR, "Batch file %s read error: %s\n",
filename, strerror(errno));
close(fdb_delta);
filename, strerror(errno));
close(f_delta);
exit_cleanup(1);
}

View File

@@ -23,7 +23,7 @@ int csum_length=2; /* initial value */
#define CSUM_CHUNK 64
int checksum_seed = 0;
extern int checksum_seed;
extern int protocol_version;
/*

View File

@@ -72,7 +72,7 @@ static char *cleanup_new_fname;
static struct file_struct *cleanup_file;
static int cleanup_fd1, cleanup_fd2;
static struct map_struct *cleanup_buf;
static int cleanup_pid = 0;
static pid_t cleanup_pid = 0;
extern int io_error;
pid_t cleanup_child_pid = -1;
@@ -118,13 +118,13 @@ void _exit_cleanup(int code, const char *file, int line)
if (cleanup_fd2 != -1) close(cleanup_fd2);
finish_transfer(cleanup_new_fname, fname, cleanup_file);
}
io_flush();
io_flush(FULL_FLUSH);
if (cleanup_fname)
do_unlink(cleanup_fname);
if (code) {
kill_all(SIGUSR1);
}
if ((cleanup_pid != 0) && (cleanup_pid == (int) getpid())) {
if (cleanup_pid && cleanup_pid == getpid()) {
char *pidf = lp_pid_file();
if (pidf && *pidf) {
unlink(lp_pid_file());
@@ -166,7 +166,7 @@ void cleanup_set(char *fnametmp, char *fname, struct file_struct *file,
cleanup_fd2 = fd2;
}
void cleanup_set_pid(int pid)
void cleanup_set_pid(pid_t pid)
{
cleanup_pid = pid;
}

View File

@@ -1,20 +1,20 @@
/* -*- 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.
@@ -22,7 +22,7 @@
/**
* @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()
@@ -39,7 +39,7 @@ extern int am_server;
/**
* Return the IP addr of the client as a string
* Return the IP addr of the client as a string
**/
char *client_addr(int fd)
{
@@ -50,19 +50,18 @@ char *client_addr(int fd)
static char addr_buf[100];
static int initialised;
if (initialised) return addr_buf;
if (initialised)
return addr_buf;
initialised = 1;
if (am_server) {
/* daemon over --rsh mode */
if (am_server) { /* daemon over --rsh mode */
strcpy(addr_buf, "0.0.0.0");
if ((ssh_client = getenv("SSH_CLIENT")) != NULL) {
/* truncate SSH_CLIENT to just IP address */
p = strchr(ssh_client, ' ');
if (p) {
len = MIN((unsigned int) (p - ssh_client),
sizeof(addr_buf) - 1);
if ((p = strchr(ssh_client, ' ')) != NULL) {
len = MIN((unsigned int) (p - ssh_client),
sizeof addr_buf - 1);
strncpy(addr_buf, ssh_client, len);
*(addr_buf + len) = '\0';
}
@@ -101,58 +100,56 @@ char *client_name(int fd)
static char name_buf[100];
static char port_buf[100];
static int initialised;
struct sockaddr_storage ss, *ssp;
struct sockaddr_in sin;
#ifdef INET6
struct sockaddr_in6 sin6;
#endif
struct sockaddr_storage ss;
socklen_t ss_len;
if (initialised) return name_buf;
if (initialised)
return name_buf;
strcpy(name_buf, default_name);
initialised = 1;
if (am_server) {
/* daemon over --rsh mode */
memset(&ss, 0, sizeof ss);
if (am_server) { /* daemon over --rsh mode */
char *addr = client_addr(fd);
#ifdef INET6
int dots = 0;
char *p;
struct addrinfo hint, *answer;
int err;
for (p = addr; *p && (dots <= 3); p++) {
if (*p == '.')
dots++;
}
if (dots > 3) {
/* more than 4 parts to IP address, must be ipv6 */
ssp = (struct sockaddr_storage *) &sin6;
ss_len = sizeof sin6;
memset(ssp, 0, ss_len);
inet_pton(AF_INET6, addr, &sin6.sin6_addr);
sin6.sin6_family = AF_INET6;
} else
memset(&hint, 0, sizeof hint);
#ifdef AI_NUMERICHOST
hint.ai_flags = AI_NUMERICHOST;
#endif
{
ssp = (struct sockaddr_storage *) &sin;
ss_len = sizeof sin;
memset(ssp, 0, ss_len);
inet_pton(AF_INET, addr, &sin.sin_addr);
sin.sin_family = AF_INET;
hint.ai_socktype = SOCK_STREAM;
if ((err = getaddrinfo(addr, NULL, &hint, &answer)) != 0) {
rprintf(FERROR, RSYNC_NAME ": malformed address %s: %s\n",
addr, gai_strerror(err));
return name_buf;
}
switch (answer->ai_family) {
case AF_INET:
ss_len = sizeof (struct sockaddr_in);
memcpy(&ss, answer->ai_addr, ss_len);
break;
#ifdef INET6
case AF_INET6:
ss_len = sizeof (struct sockaddr_in6);
memcpy(&ss, answer->ai_addr, ss_len);
break;
#endif
}
freeaddrinfo(answer);
} else {
ss_len = sizeof ss;
ssp = &ss;
client_sockaddr(fd, &ss, &ss_len);
}
if (!lookup_name(fd, ssp, ss_len, name_buf, sizeof name_buf,
if (!lookup_name(fd, &ss, ss_len, name_buf, sizeof name_buf,
port_buf, sizeof port_buf))
check_name(fd, ssp, name_buf);
check_name(fd, &ss, name_buf);
return name_buf;
}
@@ -169,7 +166,7 @@ void client_sockaddr(int fd,
struct sockaddr_storage *ss,
socklen_t *ss_len)
{
memset(ss, 0, sizeof(*ss));
memset(ss, 0, sizeof *ss);
if (getpeername(fd, (struct sockaddr *) ss, ss_len)) {
/* FIXME: Can we really not continue? */
@@ -179,7 +176,7 @@ void client_sockaddr(int fd,
}
#ifdef INET6
if (get_sockaddr_family(ss) == AF_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
@@ -190,12 +187,12 @@ void client_sockaddr(int fd,
struct sockaddr_in6 sin6;
struct sockaddr_in *sin;
memcpy(&sin6, ss, sizeof(sin6));
memcpy(&sin6, ss, sizeof sin6);
sin = (struct sockaddr_in *)ss;
memset(sin, 0, sizeof(*sin));
memset(sin, 0, sizeof *sin);
sin->sin_family = AF_INET;
*ss_len = sizeof(struct sockaddr_in);
#ifdef HAVE_SOCKADDR_LEN
*ss_len = sizeof (struct sockaddr_in);
#if HAVE_SOCKADDR_IN_LEN
sin->sin_len = *ss_len;
#endif
sin->sin_port = sin6.sin6_port;
@@ -204,8 +201,8 @@ void client_sockaddr(int fd,
* (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));
}
sizeof sin->sin_addr);
}
#endif
}
@@ -221,7 +218,7 @@ int lookup_name(int fd, const struct sockaddr_storage *ss,
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,
@@ -250,7 +247,7 @@ int compare_addrinfo_sockaddr(const struct addrinfo *ai,
{
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",
@@ -264,18 +261,19 @@ int compare_addrinfo_sockaddr(const struct addrinfo *ai,
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) {
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;
if (ai->ai_addrlen < sizeof(struct sockaddr_in6)) {
if (ai->ai_addrlen < sizeof (struct sockaddr_in6)) {
rprintf(FERROR,
"%s: too short sockaddr_in6; length=%d\n",
fn, ai->ai_addrlen);
@@ -293,10 +291,9 @@ int compare_addrinfo_sockaddr(const struct addrinfo *ai,
return 0;
}
#endif /* INET6 */
else {
/* don't know */
return 1;
}
/* don't know */
return 1;
}
@@ -318,7 +315,7 @@ int check_name(int fd,
int error;
int ss_family = get_sockaddr_family(ss);
memset(&hints, 0, sizeof(hints));
memset(&hints, 0, sizeof hints);
hints.ai_family = ss_family;
hints.ai_flags = AI_CANONNAME;
hints.ai_socktype = SOCK_STREAM;

View File

@@ -27,17 +27,31 @@
#include "rsync.h"
extern int am_sender;
extern int am_server;
extern int am_daemon;
extern int am_root;
extern int module_id;
extern int read_only;
extern int verbose;
extern int rsync_port;
char *auth_user;
extern int kludge_around_eof;
extern int daemon_over_rsh;
extern int list_only;
extern int sanitize_paths;
extern int filesfrom_fd;
extern int remote_protocol;
extern int protocol_version;
extern struct exclude_struct **server_exclude_list;
extern int io_timeout;
extern int orig_umask;
extern int no_detach;
extern int default_af_hint;
extern char *bind_address;
extern struct exclude_list_struct server_exclude_list;
extern char *exclude_path_prefix;
extern char *config_file;
char *auth_user;
/**
* Run a client connected to an rsyncd. The alternative to this
@@ -57,8 +71,6 @@ int start_socket_client(char *host, char *path, int argc, char *argv[])
{
int fd, ret;
char *p, *user=NULL;
extern char *bind_address;
extern int default_af_hint;
/* this is redundant with code in start_inband_exchange(), but
* this short-circuits a problem before we open a socket, and
@@ -75,18 +87,10 @@ int start_socket_client(char *host, char *path, int argc, char *argv[])
*p = 0;
}
if (verbose >= 2) {
/* FIXME: If we're going to use a socket program for
* testing, then this message is wrong. We need to
* say something like "(except really using %s)" */
rprintf(FINFO, "opening tcp connection to %s port %d\n",
host, rsync_port);
}
fd = open_socket_out_wrapped(host, rsync_port, bind_address,
default_af_hint);
if (fd == -1) {
if (fd == -1)
exit_cleanup(RERR_SOCKETIO);
}
ret = start_inband_exchange(user, path, fd, fd, argc);
@@ -100,10 +104,6 @@ int start_inband_exchange(char *user, char *path, int f_in, int f_out, int argc)
int sargc = 0;
char line[MAXPATHLEN];
char *p;
extern int kludge_around_eof;
extern int am_sender;
extern int daemon_over_rsh;
extern int list_only;
if (argc == 0 && !am_sender)
list_only = 1;
@@ -129,7 +129,7 @@ int start_inband_exchange(char *user, char *path, int f_in, int f_out, int argc)
sargs[sargc] = NULL;
io_printf(f_out, "@RSYNCD: %d\n", PROTOCOL_VERSION);
io_printf(f_out, "@RSYNCD: %d\n", protocol_version);
if (!read_line(f_in, line, sizeof(line)-1)) {
rprintf(FERROR, "rsync: did not see server greeting\n");
@@ -192,7 +192,7 @@ int start_inband_exchange(char *user, char *path, int f_in, int f_out, int argc)
io_printf(f_out, "\n");
if (protocol_version < 23) {
if (protocol_version == 22 || (protocol_version > 17 && !am_sender))
if (protocol_version == 22 || !am_sender)
io_start_multiplex_in(f_in);
}
@@ -217,10 +217,6 @@ static int rsync_module(int f_in, int f_out, int i)
int start_glob=0;
int ret;
char *request=NULL;
extern int am_sender;
extern int am_server;
extern int am_daemon;
extern int am_root;
if (!allow_access(addr, host, lp_hosts_allow(i), lp_hosts_deny(i))) {
rprintf(FERROR,"rsync denied on module %s from %s (%s)\n",
@@ -262,7 +258,7 @@ static int rsync_module(int f_in, int f_out, int i)
module_id = i;
am_root = (getuid() == 0);
am_root = (MY_UID() == 0);
if (am_root) {
p = lp_uid(i);
@@ -298,16 +294,19 @@ static int rsync_module(int f_in, int f_out, int i)
exclude_path_prefix = "";
p = lp_include_from(i);
add_exclude_file(&server_exclude_list, p, MISSING_FATAL, ADD_INCLUDE);
add_exclude_file(&server_exclude_list, p,
XFLG_FATAL_ERRORS | XFLG_DEF_INCLUDE);
p = lp_include(i);
add_exclude_line(&server_exclude_list, p, ADD_INCLUDE);
add_exclude(&server_exclude_list, p,
XFLG_WORD_SPLIT | XFLG_DEF_INCLUDE);
p = lp_exclude_from(i);
add_exclude_file(&server_exclude_list, p, MISSING_FATAL, ADD_EXCLUDE);
add_exclude_file(&server_exclude_list, p,
XFLG_FATAL_ERRORS);
p = lp_exclude(i);
add_exclude_line(&server_exclude_list, p, ADD_EXCLUDE);
add_exclude(&server_exclude_list, p, XFLG_WORD_SPLIT);
exclude_path_prefix = NULL;
@@ -332,14 +331,14 @@ static int rsync_module(int f_in, int f_out, int i)
return -1;
}
if (!push_dir("/", 0)) {
if (!push_dir("/")) {
rsyserr(FERROR, errno, "chdir %s failed\n", lp_path(i));
io_printf(f_out, "@ERROR: chdir failed\n");
return -1;
}
} else {
if (!push_dir(lp_path(i), 0)) {
if (!push_dir(lp_path(i))) {
rsyserr(FERROR, errno, "chdir %s failed\n", lp_path(i));
io_printf(f_out, "@ERROR: chdir failed\n");
return -1;
@@ -379,7 +378,7 @@ static int rsync_module(int f_in, int f_out, int i)
return -1;
}
am_root = (getuid() == 0);
am_root = (MY_UID() == 0);
}
io_printf(f_out, "@RSYNCD: OK\n");
@@ -419,19 +418,6 @@ static int rsync_module(int f_in, int f_out, int i)
}
}
if (sanitize_paths) {
/*
* Note that this is applied to all parameters, whether or not
* they are filenames, but no other legal parameters contain
* the forms that need to be sanitized so it doesn't hurt;
* it is not known at this point which parameters are files
* and which aren't.
*/
for (i = 1; i < argc; i++) {
sanitize_path(argv[i], NULL);
}
}
argp = argv;
ret = parse_arguments(&argc, (const char ***) &argp, 0);
@@ -453,11 +439,12 @@ static int rsync_module(int f_in, int f_out, int i)
#ifndef DEBUG
/* don't allow the logs to be flooded too fast */
if (verbose > 1) verbose = 1;
if (verbose > lp_max_verbosity())
verbose = lp_max_verbosity();
#endif
if (protocol_version < 23) {
if (protocol_version == 22 || (protocol_version > 17 && am_sender))
if (protocol_version == 22 || am_sender)
io_start_multiplex_out(f_out);
}
@@ -475,7 +462,6 @@ static int rsync_module(int f_in, int f_out, int i)
}
if (lp_timeout(i)) {
extern int io_timeout;
io_timeout = lp_timeout(i);
}
@@ -507,8 +493,6 @@ int start_daemon(int f_in, int f_out)
char line[200];
char *motd;
int i = -1;
extern char *config_file;
extern int am_server;
if (!lp_load(config_file, 0)) {
exit_cleanup(RERR_SYNTAX);
@@ -522,7 +506,7 @@ int start_daemon(int f_in, int f_out)
set_nonblocking(f_in);
}
io_printf(f_out, "@RSYNCD: %d\n", PROTOCOL_VERSION);
io_printf(f_out, "@RSYNCD: %d\n", protocol_version);
motd = lp_motd_file();
if (motd && *motd) {
@@ -579,10 +563,7 @@ int start_daemon(int f_in, int f_out)
int daemon_main(void)
{
extern char *config_file;
extern int orig_umask;
char *pid_file;
extern int no_detach;
if (is_a_socket(STDIN_FILENO)) {
int i;
@@ -616,7 +597,7 @@ int daemon_main(void)
if (((pid_file = lp_pid_file()) != NULL) && (*pid_file != '\0')) {
char pidbuf[16];
int fd;
int pid = (int) getpid();
pid_t pid = getpid();
cleanup_set_pid(pid);
if ((fd = do_open(lp_pid_file(), O_WRONLY|O_CREAT|O_TRUNC,
0666 & ~orig_umask)) == -1) {
@@ -624,7 +605,7 @@ int daemon_main(void)
rsyserr(FLOG, errno, "failed to create pid file %s", pid_file);
exit_cleanup(RERR_FILEIO);
}
snprintf(pidbuf, sizeof(pidbuf), "%d\n", pid);
snprintf(pidbuf, sizeof pidbuf, "%ld\n", (long)pid);
write(fd, pidbuf, strlen(pidbuf));
close(fd);
}

View File

@@ -38,7 +38,6 @@ extern int preserve_times;
extern int always_checksum;
extern int checksum_seed;
extern int protocol_version;
extern int verbose;
@@ -85,11 +84,9 @@ void setup_protocol(int f_out,int f_in)
}
if (am_server) {
if (read_batch || write_batch)
checksum_seed = 32761;
else
if (!checksum_seed)
checksum_seed = time(NULL);
write_int(f_out,checksum_seed);
write_int(f_out, checksum_seed);
} else {
checksum_seed = read_int(f_in);
}

133
config.guess vendored
View File

@@ -3,7 +3,7 @@
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
# 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
timestamp='2003-01-10'
timestamp='2003-10-03'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
@@ -106,6 +106,7 @@ trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
: ${TMPDIR=/tmp} ;
{ tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
{ test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
{ tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
{ echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
dummy=$tmp/dummy ;
tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
@@ -235,74 +236,56 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
*:OpenBSD:*:*)
echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE}
exit 0 ;;
*:MicroBSD:*:*)
echo ${UNAME_MACHINE}-unknown-microbsd${UNAME_RELEASE}
exit 0 ;;
alpha:OSF1:*:*)
if test $UNAME_RELEASE = "V4.0"; then
UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
fi
# According to Compaq, /usr/sbin/psrinfo has been available on
# OSF/1 and Tru64 systems produced since 1995. I hope that
# covers most systems running today. This code pipes the CPU
# types through head -n 1, so we only detect the type of CPU 0.
ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
case "$ALPHA_CPU_TYPE" in
"EV4 (21064)")
UNAME_MACHINE="alpha" ;;
"EV4.5 (21064)")
UNAME_MACHINE="alpha" ;;
"LCA4 (21066/21068)")
UNAME_MACHINE="alpha" ;;
"EV5 (21164)")
UNAME_MACHINE="alphaev5" ;;
"EV5.6 (21164A)")
UNAME_MACHINE="alphaev56" ;;
"EV5.6 (21164PC)")
UNAME_MACHINE="alphapca56" ;;
"EV5.7 (21164PC)")
UNAME_MACHINE="alphapca57" ;;
"EV6 (21264)")
UNAME_MACHINE="alphaev6" ;;
"EV6.7 (21264A)")
UNAME_MACHINE="alphaev67" ;;
"EV6.8CB (21264C)")
UNAME_MACHINE="alphaev68" ;;
"EV6.8AL (21264B)")
UNAME_MACHINE="alphaev68" ;;
"EV6.8CX (21264D)")
UNAME_MACHINE="alphaev68" ;;
"EV6.9A (21264/EV69A)")
UNAME_MACHINE="alphaev69" ;;
"EV7 (21364)")
UNAME_MACHINE="alphaev7" ;;
"EV7.9 (21364A)")
UNAME_MACHINE="alphaev79" ;;
esac
# A Vn.n version is a released version.
# A Tn.n version is a released field test version.
# A Xn.n version is an unreleased experimental baselevel.
# 1.2 uses "1.2" for uname -r.
eval $set_cc_for_build
cat <<EOF >$dummy.s
.data
\$Lformat:
.byte 37,100,45,37,120,10,0 # "%d-%x\n"
.text
.globl main
.align 4
.ent main
main:
.frame \$30,16,\$26,0
ldgp \$29,0(\$27)
.prologue 1
.long 0x47e03d80 # implver \$0
lda \$2,-1
.long 0x47e20c21 # amask \$2,\$1
lda \$16,\$Lformat
mov \$0,\$17
not \$1,\$18
jsr \$26,printf
ldgp \$29,0(\$26)
mov 0,\$16
jsr \$26,exit
.end main
EOF
$CC_FOR_BUILD -o $dummy $dummy.s 2>/dev/null
if test "$?" = 0 ; then
case `$dummy` in
0-0)
UNAME_MACHINE="alpha"
;;
1-0)
UNAME_MACHINE="alphaev5"
;;
1-1)
UNAME_MACHINE="alphaev56"
;;
1-101)
UNAME_MACHINE="alphapca56"
;;
2-303)
UNAME_MACHINE="alphaev6"
;;
2-307)
UNAME_MACHINE="alphaev67"
;;
2-1307)
UNAME_MACHINE="alphaev68"
;;
3-1307)
UNAME_MACHINE="alphaev7"
;;
esac
fi
echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
exit 0 ;;
Alpha*:OpenVMS:*:*)
echo alpha-hp-vms
exit 0 ;;
Alpha\ *:Windows_NT*:*)
# How do we know it's Interix rather than the generic POSIX subsystem?
# Should we change UNAME_MACHINE based on the output of uname instead
@@ -341,6 +324,9 @@ EOF
NILE*:*:*:dcosx)
echo pyramid-pyramid-svr4
exit 0 ;;
DRS?6000:unix:4.0:6*)
echo sparc-icl-nx6
exit 0 ;;
DRS?6000:UNIX_SV:4.2*:7*)
case `/usr/bin/uname -p` in
sparc) echo sparc-icl-nx7 && exit 0 ;;
@@ -748,7 +734,7 @@ EOF
echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
exit 0 ;;
*:UNICOS/mp:*:*)
echo nv1-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
echo nv1-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
exit 0 ;;
F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
@@ -765,7 +751,7 @@ EOF
*:BSD/OS:*:*)
echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
exit 0 ;;
*:FreeBSD:*:*)
*:FreeBSD:*:*|*:GNU/FreeBSD:*:*)
# Determine whether the default compiler uses glibc.
eval $set_cc_for_build
sed 's/^ //' << EOF >$dummy.c
@@ -777,7 +763,10 @@ EOF
#endif
EOF
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`${LIBC:+-$LIBC}
# GNU/FreeBSD systems have a "k" prefix to indicate we are using
# FreeBSD's kernel, but not the complete OS.
case ${LIBC} in gnu) kernel_only='k' ;; esac
echo ${UNAME_MACHINE}-unknown-${kernel_only}freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`${LIBC:+-$LIBC}
exit 0 ;;
i*:CYGWIN*:*)
echo ${UNAME_MACHINE}-pc-cygwin
@@ -788,8 +777,8 @@ EOF
i*:PW*:*)
echo ${UNAME_MACHINE}-pc-pw32
exit 0 ;;
x86:Interix*:3*)
echo i586-pc-interix3
x86:Interix*:[34]*)
echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//'
exit 0 ;;
[345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
echo i${UNAME_MACHINE}-pc-mks
@@ -818,6 +807,9 @@ EOF
arm*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
exit 0 ;;
cris:Linux:*:*)
echo cris-axis-linux-gnu
exit 0 ;;
ia64:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
exit 0 ;;
@@ -896,6 +888,9 @@ EOF
s390:Linux:*:* | s390x:Linux:*:*)
echo ${UNAME_MACHINE}-ibm-linux
exit 0 ;;
sh64*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
exit 0 ;;
sh*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
exit 0 ;;
@@ -953,6 +948,9 @@ EOF
LIBC=gnuaout
#endif
#endif
#ifdef __dietlibc__
LIBC=dietlibc
#endif
EOF
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0
@@ -1054,7 +1052,7 @@ EOF
exit 0 ;;
M68*:*:R3V[567]*:*)
test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0)
3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0)
OS_REL=''
test -r /etc/.relid \
&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
@@ -1169,7 +1167,7 @@ EOF
*:QNX:*:4*)
echo i386-pc-qnx
exit 0 ;;
NSR-[DGKLNPTVW]:NONSTOP_KERNEL:*:*)
NSR-[DGKLNPTVWY]:NONSTOP_KERNEL:*:*)
echo nsr-tandem-nsk${UNAME_RELEASE}
exit 0 ;;
*:NonStop-UX:*:*)
@@ -1210,6 +1208,9 @@ EOF
*:ITS:*:*)
echo pdp10-unknown-its
exit 0 ;;
SEI:*:*:SEIUX)
echo mips-sei-seiux${UNAME_RELEASE}
exit 0 ;;
esac
#echo '(No uname command or uname output not recognized.)' 1>&2

72
config.sub vendored
View File

@@ -3,7 +3,7 @@
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
# 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
timestamp='2003-01-22'
timestamp='2003-08-18'
# This file is (in principle) common to ALL GNU software.
# The presence of a machine in this file suggests that SOME GNU software
@@ -118,7 +118,7 @@ esac
# Here we must recognize all the valid KERNEL-OS combinations.
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
case $maybe_os in
nto-qnx* | linux-gnu* | freebsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*)
nto-qnx* | linux-gnu* | linux-dietlibc | kfreebsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*)
os=-$maybe_os
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
;;
@@ -228,13 +228,14 @@ case $basic_machine in
| a29k \
| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
| am33_2.0 \
| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
| clipper \
| c4x | clipper \
| d10v | d30v | dlx | dsp16xx \
| fr30 | frv \
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
| i370 | i860 | i960 | ia64 \
| ip2k \
| ip2k | iq2000 \
| m32r | m68000 | m68k | m88k | mcore \
| mips | mipsbe | mipseb | mipsel | mipsle \
| mips16 \
@@ -247,6 +248,7 @@ case $basic_machine in
| mipsisa32 | mipsisa32el \
| mipsisa32r2 | mipsisa32r2el \
| mipsisa64 | mipsisa64el \
| mipsisa64r2 | mipsisa64r2el \
| mipsisa64sb1 | mipsisa64sb1el \
| mipsisa64sr71k | mipsisa64sr71kel \
| mipstx39 | mipstx39el \
@@ -257,11 +259,11 @@ case $basic_machine in
| pdp10 | pdp11 | pj | pjl \
| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
| pyramid \
| sh | sh[1234] | sh3e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
| sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
| sh64 | sh64le \
| sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \
| strongarm \
| tahoe | thumb | tic80 | tron \
| tahoe | thumb | tic4x | tic80 | tron \
| v850 | v850e \
| we32k \
| x86 | xscale | xstormy16 | xtensa \
@@ -296,7 +298,7 @@ case $basic_machine in
| arm-* | armbe-* | armle-* | armeb-* | armv*-* \
| avr-* \
| bs2000-* \
| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* \
| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
| clipper-* | cydra-* \
| d10v-* | d30v-* | dlx-* \
| elxsi-* \
@@ -304,7 +306,7 @@ case $basic_machine in
| h8300-* | h8500-* \
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
| i*86-* | i860-* | i960-* | ia64-* \
| ip2k-* \
| ip2k-* | iq2000-* \
| m32r-* \
| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
| m88110-* | m88k-* | mcore-* \
@@ -319,6 +321,7 @@ case $basic_machine in
| mipsisa32-* | mipsisa32el-* \
| mipsisa32r2-* | mipsisa32r2el-* \
| mipsisa64-* | mipsisa64el-* \
| mipsisa64r2-* | mipsisa64r2el-* \
| mipsisa64sb1-* | mipsisa64sb1el-* \
| mipsisa64sr71k-* | mipsisa64sr71kel-* \
| mipstx39-* | mipstx39el-* \
@@ -329,11 +332,13 @@ case $basic_machine in
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
| pyramid-* \
| romp-* | rs6000-* \
| sh-* | sh[1234]-* | sh3e-* | sh[34]eb-* | shbe-* \
| sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \
| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
| sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \
| sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
| tahoe-* | thumb-* | tic30-* | tic4x-* | tic54x-* | tic80-* | tron-* \
| tahoe-* | thumb-* \
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
| tron-* \
| v850-* | v850e-* | vax-* \
| we32k-* \
| x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \
@@ -371,6 +376,9 @@ case $basic_machine in
basic_machine=a29k-none
os=-bsd
;;
amd64)
basic_machine=x86_64-pc
;;
amdahl)
basic_machine=580-amdahl
os=-sysv
@@ -766,18 +774,24 @@ case $basic_machine in
pentiumpro | p6 | 6x86 | athlon | athlon_*)
basic_machine=i686-pc
;;
pentiumii | pentium2)
pentiumii | pentium2 | pentiumiii | pentium3)
basic_machine=i686-pc
;;
pentium4)
basic_machine=i786-pc
;;
pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
pentiumpro-* | p6-* | 6x86-* | athlon-*)
basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
pentiumii-* | pentium2-*)
pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
pentium4-*)
basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
pn)
basic_machine=pn-gould
;;
@@ -836,6 +850,10 @@ case $basic_machine in
sb1el)
basic_machine=mipsisa64sb1el-unknown
;;
sei)
basic_machine=mips-sei
os=-seiux
;;
sequent)
basic_machine=i386-sequent
;;
@@ -843,6 +861,9 @@ case $basic_machine in
basic_machine=sh-hitachi
os=-hms
;;
sh64)
basic_machine=sh64-unknown
;;
sparclite-wrs | simso-wrs)
basic_machine=sparclite-wrs
os=-vxworks
@@ -917,14 +938,18 @@ case $basic_machine in
basic_machine=t90-cray
os=-unicos
;;
tic4x | c4x*)
basic_machine=tic4x-unknown
os=-coff
;;
tic54x | c54x*)
basic_machine=tic54x-unknown
os=-coff
;;
tic55x | c55x*)
basic_machine=tic55x-unknown
os=-coff
;;
tic6x | c6x*)
basic_machine=tic6x-unknown
os=-coff
;;
tx39)
basic_machine=mipstx39-unknown
;;
@@ -1027,7 +1052,7 @@ case $basic_machine in
we32k)
basic_machine=we32k-att
;;
sh3 | sh4 | sh3eb | sh4eb | sh[1234]le | sh3ele)
sh3 | sh4 | sh[34]eb | sh[1234]le | sh[23]ele)
basic_machine=sh-unknown
;;
sh64)
@@ -1106,7 +1131,7 @@ case $os in
| -aos* \
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
| -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \
| -hiux* | -386bsd* | -netbsd* | -openbsd* | -kfreebsd* | -freebsd* | -riscix* \
| -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
@@ -1118,7 +1143,7 @@ case $os in
| -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
| -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
| -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
| -powermax* | -dnix* | -microbsd*)
| -powermax* | -dnix* | -nx6 | -nx7 | -sei*)
# Remember, each alternative MUST END IN *, to match a version number.
;;
-qnx*)
@@ -1142,6 +1167,9 @@ case $os in
-mac*)
os=`echo $os | sed -e 's|mac|macos|'`
;;
-linux-dietlibc)
os=-linux-dietlibc
;;
-linux*)
os=`echo $os | sed -e 's|linux|linux-gnu|'`
;;
@@ -1230,6 +1258,9 @@ case $os in
-aros*)
os=-aros
;;
-kaos*)
os=-kaos
;;
-none)
;;
*)
@@ -1261,6 +1292,9 @@ case $basic_machine in
arm*-semi)
os=-aout
;;
c4x-* | tic4x-*)
os=-coff
;;
# This must come before the *-dec entry.
pdp10-*)
os=-tops20

View File

@@ -5,7 +5,7 @@ AC_CONFIG_SRCDIR([byteorder.h])
AC_CONFIG_HEADER(config.h)
AC_PREREQ(2.52)
RSYNC_VERSION=2.6.0
RSYNC_VERSION=2.6.2
AC_SUBST(RSYNC_VERSION)
AC_MSG_NOTICE([Configuring rsync $RSYNC_VERSION])
@@ -18,6 +18,7 @@ AC_CANONICAL_TARGET([])
dnl Checks for programs.
AC_PROG_CC
AC_PROG_CPP
AC_PROG_EGREP
AC_PROG_INSTALL
AC_PROG_CC_STDC
AC_SUBST(SHELL)
@@ -96,6 +97,27 @@ AC_ARG_WITH(rsync-path,
AC_DEFINE_UNQUOTED(RSYNC_PATH, "$RSYNC_PATH", [location of rsync on remote machine])
AC_ARG_WITH(rsyncd-conf,
AC_HELP_STRING([--with-rsyncd-conf=PATH], [set configuration file for rsync server to PATH (default: /etc/rsyncd.conf)]),
[ if test ! -z "$with_rsyncd_conf" ; then
case $with_rsyncd_conf in
yes|no)
RSYNCD_SYSCONF="/etc/rsyncd.conf"
;;
/*)
RSYNCD_SYSCONF="$with_rsyncd_conf"
;;
*)
AC_MSG_ERROR(You must specify an absolute path to --with-rsyncd-conf=PATH)
;;
esac
else
RSYNCD_SYSCONF="/etc/rsyncd.conf"
fi ],
[ RSYNCD_SYSCONF="/etc/rsyncd.conf" ])
AC_DEFINE_UNQUOTED(RSYNCD_SYSCONF, "$RSYNCD_SYSCONF", [location of configuration file for rsync server])
AC_ARG_WITH(rsh,
AC_HELP_STRING([--with-rsh=CMD], [set remote shell command to CMD (default: ssh)]))
@@ -121,24 +143,29 @@ AC_TRY_RUN([
#include <sys/types.h>
#include <sys/wait.h>
int main(void)
int main(void)
{
struct flock lock;
int status;
int fd = open("conftest.dat", O_CREAT|O_RDWR, 0600);
int status;
char tpl[32] = "/tmp/locktest.XXXXXX";
int fd = mkstemp(tpl);
if (fd < 0) {
strcpy(tpl, "conftest.dat");
fd = open(tpl, O_CREAT|O_RDWR, 0600);
}
lock.l_type = F_WRLCK;
lock.l_whence = SEEK_SET;
lock.l_start = 0;
lock.l_len = 1;
lock.l_pid = 0;
fcntl(fd,F_SETLK,&lock);
if (fork() == 0) {
lock.l_start = 1;
exit(fcntl(fd,F_SETLK,&lock) == 0);
}
wait(&status);
unlink("conftest.dat");
lock.l_start = 1;
_exit(fcntl(fd,F_SETLK,&lock) == 0);
}
wait(&status);
unlink(tpl);
exit(WEXITSTATUS(status));
}
],
@@ -151,7 +178,7 @@ ipv6type=unknown
ipv6lib=none
ipv6trylibc=yes
AC_ARG_ENABLE(ipv6,
AC_ARG_ENABLE(ipv6,
AC_HELP_STRING([--disable-ipv6], [don't even try to use IPv6]))
if test "x$enable_ipv6" != xno
@@ -177,7 +204,7 @@ yes
#ifdef __KAME__
yes
#endif],
[ipv6type=$i;
[ipv6type=$i;
AC_DEFINE(INET6, 1, [true if you have IPv6])])
;;
linux-glibc)
@@ -247,7 +274,7 @@ fi
AC_MSG_CHECKING([whether to call shutdown on all sockets])
case $host_os in
*cygwin* ) AC_MSG_RESULT(yes)
AC_DEFINE(SHUTDOWN_ALL_SOCKETS, 1,
AC_DEFINE(SHUTDOWN_ALL_SOCKETS, 1,
[Define if sockets need to be shutdown])
;;
* ) AC_MSG_RESULT(no);;
@@ -257,13 +284,12 @@ AC_C_BIGENDIAN
AC_HEADER_DIRENT
AC_HEADER_TIME
AC_HEADER_SYS_WAIT
AC_CHECK_HEADERS(sys/fcntl.h sys/select.h fcntl.h sys/time.h sys/unistd.h unistd.h utime.h grp.h)
AC_CHECK_HEADERS(compat.h sys/param.h ctype.h sys/wait.h sys/ioctl.h)
AC_CHECK_HEADERS(sys/filio.h string.h stdlib.h sys/socket.h sys/mode.h sys/un.h)
AC_CHECK_HEADERS(glob.h mcheck.h sys/sysctl.h arpa/inet.h arpa/nameser.h)
AC_CHECK_HEADERS(netdb.h)
AC_CHECK_HEADERS(malloc.h)
AC_CHECK_HEADERS(float.h)
AC_CHECK_HEADERS(sys/fcntl.h sys/select.h fcntl.h sys/time.h sys/unistd.h \
unistd.h utime.h grp.h compat.h sys/param.h ctype.h sys/wait.h \
sys/ioctl.h sys/filio.h string.h stdlib.h sys/socket.h sys/mode.h \
sys/un.h glob.h mcheck.h arpa/inet.h arpa/nameser.h \
netdb.h malloc.h float.h)
AC_HEADER_MAJOR
AC_CHECK_SIZEOF(int)
AC_CHECK_SIZEOF(long)
@@ -318,7 +344,7 @@ if test x"$ac_cv_func_connect" = x"no"; then
esac
dnl We can't just call AC_CHECK_FUNCS(connect) here, because the value
dnl has been cached.
if test x"$ac_cv_lib_socket_connect" = x"yes" ||
if test x"$ac_cv_lib_socket_connect" = x"yes" ||
test x"$ac_cv_lib_inet_connect" = x"yes"; then
# ac_cv_func_connect=yes
# don't! it would cause AC_CHECK_FUNC to succeed next time configure is run
@@ -330,8 +356,8 @@ AC_CHECK_LIB(resolv, inet_ntop)
dnl AC_MSG_NOTICE([Looking in libraries: $LIBS])
AC_CHECK_FUNCS(inet_ntop, , AC_LIBOBJ(lib/inet_ntop))
AC_CHECK_FUNCS(inet_pton, , AC_LIBOBJ(lib/inet_pton))
AC_CHECK_FUNCS(inet_ntop, , [AC_LIBOBJ(lib/inet_ntop)])
AC_CHECK_FUNCS(inet_pton, , [AC_LIBOBJ(lib/inet_pton)])
# Irix 6.5 has getaddrinfo but not the corresponding defines, so use
# builtin getaddrinfo if one of the defines don't exist
@@ -343,7 +369,7 @@ AC_CACHE_CHECK([whether defines needed by getaddrinfo exist],
#include <netdb.h>
#ifdef AI_PASSIVE
yes
#endif],
#endif],
rsync_cv_HAVE_GETADDR_DEFINES=yes,
rsync_cv_HAVE_GETADDR_DEFINES=no)])
if test x"$rsync_cv_HAVE_GETADDR_DEFINES" = x"yes"; then
@@ -360,32 +386,40 @@ if test x"$rsync_cv_HAVE_GETADDR_DEFINES" = x"yes"; then
[Define if you have the `getaddrinfo' function.])],
[AC_MSG_RESULT([no])
AC_LIBOBJ(lib/getaddrinfo)])])
AC_CHECK_FUNCS(getnameinfo, , AC_LIBOBJ(lib/getnameinfo))
AC_CHECK_FUNCS(getnameinfo, , [AC_LIBOBJ(lib/getnameinfo)])
else
AC_LIBOBJ(lib/getaddrinfo)
AC_LIBOBJ(lib/getnameinfo)
fi
AC_CHECK_MEMBER([struct sockaddr.sa_len],
[ AC_DEFINE(HAVE_SOCKADDR_LEN) ],
AC_CHECK_MEMBER([struct sockaddr.sa_len],
[ AC_DEFINE(HAVE_SOCKADDR_LEN, 1, [Do we have sockaddr.sa_len?]) ],
[],
[
#include <sys/types.h>
#include <sys/socket.h>
])
AC_CHECK_MEMBER([struct sockaddr_in.sin_len],
[ AC_DEFINE(HAVE_SOCKADDR_IN_LEN, 1, [Do we have sockaddr_in.sin_len?]) ],
[],
[
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
])
AC_MSG_CHECKING(struct sockaddr_storage)
AC_TRY_COMPILE([#include <sys/types.h>
#include <sys/socket.h>],
[struct sockaddr_storage x;],
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_SOCKADDR_STORAGE, 1,
AC_DEFINE(HAVE_SOCKADDR_STORAGE, 1,
[Define if you have strct sockaddr_storage.] ),
AC_MSG_RESULT(no))
AC_CHECK_MEMBER([struct sockaddr_in6.sin6_scope_id],
[ AC_DEFINE(HAVE_SOCKADDR_IN6_SCOPE_ID) ],
[ AC_DEFINE(HAVE_SOCKADDR_IN6_SCOPE_ID, 1, [Do we have sockaddr_in6.sin6_scope_id?]) ],
[],
[
#include <sys/types.h>
@@ -402,15 +436,15 @@ fi
dnl At the moment we don't test for a broken memcmp(), because all we
dnl need to do is test for equality, not comparison, and it seems that
dnl every platform has a memcmp that can do at least that.
dnl every platform has a memcmp that can do at least that.
dnl AC_FUNC_MEMCMP
AC_FUNC_UTIME_NULL
AC_FUNC_ALLOCA
AC_CHECK_FUNCS(waitpid wait4 getcwd strdup strerror chown chmod mknod mkfifo)
AC_CHECK_FUNCS(fchmod fstat strchr readlink link utime utimes strftime)
AC_CHECK_FUNCS(memmove lchown vsnprintf snprintf asprintf setsid glob strpbrk)
AC_CHECK_FUNCS(strlcat strlcpy strtol mtrace mallinfo setgroups)
AC_CHECK_FUNCS(waitpid wait4 getcwd strdup strerror chown chmod mknod mkfifo \
fchmod fstat strchr readlink link utime utimes strftime mtrace \
memmove lchown vsnprintf snprintf asprintf setsid glob strpbrk \
strlcat strlcpy strtol mallinfo getgroups setgroups geteuid getegid)
AC_CACHE_CHECK([for working socketpair],rsync_cv_HAVE_SOCKETPAIR,[
AC_TRY_RUN([
@@ -516,7 +550,7 @@ AC_CACHE_CHECK([for C99 vsnprintf],rsync_cv_HAVE_C99_VSNPRINTF,[
AC_TRY_RUN([
#include <sys/types.h>
#include <stdarg.h>
void foo(const char *format, ...) {
void foo(const char *format, ...) {
va_list ap;
int len;
char buf[5];
@@ -543,10 +577,10 @@ AC_TRY_RUN([#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
main() {
main() {
struct stat st;
char tpl[20]="/tmp/test.XXXXXX";
int fd = mkstemp(tpl);
char tpl[20]="/tmp/test.XXXXXX";
int fd = mkstemp(tpl);
if (fd == -1) exit(1);
unlink(tpl);
if (fstat(fd, &st) != 0) exit(1);
@@ -569,7 +603,7 @@ AC_TRY_RUN([
#include <arpa/inet.h>
main() { struct in_addr ip; ip.s_addr = 0x12345678;
if (strcmp(inet_ntoa(ip),"18.52.86.120") &&
strcmp(inet_ntoa(ip),"120.86.52.18")) { exit(1); }
strcmp(inet_ntoa(ip),"120.86.52.18")) { exit(1); }
exit(0);}],
rsync_cv_REPLACE_INET_NTOA=no,rsync_cv_REPLACE_INET_NTOA=yes,rsync_cv_REPLACE_INET_NTOA=cross)])
if test x"$rsync_cv_REPLACE_INET_NTOA" = x"yes"; then
@@ -583,7 +617,7 @@ AC_TRY_RUN([
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
main() { struct in_addr ip;
main() { struct in_addr ip;
if (inet_aton("example", &ip) == 0) exit(0); exit(1);}],
rsync_cv_REPLACE_INET_ATON=no,rsync_cv_REPLACE_INET_ATON=yes,rsync_cv_REPLACE_INET_ATON=cross)])
if test x"$rsync_cv_REPLACE_INET_ATON" = x"yes"; then

403
exclude.c
View File

@@ -27,57 +27,56 @@
#include "rsync.h"
extern int verbose;
extern int eol_nulls;
extern int list_only;
extern int recurse;
struct exclude_struct **exclude_list;
struct exclude_struct **local_exclude_list;
struct exclude_struct **server_exclude_list;
extern char curr_dir[];
struct exclude_list_struct exclude_list = { 0, 0, "" };
struct exclude_list_struct local_exclude_list = { 0, 0, "per-dir .cvsignore " };
struct exclude_list_struct server_exclude_list = { 0, 0, "server " };
char *exclude_path_prefix = NULL;
/** Build an exclude structure given a exclude pattern */
static struct exclude_struct *make_exclude(const char *pattern, int include)
static void make_exclude(struct exclude_list_struct *listp, const char *pattern,
int pat_len, int include)
{
struct exclude_struct *ret;
char *cp;
int pat_len;
const char *cp;
int ex_len;
ret = new(struct exclude_struct);
if (!ret) out_of_memory("make_exclude");
if (!ret)
out_of_memory("make_exclude");
memset(ret, 0, sizeof(*ret));
if (strncmp(pattern,"- ",2) == 0) {
pattern += 2;
} else if (strncmp(pattern,"+ ",2) == 0) {
ret->include = 1;
pattern += 2;
} else {
ret->include = include;
}
memset(ret, 0, sizeof ret[0]);
ret->include = include;
if (exclude_path_prefix)
ret->match_flags |= MATCHFLG_ABS_PATH;
if (exclude_path_prefix && *pattern == '/') {
ret->pattern = new_array(char,
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");
}
if (exclude_path_prefix && *pattern == '/')
ex_len = strlen(exclude_path_prefix);
else
ex_len = 0;
ret->pattern = new_array(char, ex_len + pat_len + 1);
if (!ret->pattern)
out_of_memory("make_exclude");
if (ex_len)
memcpy(ret->pattern, exclude_path_prefix, ex_len);
strlcpy(ret->pattern + ex_len, pattern, pat_len + 1);
pat_len += ex_len;
if (strpbrk(pattern, "*[?")) {
if (strpbrk(ret->pattern, "*[?")) {
ret->match_flags |= MATCHFLG_WILD;
if (strstr(pattern, "**")) {
if ((cp = strstr(ret->pattern, "**")) != NULL) {
ret->match_flags |= MATCHFLG_WILD2;
/* If the pattern starts with **, note that. */
if (*pattern == '*' && pattern[1] == '*')
if (cp == ret->pattern)
ret->match_flags |= MATCHFLG_WILD2_PREFIX;
}
}
pat_len = strlen(ret->pattern);
if (pat_len > 1 && ret->pattern[pat_len-1] == '/') {
ret->pattern[pat_len-1] = 0;
ret->directory = 1;
@@ -86,32 +85,35 @@ static struct exclude_struct *make_exclude(const char *pattern, int include)
for (cp = ret->pattern; (cp = strchr(cp, '/')) != NULL; cp++)
ret->slash_cnt++;
return ret;
if (!listp->tail)
listp->head = listp->tail = ret;
else {
listp->tail->next = ret;
listp->tail = ret;
}
}
static void free_exclude(struct exclude_struct *ex)
{
free(ex->pattern);
memset(ex,0,sizeof(*ex));
free(ex);
}
void free_exclude_list(struct exclude_struct ***listp)
void free_exclude_list(struct exclude_list_struct *listp)
{
struct exclude_struct **list = *listp;
struct exclude_struct *ent, *next;
if (verbose > 2)
rprintf(FINFO,"clearing exclude list\n");
if (verbose > 2) {
rprintf(FINFO, "[%s] clearing %sexclude list\n",
who_am_i(), listp->debug_type);
}
if (!list)
return;
for (ent = listp->head; ent; ent = next) {
next = ent->next;
free_exclude(ent);
}
while (*list)
free_exclude(*list++);
free(*listp);
*listp = NULL;
listp->head = listp->tail = NULL;
}
static int check_one_exclude(char *name, struct exclude_struct *ex,
@@ -130,10 +132,8 @@ static int check_one_exclude(char *name, struct exclude_struct *ex,
}
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);
pathjoin(full_name, sizeof full_name, curr_dir+plus, name);
name = full_name;
}
@@ -198,33 +198,34 @@ 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)
int name_is_dir, const char *type)
{
/* 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 (verbose >= 2) {
rprintf(FINFO, "[%s] %scluding %s %s because of %spattern %s%s\n",
who_am_i(), ent->include ? "in" : "ex",
name_is_dir ? "directory" : "file", name, type,
ent->pattern, ent->directory ? "/" : "");
}
}
/*
* Return true if file NAME is defined to be excluded by either
* LOCAL_EXCLUDE_LIST or the globals EXCLUDE_LIST.
* Return -1 if file "name" is defined to be excluded by the specified
* exclude list, 1 if it is included, and 0 if it was not matched.
*/
int check_exclude(struct exclude_struct **list, char *name, int name_is_dir)
int check_exclude(struct exclude_list_struct *listp, char *name, int name_is_dir)
{
struct exclude_struct *ent;
while ((ent = *list++) != NULL) {
for (ent = listp->head; ent; ent = ent->next) {
if (check_one_exclude(name, ent, name_is_dir)) {
report_exclude_result(name, ent, name_is_dir);
return !ent->include;
report_exclude_result(name, ent, name_is_dir,
listp->debug_type);
return ent->include ? 1 : -1;
}
}
@@ -232,53 +233,105 @@ int check_exclude(struct exclude_struct **list, char *name, int name_is_dir)
}
void add_exclude(struct exclude_struct ***listp, const char *pattern, int include)
/* Get the next include/exclude arg from the string. The token will not
* be '\0' terminated, so use the returned length to limit the string.
* Also, be sure to add this length to the returned pointer before passing
* it back to ask for the next token. This routine will not parse the +/-
* prefixes or the "!" token when xflags contains XFLG_WORDS_ONLY. The
* *incl_ptr value will be 1 for an include, 0 for an exclude, and -1 for
* the list-clearing "!" token.
*/
static const char *get_exclude_tok(const char *p, int *len_ptr, int *incl_ptr,
int xflags)
{
struct exclude_struct **list = *listp;
int len = 0;
const unsigned char *s = (const unsigned char *)p;
int len;
if (*pattern == '!' && !pattern[1]) {
free_exclude_list(listp);
return;
if (xflags & XFLG_WORD_SPLIT) {
/* Skip over any initial whitespace. */
while (isspace(*s))
s++;
/* Update for "!" check. */
p = (const char *)s;
}
if (list)
for (; list[len]; len++) {}
/* Is this a '+' or '-' followed by a space (not whitespace)? */
if (!(xflags & XFLG_WORDS_ONLY)
&& (*s == '-' || *s == '+') && s[1] == ' ') {
*incl_ptr = *s == '+';
s += 2;
} else
*incl_ptr = xflags & XFLG_DEF_INCLUDE;
list = *listp = realloc_array(list, struct exclude_struct *, len+2);
if (xflags & XFLG_WORD_SPLIT) {
const unsigned char *cp = s;
/* Token ends at whitespace or the end of the string. */
while (!isspace(*cp) && *cp != '\0')
cp++;
len = cp - s;
} else
len = strlen(s);
if (!list || !(list[len] = make_exclude(pattern, include)))
out_of_memory("add_exclude");
if (*p == '!' && len == 1 && !(xflags & XFLG_WORDS_ONLY))
*incl_ptr = -1;
if (verbose > 2) {
rprintf(FINFO,"add_exclude(%s,%s)\n",pattern,
include ? "include" : "exclude");
}
list[len+1] = NULL;
*len_ptr = len;
return (const char *)s;
}
void add_exclude_file(struct exclude_struct ***listp, const char *fname,
int fatal, int include)
void add_exclude(struct exclude_list_struct *listp, const char *pattern,
int xflags)
{
int fd;
int pat_len, incl;
const char *cp;
if (!pattern)
return;
cp = pattern;
pat_len = 0;
while (1) {
cp = get_exclude_tok(cp + pat_len, &pat_len, &incl, xflags);
if (!pat_len)
break;
/* If we got the special "!" token, clear the list. */
if (incl < 0)
free_exclude_list(listp);
else {
make_exclude(listp, cp, pat_len, incl);
if (verbose > 2) {
rprintf(FINFO, "[%s] add_exclude(%.*s, %s%s)\n",
who_am_i(), pat_len, cp,
listp->debug_type,
incl ? "include" : "exclude");
}
}
}
}
void add_exclude_file(struct exclude_list_struct *listp, const char *fname,
int xflags)
{
FILE *fp;
char line[MAXPATHLEN];
char *eob = line + MAXPATHLEN - 1;
extern int eol_nulls;
int word_split = xflags & XFLG_WORD_SPLIT;
if (!fname || !*fname)
return;
if (*fname != '-' || fname[1])
fd = open(fname, O_RDONLY|O_BINARY);
fp = fopen(fname, "rb");
else
fd = 0;
if (fd < 0) {
if (fatal) {
fp = stdin;
if (!fp) {
if (xflags & XFLG_FATAL_ERRORS) {
rsyserr(FERROR, errno,
"failed to open %s file %s",
include ? "include" : "exclude",
xflags & XFLG_DEF_INCLUDE ? "include" : "exclude",
fname);
exit_cleanup(RERR_FILEIO);
}
@@ -286,172 +339,108 @@ void add_exclude_file(struct exclude_struct ***listp, const char *fname,
}
while (1) {
char ch, *s = line;
int cnt;
char *s = line;
int ch;
while (1) {
if ((cnt = read(fd, &ch, 1)) <= 0) {
if (cnt < 0 && errno == EINTR)
if ((ch = getc(fp)) == EOF) {
if (ferror(fp) && errno == EINTR)
continue;
break;
}
if (word_split && isspace(ch))
break;
if (eol_nulls? !ch : (ch == '\n' || ch == '\r'))
break;
if (s < eob)
*s++ = ch;
}
*s = '\0';
if (*line && *line != ';' && *line != '#') {
/* Skip lines starting with semicolon or pound.
* It probably wouldn't cause any harm to not skip
* them but there's no need to save them. */
add_exclude(listp, line, include);
}
if (cnt <= 0)
/* Skip an empty token and (when line parsing) comments. */
if (*line && (word_split || (*line != ';' && *line != '#')))
add_exclude(listp, line, xflags);
if (ch == EOF)
break;
}
close(fd);
fclose(fp);
}
void send_exclude_list(int f)
{
int i;
extern int protocol_version;
extern int list_only, recurse;
struct exclude_struct *ent;
/* 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);
add_exclude(&exclude_list, "/*/*", 0);
if (!exclude_list) {
write_int(f,0);
return;
}
for (ent = exclude_list.head; ent; ent = ent->next) {
unsigned int l;
char p[MAXPATHLEN+1];
for (i=0;exclude_list[i];i++) {
int l;
char pattern[MAXPATHLEN];
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) {
rprintf(FERROR,"remote rsync does not support include syntax - aborting\n");
exit_cleanup(RERR_UNSUPPORTED);
}
write_int(f,l+2);
write_buf(f,"+ ",2);
} else {
write_int(f,l);
l = strlcpy(p, ent->pattern, sizeof p);
if (l == 0 || l >= MAXPATHLEN)
continue;
if (ent->directory) {
p[l++] = '/';
p[l] = '\0';
}
write_buf(f,pattern,l);
if (ent->include) {
write_int(f, l + 2);
write_buf(f, "+ ", 2);
} else if ((*p == '-' || *p == '+') && p[1] == ' ') {
write_int(f, l + 2);
write_buf(f, "- ", 2);
} else
write_int(f, l);
write_buf(f, p, l);
}
write_int(f,0);
write_int(f, 0);
}
void recv_exclude_list(int f)
{
char line[MAXPATHLEN];
char line[MAXPATHLEN+1]; /* Allows a trailing slash on a max-len dir */
unsigned int l;
while ((l=read_int(f))) {
if (l >= MAXPATHLEN) overflow("recv_exclude_list");
read_sbuf(f,line,l);
add_exclude(&exclude_list, line, ADD_EXCLUDE);
while ((l = read_int(f)) != 0) {
if (l >= sizeof line)
overflow("recv_exclude_list");
read_sbuf(f, line, l);
add_exclude(&exclude_list, line, 0);
}
}
/* Get the next include/exclude arg from the string. It works in a similar way
** to strtok - initially an arg is sent over, from then on NULL. This
** routine takes into account any +/- in the strings and does not
** consider the space following it as a delimeter.
*/
char *get_exclude_tok(char *p)
{
static char *s;
static int more;
char *t;
if (p) {
s=p;
if (*p)
more=1;
}
if (!more)
return(NULL);
/* Skip over any initial spaces */
while (isspace(* (unsigned char *) s))
s++;
/* Are we at the end of the string? */
if (*s) {
/* remember the beginning of the token */
t=s;
/* 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++;
} else {
t=NULL;
}
/* Have we reached the end of the string? */
if (*s)
*s++='\0';
else
more=0;
return(t);
}
void add_exclude_line(struct exclude_struct ***listp,
const char *line, int include)
{
char *tok, *p;
if (!line || !*line) return;
p = strdup(line);
if (!p) out_of_memory("add_exclude_line");
for (tok=get_exclude_tok(p); tok; tok=get_exclude_tok(NULL))
add_exclude(listp, tok, include);
free(p);
}
static char *cvs_ignore_list[] = {
"RCS/", "SCCS/", "CVS/", ".svn/", "CVS.adm", "RCSLOG", "cvslog.*",
"tags", "TAGS", ".make.state", ".nse_depinfo",
"*~", "#*", ".#*", ", *", "*.old", "*.bak", "*.BAK", "*.orig",
"*.rej", ".del-*", "*.a", "*.o", "*.obj", "*.so", "*.Z", "*.elc", "*.ln",
"core", NULL};
static char default_cvsignore[] =
/* These default ignored items come from the CVS manual. */
"RCS SCCS CVS CVS.adm RCSLOG cvslog.* tags TAGS"
" .make.state .nse_depinfo *~ #* .#* ,* _$* *$"
" *.old *.bak *.BAK *.orig *.rej .del-*"
" *.a *.olb *.o *.obj *.so *.exe"
" *.Z *.elc *.ln core"
/* The rest we added to suit ourself. */
" .svn/";
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(&exclude_list, default_cvsignore,
XFLG_WORD_SPLIT | XFLG_WORDS_ONLY);
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);
if ((p = getenv("HOME"))
&& pathjoin(fname, sizeof fname, p, ".cvsignore") < sizeof fname) {
add_exclude_file(&exclude_list, fname,
XFLG_WORD_SPLIT | XFLG_WORDS_ONLY);
}
add_exclude_line(&exclude_list, getenv("CVSIGNORE"), ADD_EXCLUDE);
add_exclude(&exclude_list, getenv("CVSIGNORE"),
XFLG_WORD_SPLIT | XFLG_WORDS_ONLY);
}

View File

@@ -1,24 +1,24 @@
/*
/*
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
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 IO utilities used in rsync
File IO utilities used in rsync
*/
#include "rsync.h"
@@ -42,8 +42,8 @@ static int write_sparse(int f,char *buf,size_t len)
size_t l1=0, l2=0;
int ret;
for (l1=0;l1<len && buf[l1]==0;l1++) ;
for (l2=0;l2<(len-l1) && buf[len-(l2+1)]==0;l2++) ;
for (l1 = 0; l1 < len && buf[l1] == 0; l1++) {}
for (l2 = 0; l2 < len-l1 && buf[len-(l2+1)] == 0; l2++) {}
last_byte = buf[len-1];
@@ -51,24 +51,46 @@ static int write_sparse(int f,char *buf,size_t len)
last_sparse=1;
if (l1 > 0) {
do_lseek(f,l1,SEEK_CUR);
do_lseek(f,l1,SEEK_CUR);
}
if (l1 == len)
if (l1 == len)
return len;
ret = write(f, buf + l1, len - (l1+l2));
if (ret == -1 || ret == 0)
return ret;
else if (ret != (int) (len - (l1+l2)))
else if (ret != (int) (len - (l1+l2)))
return (l1+ret);
if (l2 > 0)
do_lseek(f,l2,SEEK_CUR);
return len;
}
static char *wf_writeBuf;
static size_t wf_writeBufSize;
static size_t wf_writeBufCnt;
int flush_write_file(int f)
{
int ret = 0;
char *bp = wf_writeBuf;
while (wf_writeBufCnt > 0) {
if ((ret = write(f, bp, wf_writeBufCnt)) < 0) {
if (errno == EINTR)
continue;
return ret;
}
wf_writeBufCnt -= ret;
bp += ret;
}
return ret;
}
/*
* write_file does not allow incomplete writes. It loops internally
* until len bytes are written or errno is set.
@@ -77,13 +99,30 @@ int write_file(int f,char *buf,size_t len)
{
int ret = 0;
while (len>0) {
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);
if (!wf_writeBuf) {
wf_writeBufSize = MAX_MAP_SIZE;
wf_writeBufCnt = 0;
wf_writeBuf = new_array(char, MAX_MAP_SIZE);
if (!wf_writeBuf)
out_of_memory("write_file");
}
r1 = MIN(len, wf_writeBufSize - wf_writeBufCnt);
if (r1) {
memcpy(wf_writeBuf + wf_writeBufCnt, buf, r1);
wf_writeBufCnt += r1;
}
if (wf_writeBufCnt == wf_writeBufSize) {
if (flush_write_file(f) < 0)
return -1;
if (!r1 && len)
continue;
}
}
if (r1 <= 0) {
if (ret > 0) return ret;
@@ -137,7 +176,7 @@ char *map_ptr(struct map_struct *map,OFF_T offset,int len)
}
/* in most cases the region will already be available */
if (offset >= map->p_offset &&
if (offset >= map->p_offset &&
offset+len <= map->p_offset+map->p_len) {
return (map->p + (offset - map->p_offset));
}
@@ -206,8 +245,8 @@ char *map_ptr(struct map_struct *map,OFF_T offset,int len)
map->p_offset = window_start;
map->p_len = window_size;
return map->p + (offset - map->p_offset);
return map->p + (offset - map->p_offset);
}

1314
flist.c
View File

File diff suppressed because it is too large Load Diff

View File

@@ -30,6 +30,9 @@ extern int preserve_links;
extern int am_root;
extern int preserve_devices;
extern int preserve_hard_links;
extern int preserve_perms;
extern int preserve_uid;
extern int preserve_gid;
extern int update_only;
extern int opt_ignore_existing;
extern int csum_length;
@@ -38,31 +41,33 @@ extern int size_only;
extern int io_timeout;
extern int protocol_version;
extern int always_checksum;
extern int modify_window;
extern char *compare_dest;
extern int link_dest;
extern int whole_file;
extern int local_server;
extern int write_batch;
extern int list_only;
extern int only_existing;
extern int orig_umask;
extern int safe_symlinks;
/* choose whether to skip a particular file */
static int skip_file(char *fname,
struct file_struct *file, STRUCT_STAT *st)
static int skip_file(char *fname, struct file_struct *file, STRUCT_STAT *st)
{
if (st->st_size != file->length) {
return 0;
}
if (link_dest) {
extern int preserve_perms;
extern int preserve_uid;
extern int preserve_gid;
if(preserve_perms
&& (st->st_mode & ~_S_IFMT) != (file->mode & ~_S_IFMT))
if (preserve_perms
&& (st->st_mode & CHMOD_BITS) != (file->mode & CHMOD_BITS))
return 0;
if (preserve_uid && st->st_uid != file->uid)
if (am_root && preserve_uid && st->st_uid != file->uid)
return 0;
if (preserve_gid && st->st_gid != file->gid)
if (preserve_gid && file->gid != GID_NONE
&& st->st_gid != file->gid)
return 0;
}
@@ -74,17 +79,14 @@ static int skip_file(char *fname,
if (compare_dest != NULL) {
if (access(fname, 0) != 0) {
snprintf(fnamecmpdest,MAXPATHLEN,"%s/%s",
compare_dest,fname);
pathjoin(fnamecmpdest, sizeof fnamecmpdest,
compare_dest, fname);
fname = fnamecmpdest;
}
}
file_checksum(fname,sum,st->st_size);
if (protocol_version < 21) {
return (memcmp(sum,file->sum,2) == 0);
} else {
return (memcmp(sum,file->sum,MD4_SUM_LENGTH) == 0);
}
return memcmp(sum, file->u.sum, protocol_version < 21 ? 2
: MD4_SUM_LENGTH) == 0;
}
if (size_only) {
@@ -100,14 +102,13 @@ static int skip_file(char *fname,
/*
* NULL sum_struct means we have no checksums
* NULL sum_struct means we have no checksums
*/
void write_sum_head(int f, struct sum_struct *sum)
{
static struct sum_struct null_sum;
if (sum == (struct sum_struct *)NULL)
if (sum == NULL)
sum = &null_sum;
write_int(f, sum->count);
@@ -137,8 +138,9 @@ void write_sum_head(int f, struct sum_struct *sum)
static void sum_sizes_sqroot(struct sum_struct *sum, uint64 len)
{
extern int block_size;
int blength, s2length, b;
extern unsigned int block_size;
unsigned int blength;
int s2length;
uint32 c;
uint64 l;
@@ -167,7 +169,7 @@ static void sum_sizes_sqroot(struct sum_struct *sum, uint64 len)
} else if (csum_length == SUM_LENGTH) {
s2length = SUM_LENGTH;
} else {
b = BLOCKSUM_BIAS;
int b = BLOCKSUM_BIAS;
l = len;
while (l >>= 1) {
b += 2;
@@ -192,10 +194,9 @@ static void sum_sizes_sqroot(struct sum_struct *sum, uint64 len)
sum->remainder = (len % blength);
if (sum->count && verbose > 2) {
rprintf(FINFO, "count=%ld rem=%ld blength=%ld s2length=%ld flength=%.0f\n",
(long) sum->count, (long) sum->remainder,
(long) sum->blength, (long) sum->s2length,
(double) sum->flength);
rprintf(FINFO, "count=%.0f rem=%u blength=%u s2length=%d flength=%.0f\n",
(double)sum->count, sum->remainder, sum->blength,
sum->s2length, (double)sum->flength);
}
}
@@ -210,10 +211,6 @@ static void sum_sizes_sqroot(struct sum_struct *sum, uint64 len)
* Whew. */
static BOOL disable_deltas_p(void)
{
extern int whole_file;
extern int local_server;
extern int write_batch;
if (whole_file > 0)
return True;
if (whole_file == 0 || write_batch)
@@ -227,7 +224,7 @@ static BOOL disable_deltas_p(void)
*
* Generate approximately one checksum every block_len bytes.
*/
static void generate_and_send_sums(struct map_struct *buf, OFF_T len, int f_out)
static void generate_and_send_sums(struct map_struct *buf, size_t len, int f_out)
{
size_t i;
struct sum_struct sum;
@@ -238,7 +235,7 @@ static void generate_and_send_sums(struct map_struct *buf, OFF_T len, int f_out)
write_sum_head(f_out, &sum);
for (i = 0; i < sum.count; i++) {
int n1 = MIN(len, sum.blength);
unsigned int n1 = MIN(len, sum.blength);
char *map = map_ptr(buf, offset, n1);
uint32 sum1 = get_checksum1(map, n1);
char sum2[SUM_LENGTH];
@@ -247,8 +244,9 @@ static void generate_and_send_sums(struct map_struct *buf, OFF_T len, int f_out)
if (verbose > 3) {
rprintf(FINFO,
"chunk[%ld] offset=%.0f len=%d sum1=%08lx\n",
(long)i,(double)offset,n1,(unsigned long)sum1);
"chunk[%.0f] offset=%.0f len=%u sum1=%08lx\n",
(double)i, (double)offset, n1,
(unsigned long)sum1);
}
write_int(f_out, sum1);
write_buf(f_out, sum2, sum.s2length);
@@ -267,22 +265,17 @@ static void generate_and_send_sums(struct map_struct *buf, OFF_T len, int f_out)
* @note This comment was added later by mbp who was trying to work it
* out. It might be wrong.
**/
void recv_generator(char *fname, struct file_list *flist, int i, int f_out)
void recv_generator(char *fname, struct file_struct *file, int i, int f_out)
{
int fd;
STRUCT_STAT st;
struct map_struct *buf;
struct map_struct *mapbuf;
int statret;
struct file_struct *file = flist->files[i];
char *fnamecmp;
char fnamecmpbuf[MAXPATHLEN];
extern char *compare_dest;
extern int list_only;
extern int preserve_perms;
extern int only_existing;
extern int orig_umask;
if (list_only) return;
if (list_only)
return;
if (verbose > 2)
rprintf(FINFO,"recv_generator(%s,%d)\n",fname,i);
@@ -301,7 +294,8 @@ void recv_generator(char *fname, struct file_list *flist, int i, int f_out)
/* if the file exists already and we aren't perserving
* permissions then act as though the remote end sent
* us the file permissions we already have */
file->mode = (file->mode & _S_IFMT) | (st.st_mode & ~_S_IFMT);
file->mode = (file->mode & ~CHMOD_BITS)
| (st.st_mode & CHMOD_BITS);
}
if (S_ISDIR(file->mode)) {
@@ -340,12 +334,11 @@ void recv_generator(char *fname, struct file_list *flist, int i, int f_out)
#if SUPPORT_LINKS
char lnk[MAXPATHLEN];
int l;
extern int safe_symlinks;
if (safe_symlinks && unsafe_symlink(file->link, fname)) {
if (safe_symlinks && unsafe_symlink(file->u.link, fname)) {
if (verbose) {
rprintf(FINFO, "ignoring unsafe symlink %s -> \"%s\"\n",
full_fname(fname), file->link);
full_fname(fname), file->u.link);
}
return;
}
@@ -356,7 +349,7 @@ void recv_generator(char *fname, struct file_list *flist, int i, int f_out)
/* A link already pointing to the
* right place -- no further action
* required. */
if (strcmp(lnk,file->link) == 0) {
if (strcmp(lnk,file->u.link) == 0) {
set_perms(fname,file,&st,1);
return;
}
@@ -366,13 +359,13 @@ void recv_generator(char *fname, struct file_list *flist, int i, int f_out)
* in place. */
delete_file(fname);
}
if (do_symlink(file->link,fname) != 0) {
if (do_symlink(file->u.link,fname) != 0) {
rprintf(FERROR, "symlink %s -> \"%s\" failed: %s\n",
full_fname(fname), file->link, strerror(errno));
full_fname(fname), file->u.link, strerror(errno));
} else {
set_perms(fname,file,NULL,0);
if (verbose) {
rprintf(FINFO,"%s -> %s\n", fname,file->link);
rprintf(FINFO,"%s -> %s\n", fname,file->u.link);
}
}
#endif
@@ -383,12 +376,12 @@ void recv_generator(char *fname, struct file_list *flist, int i, int f_out)
if (am_root && preserve_devices && IS_DEVICE(file->mode)) {
if (statret != 0 ||
st.st_mode != file->mode ||
(DEV64_T)st.st_rdev != file->rdev) {
st.st_rdev != file->u.rdev) {
delete_file(fname);
if (verbose > 2)
rprintf(FINFO,"mknod(%s,0%o,0x%x)\n",
fname,(int)file->mode,(int)file->rdev);
if (do_mknod(fname,file->mode,file->rdev) != 0) {
fname,(int)file->mode,(int)file->u.rdev);
if (do_mknod(fname,file->mode,file->u.rdev) != 0) {
rprintf(FERROR, "mknod %s failed: %s\n",
full_fname(fname), strerror(errno));
} else {
@@ -403,11 +396,8 @@ void recv_generator(char *fname, struct file_list *flist, int i, int f_out)
}
#endif
if (preserve_hard_links && check_hard_link(file)) {
if (verbose > 1)
rprintf(FINFO, "recv_generator: \"%s\" is a hard link\n",f_name(file));
if (preserve_hard_links && hard_link_check(file, HL_CHECK_MASTER))
return;
}
if (!S_ISREG(file->mode)) {
rprintf(FINFO, "skipping non-regular file \"%s\"\n",fname);
@@ -416,10 +406,10 @@ void recv_generator(char *fname, struct file_list *flist, int i, int f_out)
fnamecmp = fname;
if ((statret == -1) && (compare_dest != NULL)) {
if (statret == -1 && compare_dest != NULL) {
/* try the file at compare_dest instead */
int saveerrno = errno;
snprintf(fnamecmpbuf,MAXPATHLEN,"%s/%s",compare_dest,fname);
pathjoin(fnamecmpbuf, sizeof fnamecmpbuf, compare_dest, fname);
statret = link_stat(fnamecmpbuf,&st);
if (!S_ISREG(st.st_mode))
statret = -1;
@@ -428,11 +418,11 @@ void recv_generator(char *fname, struct file_list *flist, int i, int f_out)
#if HAVE_LINK
else if (link_dest && !dry_run) {
if (do_link(fnamecmpbuf, fname) != 0) {
if (verbose > 0)
if (verbose > 0) {
rprintf(FINFO,"link %s => %s : %s\n",
fnamecmpbuf,
fname,
fnamecmpbuf, fname,
strerror(errno));
}
}
fnamecmp = fnamecmpbuf;
}
@@ -442,6 +432,8 @@ void recv_generator(char *fname, struct file_list *flist, int i, int f_out)
}
if (statret == -1) {
if (preserve_hard_links && hard_link_check(file, HL_SKIP))
return;
if (errno == ENOENT) {
write_int(f_out,i);
if (!dry_run) write_sum_head(f_out, NULL);
@@ -459,6 +451,8 @@ void recv_generator(char *fname, struct file_list *flist, int i, int f_out)
}
/* now pretend the file didn't exist */
if (preserve_hard_links && hard_link_check(file, HL_SKIP))
return;
write_int(f_out,i);
if (!dry_run) write_sum_head(f_out, NULL);
return;
@@ -500,40 +494,44 @@ void recv_generator(char *fname, struct file_list *flist, int i, int f_out)
rprintf(FERROR, "failed to open %s, continuing: %s\n",
full_fname(fnamecmp), strerror(errno));
/* pretend the file didn't exist */
if (preserve_hard_links && hard_link_check(file, HL_SKIP))
return;
write_int(f_out,i);
write_sum_head(f_out, NULL);
return;
}
if (st.st_size > 0) {
buf = map_file(fd,st.st_size);
} else {
buf = NULL;
}
if (st.st_size > 0)
mapbuf = map_file(fd,st.st_size);
else
mapbuf = NULL;
if (verbose > 3)
rprintf(FINFO,"gen mapped %s of size %.0f\n",fnamecmp,(double)st.st_size);
if (verbose > 3) {
rprintf(FINFO,"gen mapped %s of size %.0f\n", fnamecmp,
(double)st.st_size);
}
if (verbose > 2)
rprintf(FINFO, "generating and sending sums for %d\n", i);
write_int(f_out,i);
generate_and_send_sums(buf, st.st_size, f_out);
generate_and_send_sums(mapbuf, st.st_size, f_out);
close(fd);
if (buf) unmap_file(buf);
if (mapbuf) unmap_file(mapbuf);
}
void generate_files(int f,struct file_list *flist,char *local_name,int f_recv)
void generate_files(int f, struct file_list *flist, char *local_name)
{
int i;
int phase=0;
char fbuf[MAXPATHLEN];
if (verbose > 2)
rprintf(FINFO,"generator starting pid=%d count=%d\n",
(int)getpid(),flist->count);
if (verbose > 2) {
rprintf(FINFO, "generator starting pid=%ld count=%d\n",
(long)getpid(), flist->count);
}
if (verbose >= 2) {
rprintf(FINFO,
@@ -549,21 +547,23 @@ void generate_files(int f,struct file_list *flist,char *local_name,int f_recv)
for (i = 0; i < flist->count; i++) {
struct file_struct *file = flist->files[i];
mode_t saved_mode = file->mode;
if (!file->basename) continue;
struct file_struct copy;
if (!file->basename)
continue;
/* we need to ensure that any directories we create have writeable
permissions initially so that we can create the files within
them. This is then fixed after the files are transferred */
if (!am_root && S_ISDIR(file->mode)) {
file->mode |= S_IWUSR; /* user write */
if (!am_root && S_ISDIR(file->mode) && !(file->mode & S_IWUSR)) {
copy = *file;
/* XXX: Could this be causing a problem on SCO? Perhaps their
* handling of permissions is strange? */
copy.mode |= S_IWUSR; /* user write */
file = &copy;
}
recv_generator(local_name?local_name:f_name(file), flist,i,f);
file->mode = saved_mode;
recv_generator(local_name ? local_name : f_name_to(file, fbuf),
file, i, f);
}
phase++;
@@ -577,9 +577,10 @@ void generate_files(int f,struct file_list *flist,char *local_name,int f_recv)
/* files can cycle through the system more than once
* to catch initial checksum errors */
for (i=read_int(f_recv); i != -1; i=read_int(f_recv)) {
while ((i = get_redo_num()) != -1) {
struct file_struct *file = flist->files[i];
recv_generator(local_name?local_name:f_name(file), flist,i,f);
recv_generator(local_name ? local_name : f_name_to(file, fbuf),
file, i, f);
}
phase++;
@@ -587,4 +588,19 @@ void generate_files(int f,struct file_list *flist,char *local_name,int f_recv)
rprintf(FINFO,"generate_files phase=%d\n",phase);
write_int(f,-1);
if (preserve_hard_links)
do_hard_links();
/* now we need to fix any directory permissions that were
* modified during the transfer */
for (i = 0; i < flist->count; i++) {
struct file_struct *file = flist->files[i];
if (!file->basename || !S_ISDIR(file->mode)) continue;
recv_generator(local_name ? local_name : f_name(file),
file, i, -1);
}
if (verbose > 2)
rprintf(FINFO,"generate_files finished\n");
}

View File

@@ -26,24 +26,42 @@
#include "rsync.h"
#ifndef NGROUPS
/* It ought to be defined, but just in case. */
# define NGROUPS 32
#endif
int
main(UNUSED(int argc), UNUSED(char *argv[]))
{
int n, i;
gid_t list[NGROUPS];
gid_t *list;
gid_t gid = MY_GID();
int gid_in_list = 0;
if ((n = getgroups(NGROUPS, list)) == -1) {
#ifdef HAVE_GETGROUPS
if ((n = getgroups(0, NULL)) < 0) {
perror("getgroups");
return 1;
}
#else
n = 0;
#endif
for (i = 0; i < n; i++)
printf("%u ", list[i]);
list = (gid_t*)malloc(sizeof (gid_t) * (n + 1));
if (!list) {
fprintf(stderr, "out of memory!\n");
exit(1);
}
#ifdef HAVE_GETGROUPS
if (n > 0)
n = getgroups(n, list);
#endif
for (i = 0; i < n; i++) {
printf("%lu ", (unsigned long)list[i]);
if (list[i] == gid)
gid_in_list = 1;
}
/* The default gid might not be in the list on some systems. */
if (!gid_in_list)
printf("%lu", (unsigned long)gid);
printf("\n");
return 0;

233
hlink.c
View File

@@ -1,18 +1,18 @@
/*
/*
Copyright (C) Andrew Tridgell 1996
Copyright (C) Paul Mackerras 1996
Copyright (C) 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.
@@ -22,138 +22,144 @@
extern int dry_run;
extern int verbose;
extern int make_backups;
#if SUPPORT_HARD_LINKS
static int hlink_compare(struct file_struct *f1, struct file_struct *f2)
static int hlink_compare(struct file_struct **file1, struct file_struct **file2)
{
if (!S_ISREG(f1->mode) && !S_ISREG(f2->mode))
return 0;
if (!S_ISREG(f1->mode))
return -1;
if (!S_ISREG(f2->mode))
return 1;
struct file_struct *f1 = *file1;
struct file_struct *f2 = *file2;
if (f1->dev != f2->dev)
return (int) (f1->dev > f2->dev ? 1 : -1);
if (f1->F_DEV != f2->F_DEV)
return (int) (f1->F_DEV > f2->F_DEV ? 1 : -1);
if (f1->inode != f2->inode)
return (int) (f1->inode > f2->inode ? 1 : -1);
if (f1->F_INODE != f2->F_INODE)
return (int) (f1->F_INODE > f2->F_INODE ? 1 : -1);
return file_compare(&f1, &f2);
return file_compare(file1, file2);
}
static struct file_struct *hlink_list;
static struct file_struct **hlink_list;
static int hlink_count;
#define LINKED(p1,p2) ((p1)->F_DEV == (p2)->F_DEV \
&& (p1)->F_INODE == (p2)->F_INODE)
/* Analyze the data in the hlink_list[], remove items that aren't multiply
* linked, and replace the dev+inode data with the hlindex+next linked list. */
static void link_idev_data(struct file_list *flist)
{
struct file_struct *head;
int from, to, start;
alloc_pool_t hlink_pool;
alloc_pool_t idev_pool = flist->hlink_pool;
hlink_pool = pool_create(128 * 1024, sizeof (struct hlink),
out_of_memory, POOL_INTERN);
for (from = to = 0; from < hlink_count; from++) {
start = from;
head = hlink_list[start];
while (from < hlink_count-1
&& LINKED(hlink_list[from], hlink_list[from+1])) {
pool_free(idev_pool, 0, hlink_list[from]->link_u.idev);
hlink_list[from]->link_u.links = pool_talloc(hlink_pool,
struct hlink, 1, "hlink_list");
hlink_list[from]->F_HLINDEX = to;
hlink_list[from]->F_NEXT = hlink_list[from+1];
from++;
}
if (from > start) {
pool_free(idev_pool, 0, hlink_list[from]->link_u.idev);
hlink_list[from]->link_u.links = pool_talloc(hlink_pool,
struct hlink, 1, "hlink_list");
hlink_list[from]->F_HLINDEX = to;
hlink_list[from]->F_NEXT = head;
hlink_list[from]->flags |= FLAG_HLINK_EOL;
hlink_list[to++] = head;
} else {
pool_free(idev_pool, 0, head->link_u.idev);
head->link_u.idev = NULL;
}
}
if (!to) {
free(hlink_list);
hlink_list = NULL;
pool_destroy(hlink_pool);
hlink_pool = NULL;
} else {
hlink_count = to;
if (!(hlink_list = realloc_array(hlink_list,
struct file_struct *, hlink_count)))
out_of_memory("init_hard_links");
}
flist->hlink_pool = hlink_pool;
pool_destroy(idev_pool);
}
#endif
void init_hard_links(struct file_list *flist)
{
#if SUPPORT_HARD_LINKS
int i;
if (flist->count < 2)
return;
if (hlink_list)
free(hlink_list);
if (!(hlink_list = new_array(struct file_struct, 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++)
memcpy(&hlink_list[i], flist->files[i],
sizeof(hlink_list[0]));
hlink_count = 0;
for (i = 0; i < flist->count; i++) {
if (flist->files[i]->link_u.idev)
hlink_list[hlink_count++] = flist->files[i];
}
qsort(hlink_list, flist->count,
sizeof(hlink_list[0]), (int (*)()) hlink_compare);
qsort(hlink_list, hlink_count,
sizeof hlink_list[0], (int (*)()) hlink_compare);
hlink_count = flist->count;
if (!hlink_count) {
free(hlink_list);
hlink_list = NULL;
} else
link_idev_data(flist);
#endif
}
/* check if a file should be skipped because it is the same as an
earlier hard link */
int check_hard_link(struct file_struct *file)
int hard_link_check(struct file_struct *file, int skip)
{
#if SUPPORT_HARD_LINKS
int low = 0, high = hlink_count - 1;
int ret = 0;
if (!hlink_list || !S_ISREG(file->mode))
if (!hlink_list || !file->link_u.links)
return 0;
while (low != high) {
int mid = (low + high) / 2;
ret = hlink_compare(&hlink_list[mid], file);
if (ret == 0) {
low = mid;
break;
}
if (ret > 0)
high = mid;
else
low = mid + 1;
}
/* XXX: To me this looks kind of dodgy -- why do we use [low]
* here and [low-1] below? -- mbp */
if (hlink_compare(&hlink_list[low], file) != 0)
return 0;
if (low > 0 &&
S_ISREG(hlink_list[low - 1].mode) &&
file->dev == hlink_list[low - 1].dev &&
file->inode == hlink_list[low - 1].inode) {
if (verbose >= 2) {
rprintf(FINFO, "check_hard_link: \"%s\" is a hard link to file %d, \"%s\"\n",
f_name(file), low-1, f_name(&hlink_list[low-1]));
if (skip && !(file->flags & FLAG_HLINK_EOL))
hlink_list[file->F_HLINDEX] = file->F_NEXT;
if (hlink_list[file->F_HLINDEX] != file) {
if (verbose > 1) {
rprintf(FINFO, "\"%s\" is a hard link\n",
f_name(file));
}
return 1;
}
#endif
return 0;
}
#if SUPPORT_HARD_LINKS
static void hard_link_one(int i)
static void hard_link_one(char *hlink1, char *hlink2)
{
STRUCT_STAT st1, st2;
if (link_stat(f_name(&hlink_list[i - 1]), &st1) != 0)
return;
if (link_stat(f_name(&hlink_list[i]), &st2) != 0) {
if (do_link
(f_name(&hlink_list[i - 1]),
f_name(&hlink_list[i])) != 0) {
if (verbose > 0)
rprintf(FINFO, "link %s => %s : %s\n",
f_name(&hlink_list[i]),
f_name(&hlink_list[i - 1]),
strerror(errno));
return;
}
} else {
if (st2.st_dev == st1.st_dev && st2.st_ino == st1.st_ino)
return;
if (robust_unlink(f_name(&hlink_list[i])) != 0 ||
do_link(f_name(&hlink_list[i - 1]),
f_name(&hlink_list[i])) != 0) {
if (verbose > 0)
rprintf(FINFO, "link %s => %s : %s\n",
f_name(&hlink_list[i]),
f_name(&hlink_list[i - 1]),
strerror(errno));
return;
if (do_link(hlink1, hlink2)) {
if (verbose) {
rprintf(FINFO, "link %s => %s failed: %s\n",
hlink2, hlink1, strerror(errno));
}
}
if (verbose > 0)
rprintf(FINFO, "%s => %s\n",
f_name(&hlink_list[i]),
f_name(&hlink_list[i - 1]));
else if (verbose)
rprintf(FINFO, "%s => %s\n", hlink2, hlink1);
}
#endif
@@ -166,18 +172,39 @@ static void hard_link_one(int i)
void do_hard_links(void)
{
#if SUPPORT_HARD_LINKS
struct file_struct *file, *first;
char hlink1[MAXPATHLEN];
char *hlink2;
STRUCT_STAT st1, st2;
int i;
if (!hlink_list)
return;
for (i = 1; i < hlink_count; i++) {
if (S_ISREG(hlink_list[i].mode) &&
S_ISREG(hlink_list[i - 1].mode) &&
hlink_list[i].basename && hlink_list[i - 1].basename &&
hlink_list[i].dev == hlink_list[i - 1].dev &&
hlink_list[i].inode == hlink_list[i - 1].inode) {
hard_link_one(i);
for (i = 0; i < hlink_count; i++) {
first = file = hlink_list[i];
if (link_stat(f_name_to(first, hlink1), &st1) != 0)
continue;
while ((file = file->F_NEXT) != first) {
hlink2 = f_name(file);
if (link_stat(hlink2, &st2) == 0) {
if (st2.st_dev == st1.st_dev
&& st2.st_ino == st1.st_ino)
continue;
if (make_backups) {
if (!make_backup(hlink2))
continue;
} else if (robust_unlink(hlink2)) {
if (verbose > 0) {
rprintf(FINFO,
"unlink %s failed: %s\n",
full_fname(hlink2),
strerror(errno));
}
continue;
}
}
hard_link_one(hlink1, hlink2);
}
}
#endif

388
io.c
View File

@@ -41,14 +41,17 @@
static int io_multiplexing_out;
static int io_multiplexing_in;
static int multiplex_in_fd;
static int multiplex_out_fd;
static int multiplex_in_fd = -1;
static int multiplex_out_fd = -1;
static time_t last_io;
static int no_flush;
extern int bwlimit;
extern int verbose;
extern int io_timeout;
extern int am_server;
extern int am_daemon;
extern int am_sender;
extern struct stats stats;
@@ -74,8 +77,9 @@ const char *io_read_phase = phase_unknown;
version is 24 or less. */
int kludge_around_eof = False;
int msg_fd_in = -1;
int msg_fd_out = -1;
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];
@@ -85,14 +89,44 @@ static int io_filesfrom_buflen;
static void read_loop(int fd, char *buf, size_t len);
struct redo_list {
struct redo_list *next;
int num;
};
static struct redo_list *redo_list_head;
static struct redo_list *redo_list_tail;
struct msg_list {
struct msg_list *next;
char *buf;
int len;
};
static struct msg_list *msg_list_head;
static struct msg_list *msg_list_tail;
static void redo_list_add(int num)
{
struct redo_list *rl;
if (!(rl = new(struct redo_list)))
exit_cleanup(RERR_MALLOC);
rl->next = NULL;
rl->num = num;
if (redo_list_tail)
redo_list_tail->next = rl;
else
redo_list_head = rl;
redo_list_tail = rl;
}
static void check_timeout(void)
{
extern int am_server, am_daemon;
time_t t;
err_list_push();
if (!io_timeout) return;
if (!io_timeout)
return;
if (!last_io) {
last_io = time(NULL);
@@ -110,41 +144,160 @@ static void check_timeout(void)
}
}
/** Setup the fd used to propagate errors */
void io_set_error_fd(int fd)
/** Setup the fd used to receive MSG_* messages. Only needed when
* we're the generator because the sender and receiver both use the
* multiplexed IO setup. */
void set_msg_fd_in(int fd)
{
io_error_fd = fd;
msg_fd_in = fd;
}
/** Read some data from the error fd and write it to the write log code */
static void read_error_fd(void)
/** Setup the fd used to send our MSG_* messages. Only needed when
* we're the receiver because the generator and the sender both use
* the multiplexed IO setup. */
void set_msg_fd_out(int fd)
{
msg_fd_out = fd;
set_nonblocking(msg_fd_out);
}
/* Add a message to the pending MSG_* list. */
static void msg_list_add(int code, char *buf, int len)
{
struct msg_list *ml;
if (!(ml = new(struct msg_list)))
exit_cleanup(RERR_MALLOC);
ml->next = NULL;
if (!(ml->buf = new_array(char, len+4)))
exit_cleanup(RERR_MALLOC);
SIVAL(ml->buf, 0, ((code+MPLEX_BASE)<<24) | len);
memcpy(ml->buf+4, buf, len);
ml->len = len+4;
if (msg_list_tail)
msg_list_tail->next = ml;
else
msg_list_head = ml;
msg_list_tail = ml;
}
void send_msg(enum msgcode code, char *buf, int len)
{
msg_list_add(code, buf, len);
msg_list_push(NORMAL_FLUSH);
}
/** Read a message from the MSG_* fd and dispatch it. This is only
* called by the generator. */
static void read_msg_fd(void)
{
char buf[200];
size_t n;
int fd = io_error_fd;
int fd = msg_fd_in;
int tag, len;
/* io_error_fd is temporarily disabled -- is this meant to
* prevent indefinite recursion? */
io_error_fd = -1;
/* Temporarily disable msg_fd_in. This is needed because we
* may call a write routine that could try to call us back. */
msg_fd_in = -1;
read_loop(fd, buf, 4);
tag = IVAL(buf, 0);
len = tag & 0xFFFFFF;
tag = tag >> 24;
tag -= MPLEX_BASE;
tag = (tag >> 24) - MPLEX_BASE;
while (len) {
n = len;
if (n > (sizeof buf - 1))
n = sizeof buf - 1;
read_loop(fd, buf, n);
rwrite((enum logcode)tag, buf, n);
len -= n;
switch (tag) {
case MSG_DONE:
if (len != 0) {
rprintf(FERROR, "invalid message %d:%d\n", tag, len);
exit_cleanup(RERR_STREAMIO);
}
redo_list_add(-1);
break;
case MSG_REDO:
if (len != 4) {
rprintf(FERROR, "invalid message %d:%d\n", tag, len);
exit_cleanup(RERR_STREAMIO);
}
read_loop(fd, buf, 4);
redo_list_add(IVAL(buf,0));
break;
case MSG_INFO:
case MSG_ERROR:
case MSG_LOG:
while (len) {
n = len;
if (n >= sizeof buf)
n = sizeof buf - 1;
read_loop(fd, buf, n);
rwrite((enum logcode)tag, buf, n);
len -= n;
}
break;
default:
rprintf(FERROR, "unknown message %d:%d\n", tag, len);
exit_cleanup(RERR_STREAMIO);
}
io_error_fd = fd;
msg_fd_in = fd;
}
/* Try to push messages off the list onto the wire. If we leave with more
* to do, return 0. On error, return -1. If everything flushed, return 1.
* This is only called by the receiver. */
int msg_list_push(int flush_it_all)
{
static int written = 0;
struct timeval tv;
fd_set fds;
if (msg_fd_out < 0)
return -1;
while (msg_list_head) {
struct msg_list *ml = msg_list_head;
int n = write(msg_fd_out, ml->buf + written, ml->len - written);
if (n < 0) {
if (errno == EINTR)
continue;
if (errno != EWOULDBLOCK && errno != EAGAIN)
return -1;
if (!flush_it_all)
return 0;
FD_ZERO(&fds);
FD_SET(msg_fd_out, &fds);
tv.tv_sec = io_timeout ? io_timeout : SELECT_TIMEOUT;
tv.tv_usec = 0;
if (!select(msg_fd_out+1, NULL, &fds, NULL, &tv))
check_timeout();
} else if ((written += n) == ml->len) {
free(ml->buf);
msg_list_head = ml->next;
if (!msg_list_head)
msg_list_tail = NULL;
free(ml);
written = 0;
}
}
return 1;
}
int get_redo_num(void)
{
struct redo_list *next;
int num;
while (!redo_list_head)
read_msg_fd();
num = redo_list_head->num;
next = redo_list_head->next;
free(redo_list_head);
redo_list_head = next;
if (!next)
redo_list_tail = NULL;
return num;
}
/**
@@ -217,7 +370,7 @@ static int read_timeout(int fd, char *buf, size_t len)
{
int n, ret=0;
io_flush();
io_flush(NORMAL_FLUSH);
while (ret == 0) {
/* until we manage to read *something* */
@@ -228,14 +381,15 @@ static int read_timeout(int fd, char *buf, size_t len)
FD_ZERO(&r_fds);
FD_SET(fd, &r_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 (msg_fd_in >= 0) {
FD_SET(msg_fd_in, &r_fds);
if (msg_fd_in >= fd_count)
fd_count = msg_fd_in+1;
}
if (io_filesfrom_f_out != -1) {
if (io_filesfrom_f_out >= 0) {
int new_fd;
if (io_filesfrom_buflen == 0) {
if (io_filesfrom_f_in != -1) {
if (io_filesfrom_f_in >= 0) {
FD_SET(io_filesfrom_f_in, &r_fds);
new_fd = io_filesfrom_f_in;
} else {
@@ -247,7 +401,8 @@ static int read_timeout(int fd, char *buf, size_t len)
FD_SET(io_filesfrom_f_out, &w_fds);
new_fd = io_filesfrom_f_out;
}
if (new_fd >= fd_count) fd_count = new_fd+1;
if (new_fd >= fd_count)
fd_count = new_fd+1;
}
tv.tv_sec = io_timeout?io_timeout:SELECT_TIMEOUT;
@@ -260,6 +415,7 @@ static int read_timeout(int fd, char *buf, size_t len)
NULL, &tv);
if (count == 0) {
msg_list_push(NORMAL_FLUSH);
check_timeout();
}
@@ -270,11 +426,10 @@ static int read_timeout(int fd, char *buf, size_t len)
continue;
}
if (io_error_fd != -1 && FD_ISSET(io_error_fd, &r_fds)) {
read_error_fd();
}
if (msg_fd_in >= 0 && FD_ISSET(msg_fd_in, &r_fds))
read_msg_fd();
if (io_filesfrom_f_out != -1) {
if (io_filesfrom_f_out >= 0) {
if (io_filesfrom_buflen) {
if (FD_ISSET(io_filesfrom_f_out, &w_fds)) {
int l = write(io_filesfrom_f_out,
@@ -290,7 +445,7 @@ static int read_timeout(int fd, char *buf, size_t len)
io_filesfrom_f_out = -1;
}
}
} else if (io_filesfrom_f_in != -1) {
} else if (io_filesfrom_f_in >= 0) {
if (FD_ISSET(io_filesfrom_f_in, &r_fds)) {
int l = read(io_filesfrom_f_in,
io_filesfrom_buf,
@@ -352,7 +507,7 @@ static int read_timeout(int fd, char *buf, size_t len)
} else if (n == 0) {
whine_about_eof();
return -1; /* doesn't return */
} else if (n == -1) {
} else if (n < 0) {
if (errno == EINTR || errno == EWOULDBLOCK ||
errno == EAGAIN)
continue;
@@ -440,48 +595,69 @@ static int read_unbuffered(int fd, char *buf, size_t len)
static size_t remaining;
int tag, ret = 0;
char line[1024];
static char *buffer;
static size_t bufferIdx = 0;
static size_t bufferSz;
if (!io_multiplexing_in || fd != multiplex_in_fd)
if (fd != multiplex_in_fd)
return read_timeout(fd, buf, len);
if (!io_multiplexing_in && remaining == 0) {
if (!buffer) {
bufferSz = 2 * IO_BUFFER_SIZE;
buffer = new_array(char, bufferSz);
if (!buffer) out_of_memory("read_unbuffered");
}
remaining = read_timeout(fd, buffer, bufferSz);
bufferIdx = 0;
}
while (ret == 0) {
if (remaining) {
len = MIN(len, remaining);
read_loop(fd, buf, len);
memcpy(buf, buffer + bufferIdx, len);
bufferIdx += len;
remaining -= len;
ret = len;
continue;
break;
}
read_loop(fd, line, 4);
tag = IVAL(line, 0);
remaining = tag & 0xFFFFFF;
tag = tag >> 24;
tag = (tag >> 24) - MPLEX_BASE;
if (tag == MPLEX_BASE)
continue;
tag -= MPLEX_BASE;
if (tag != FERROR && tag != FINFO) {
switch (tag) {
case MSG_DATA:
if (!buffer || remaining > bufferSz) {
buffer = realloc_array(buffer, char, remaining);
if (!buffer) out_of_memory("read_unbuffered");
bufferSz = remaining;
}
read_loop(fd, buffer, remaining);
bufferIdx = 0;
break;
case MSG_INFO:
case MSG_ERROR:
if (remaining >= sizeof line) {
rprintf(FERROR, "multiplexing overflow %d:%ld\n\n",
tag, (long)remaining);
exit_cleanup(RERR_STREAMIO);
}
read_loop(fd, line, remaining);
rwrite((enum logcode)tag, line, remaining);
remaining = 0;
break;
default:
rprintf(FERROR, "unexpected tag %d\n", tag);
exit_cleanup(RERR_STREAMIO);
}
if (remaining > sizeof line - 1) {
rprintf(FERROR, "multiplexing overflow %ld\n\n",
(long)remaining);
exit_cleanup(RERR_STREAMIO);
}
read_loop(fd, line, remaining);
line[remaining] = 0;
rprintf((enum logcode) tag, "%s", line);
remaining = 0;
}
if (remaining == 0)
io_flush(NORMAL_FLUSH);
return ret;
}
@@ -498,8 +674,6 @@ static void readfd(int fd, char *buffer, size_t N)
size_t total=0;
while (total < N) {
io_flush();
ret = read_unbuffered(fd, buffer + total, N-total);
total += ret;
}
@@ -599,7 +773,7 @@ static void writefd_unbuffered(int fd,char *buf,size_t len)
int fd_count, count;
struct timeval tv;
err_list_push();
msg_list_push(NORMAL_FLUSH);
no_flush++;
@@ -608,24 +782,22 @@ static void writefd_unbuffered(int fd,char *buf,size_t len)
FD_SET(fd,&w_fds);
fd_count = fd;
if (io_error_fd != -1) {
if (msg_fd_in >= 0) {
FD_ZERO(&r_fds);
FD_SET(io_error_fd,&r_fds);
if (io_error_fd > fd_count)
fd_count = io_error_fd;
FD_SET(msg_fd_in,&r_fds);
if (msg_fd_in > fd_count)
fd_count = msg_fd_in;
}
tv.tv_sec = io_timeout?io_timeout:SELECT_TIMEOUT;
tv.tv_usec = 0;
errno = 0;
count = select(fd_count+1,
io_error_fd != -1?&r_fds:NULL,
&w_fds,NULL,
&tv);
count = select(fd_count+1, msg_fd_in >= 0 ? &r_fds : NULL,
&w_fds, NULL, &tv);
if (count == 0) {
msg_list_push(NORMAL_FLUSH);
check_timeout();
}
@@ -636,23 +808,21 @@ static void writefd_unbuffered(int fd,char *buf,size_t len)
continue;
}
if (io_error_fd != -1 && FD_ISSET(io_error_fd, &r_fds)) {
read_error_fd();
}
if (msg_fd_in >= 0 && FD_ISSET(msg_fd_in, &r_fds))
read_msg_fd();
if (FD_ISSET(fd, &w_fds)) {
int ret;
size_t n = len-total;
ret = write(fd,buf+total,n);
if (ret == -1 && errno == EINTR) {
continue;
}
if (ret == -1 &&
(errno == EWOULDBLOCK || errno == EAGAIN)) {
msleep(1);
continue;
if (ret < 0) {
if (errno == EINTR)
continue;
if (errno == EWOULDBLOCK || errno == EAGAIN) {
msleep(1);
continue;
}
}
if (ret <= 0) {
@@ -682,7 +852,7 @@ static void writefd_unbuffered(int fd,char *buf,size_t len)
static char *io_buffer;
static int io_buffer_count;
void io_start_buffering(int fd)
void io_start_buffering_out(int fd)
{
if (io_buffer) return;
multiplex_out_fd = fd;
@@ -691,11 +861,16 @@ void io_start_buffering(int fd)
io_buffer_count = 0;
}
void io_start_buffering_in(int fd)
{
multiplex_in_fd = fd;
}
/**
* Write an message to a multiplexed stream. If this fails then rsync
* exits.
**/
static void mplex_write(int fd, enum logcode code, char *buf, size_t len)
static void mplex_write(int fd, enum msgcode code, char *buf, size_t len)
{
char buffer[4096];
size_t n = len;
@@ -718,26 +893,26 @@ static void mplex_write(int fd, enum logcode code, char *buf, size_t len)
}
void io_flush(void)
void io_flush(int flush_it_all)
{
int fd = multiplex_out_fd;
msg_list_push(flush_it_all);
err_list_push();
if (!io_buffer_count || no_flush)
return;
if (!io_buffer_count || no_flush) return;
if (io_multiplexing_out) {
mplex_write(fd, FNONE, io_buffer, io_buffer_count);
} else {
if (io_multiplexing_out)
mplex_write(fd, MSG_DATA, io_buffer, io_buffer_count);
else
writefd_unbuffered(fd, io_buffer, io_buffer_count);
}
io_buffer_count = 0;
}
void io_end_buffering(void)
{
io_flush();
io_flush(NORMAL_FLUSH);
if (!io_multiplexing_out) {
free(io_buffer);
io_buffer = NULL;
@@ -748,7 +923,7 @@ static void writefd(int fd,char *buf,size_t len)
{
stats.total_written += len;
err_list_push();
msg_list_push(NORMAL_FLUSH);
if (!io_buffer || fd != multiplex_out_fd) {
writefd_unbuffered(fd, buf, len);
@@ -764,7 +939,8 @@ static void writefd(int fd,char *buf,size_t len)
io_buffer_count += n;
}
if (io_buffer_count == IO_BUFFER_SIZE) io_flush();
if (io_buffer_count == IO_BUFFER_SIZE)
io_flush(NORMAL_FLUSH);
}
}
@@ -876,35 +1052,35 @@ void io_printf(int fd, const char *format, ...)
}
/** Setup for multiplexing an error stream with the data stream */
/** Setup for multiplexing a MSG_* stream with the data stream. */
void io_start_multiplex_out(int fd)
{
multiplex_out_fd = fd;
io_flush();
io_start_buffering(fd);
io_flush(NORMAL_FLUSH);
io_start_buffering_out(fd);
io_multiplexing_out = 1;
}
/** Setup for multiplexing an error stream with the data stream */
/** Setup for multiplexing a MSG_* stream with the data stream. */
void io_start_multiplex_in(int fd)
{
multiplex_in_fd = fd;
io_flush();
io_flush(NORMAL_FLUSH);
io_multiplexing_in = 1;
}
/** Write an message to the multiplexed error stream */
int io_multiplex_write(enum logcode code, char *buf, size_t len)
/** Write an message to the multiplexed data stream. */
int io_multiplex_write(enum msgcode code, char *buf, size_t len)
{
if (!io_multiplexing_out) return 0;
io_flush();
io_flush(NORMAL_FLUSH);
stats.total_written += (len+4);
mplex_write(multiplex_out_fd, code, buf, len);
return 1;
}
/** Stop output multiplexing */
/** Stop output multiplexing. */
void io_multiplexing_close(void)
{
io_multiplexing_out = 0;

View File

@@ -1,49 +1 @@
.cvsignore
Makefile
a
b
config.cache
config.h
config.log
config.status
dist.tar.gz
dummy
rsync
rsync-0.1
rsync-0.1
rsync-0.1
rsync-0.1.tar.gz
rsync-0.2
rsync-0.2
rsync-0.2.tar.gz
rsync-0.3
rsync-0.3
rsync-0.3.tar.gz
rsync-0.4
rsync-0.4
rsync-0.4.tar.gz
rsync-0.5
rsync-0.5
rsync-0.5
rsync-0.5
rsync-0.5
rsync-0.5
rsync-0.5
rsync-0.5
rsync-0.5.tar.gz
rsync-0.6
rsync-0.7
rsync-0.7
rsync-0.8
rsync-0.8
rsync-0.8
rsync-0.8
rsync-ERSION
rsync.aux
rsync.dvi
rsync.log
tech_report.aux
tech_report.dvi
tech_report.log
tech_report.ps
test

View File

@@ -116,10 +116,12 @@
{
size_t len = strlen(s);
size_t ret = len;
if (bufsize <= 0) return 0;
if (len >= bufsize) len = bufsize-1;
memcpy(d, s, len);
d[len] = 0;
if (bufsize > 0) {
if (len >= bufsize)
len = bufsize-1;
memcpy(d, s, len);
d[len] = 0;
}
return ret;
}
#endif
@@ -138,10 +140,9 @@
size_t len2 = strlen(s);
size_t ret = len1 + len2;
if (len1+len2 >= bufsize) {
len2 = bufsize - (len1+1);
}
if (len2 > 0) {
if (len1 < bufsize - 1) {
if (len2 >= bufsize - len1)
len2 = bufsize - len1 - 1;
memcpy(d+len1, s, len2);
d[len1+len2] = 0;
}

199
lib/pool_alloc.3 Normal file
View File

@@ -0,0 +1,199 @@
.ds d \-\^\-
.ds o \fR[\fP
.ds c \fR]\fP
.ds | \fR|\fP
.de D
\\.B \*d\\$1
..
.de DI
\\.BI \*d\\$1 \\$2
..
.de DR
\\.BR \*d\\$1 \\$2
..
.de Di
\\.BI \*d\\$1 " \\$2"
..
.de Db
\\.B \*d\\$1 " \\$2"
..
.de Df
\\.B \*d\*ono\*c\\$1
..
.de See
See \fB\\$1\fP for details.
..
.de SeeIn
See \fB\\$1\fP in \fB\\$2\fP for details.
..
.TH POOL_ALLOC 3
.SH NAME
pool_alloc, pool_free, pool_talloc, pool_tfree, pool_create, pool_destroy
\- Allocate and free memory in managed allocation pools.
.SH SYNOPSIS
.B #include "pool_alloc.h"
\fBstruct alloc_pool *pool_create(size_t \fIsize\fB, size_t \fIquantum\fB, void (*\fIbomb\fB)(char *), int \fIflags\fB);
\fBvoid pool_destroy(struct alloc_pool *\fIpool\fB);
\fBvoid *pool_alloc(struct alloc_pool *\fIpool\fB, size_t \fIsize\fB, char *\fImsg\fB);
\fBvoid pool_free(struct alloc_pool *\fIpool\fB, sise_t \fIsize\fB, void *\fIaddr\fB);
\fBvoid *pool_talloc(struct alloc_pool *\fIpool\fB, \fItype\fB), int \fIcount\fB, char *\fImsg\fB);
\fBvoid pool_tfree(struct alloc_pool *\fIpool\fB, \fItype\fB, int \fIcount\fB, void *\fIaddr\fB);
.SH DESCRIPTION
.P
The pool allocation routines use
.B malloc()
for underlying memory management.
What allocation pools do is cause
memory within a given pool to be in large contigious blocks
(called extents) that when freed will be reusable. Unlike
.B malloc()
the allocations are not managed individually.
Instead each extent tracks the total free memory within the
extent. Each extent can either be used to allocate memory
or to manage the freeing of memory within that extent.
When an extent has less free memory than a given
allocation request or when the first request to free
memory within that extent is received the extent ceases to
be used for allocation.
.P
This form of memory management is suited to large numbers of small
related allocations that are held for a while
and then freed as a group.
Because the
underlying allocations are done in large contigious extents
when an extent is freed it releases a large enough
contigious block of memory to be useful to subsequent
.B malloc()
and
.B pool_alloc()
calls even if allocations from other pools or from
.B malloc()
are made between allocations from a given pool.
.P
.B pool_create()
Creates an allocation pool for subsequent calls to the pool
allocation functions.
When an extent is created for allocations it will be
.I size
bytes.
Allocations from the pool have their sizes rounded up to a
multiple of
.I quantum
bytes in length.
Specifying
.B 0
for
.I quantum
Will produce a quantum that should meet maximal allignment
on most platforms.
If the
.B POOL_QALIGN
.I flag
is set allocations will be aligned to addresses that are a
multiple of
.IR quantum .
If the
.B POOL_CLEAR
.I flag
is set all allocations from the pool will be zero filled.
.P
.B pool_destroy()
destroys an allocation pool and frees all memory allocated
in that pool.
.P
.B pool_alloc()
allocates
.I size
bytes from the specified
.IR pool .
If
.I size
is
.B 0
.I quantum
bytes will be freed.
If the requested memory cannot be allocated
.B pool_alloc()
will call
.I bomb()
function, if defined, with
.I msg
as it's sole argument and
.B NULL
will be returned.
.P
.B pool_free()
frees
.I size
bytes pointed to by
.I addr
previously allocated in the specified
.IR pool .
The memory freed within an extent will not be reusable until
all of the memory in that extent has been freed but
depending on the order in which the
allocations are freed some extents may be released for reuse
while others are still in use.
If
.I size
is
.B 0
.I quantum
bytes will be freed.
If
.I addr
is
.B 0
no memory will be freed but subsequent allocations will come
from a new extent.
.P
.B pool_talloc()
is a macro that take a
.I type
and
.I count
instead of
.I size
and will cast the return value to the correct type.
.P
.B pool_tfree
is a macro to free memory previously allocated in the
specified
.IR pool .
.SH RETURN VALUE
.B pool_create()
returns a pointer to
.BR "struct alloc_pool" .
.P
.B pool_alloc()
and
.B pool_talloc()
return pointers to the allocated memory,
or NULL if the request fails.
For each extent so long as no allocations are smaller than varaible
allignment requirements this pointer will be suitably
alligned for any kind of variable.
The return type of
.B pool_alloc()
will normally require casting to the desired type but
.B pool_talloc()
will returns a pointer of the requested
.IR type .
.P
.BR pool_free() ,
.B pool_tfree()
and
.B pool_destroy()
return no value.
.SH SEE ALSO
.nf
malloc(3)
.SH AUTHOR
pool_alloc was created by J.W. Schultz of Pegasystems Technologies.
.SH BUGS AND ISSUES

304
lib/pool_alloc.c Normal file
View File

@@ -0,0 +1,304 @@
#include "rsync.h"
#define POOL_DEF_EXTENT (32 * 1024)
struct alloc_pool
{
size_t size; /* extent size */
size_t quantum; /* allocation quantum */
struct pool_extent *live; /* current extent for
* allocations */
struct pool_extent *free; /* unfreed extent list */
void (*bomb)();
/* function to call if
* malloc fails */
int flags;
/* statistical data */
unsigned long e_created; /* extents created */
unsigned long e_freed; /* extents detroyed */
uint64 n_allocated; /* calls to alloc */
uint64 n_freed; /* calls to free */
uint64 b_allocated; /* cum. bytes allocated */
uint64 b_freed; /* cum. bytes freed */
};
struct pool_extent
{
void *start; /* starting address */
size_t free; /* free bytecount */
size_t bound; /* bytes bound by padding,
* overhead and freed */
struct pool_extent *next;
};
struct align_test {
void *foo;
uint64 bar;
};
#define MINALIGN offsetof(struct align_test, bar)
/* Temporarily cast a void* var into a char* var when adding an offset (to
* keep some compilers from complaining about the pointer arithmetic). */
#define PTR_ADD(b,o) ( (void*) ((char*)(b) + (o)) )
alloc_pool_t
pool_create(size_t size, size_t quantum,
void (*bomb)(char *), int flags)
{
struct alloc_pool *pool;
if (!(pool = (struct alloc_pool*) malloc(sizeof (struct alloc_pool))))
return pool;
memset(pool, 0, sizeof (struct alloc_pool));
pool->size = size /* round extent size to min alignment reqs */
? (size + MINALIGN - 1) & ~(MINALIGN - 1)
: POOL_DEF_EXTENT;
if (pool->flags & POOL_INTERN)
{
pool->size -= sizeof (struct pool_extent);
flags |= POOL_APPEND;
}
pool->quantum = quantum ? quantum : MINALIGN;
pool->bomb = bomb;
pool->flags = flags;
return pool;
}
void
pool_destroy(alloc_pool_t p)
{
struct alloc_pool *pool = (struct alloc_pool *) p;
struct pool_extent *cur, *next;
if (!pool)
return;
if (pool->live)
{
cur = pool->live;
free(cur->start);
if (!(pool->flags & POOL_APPEND))
free(cur);
}
for (cur = pool->free; cur; cur = next)
{
next = cur->next;
free(cur->start);
if (!(pool->flags & POOL_APPEND))
free(cur);
}
free(pool);
}
void *
pool_alloc(alloc_pool_t p, size_t len, char *bomb)
{
struct alloc_pool *pool = (struct alloc_pool *) p;
if (!pool)
return NULL;
if (!len)
len = pool->quantum;
else if (pool->quantum > 1 && len % pool->quantum)
len += pool->quantum - len % pool->quantum;
if (len > pool->size)
goto bomb;
if (!pool->live || len > pool->live->free)
{
void *start;
size_t free;
size_t bound;
size_t sqew;
size_t asize;
if (pool->live)
{
pool->live->next = pool->free;
pool->free = pool->live;
}
free = pool->size;
bound = 0;
asize = pool->size;
if (pool->flags & POOL_APPEND)
asize += sizeof (struct pool_extent);
if (!(start = (void *) malloc(asize)))
goto bomb;
if (pool->flags & POOL_CLEAR)
memset(start, 0, pool->size);
if (pool->flags & POOL_APPEND)
{
pool->live = PTR_ADD(start, free);
}
else if (!(pool->live = (struct pool_extent *) malloc(sizeof (struct pool_extent))))
{
goto bomb;
}
if (pool->flags & POOL_QALIGN && pool->quantum > 1
&& (sqew = (size_t)PTR_ADD(start, free) % pool->quantum))
{
bound += sqew;
free -= sqew;
}
pool->live->start = start;
pool->live->free = free;
pool->live->bound = bound;
pool->live->next = NULL;
pool->e_created++;
}
pool->n_allocated++;
pool->b_allocated += len;
pool->live->free -= len;
return PTR_ADD(pool->live->start, pool->live->free);
bomb:
if (pool->bomb)
(*pool->bomb)(bomb);
return NULL;
}
void
pool_free(alloc_pool_t p, size_t len, void *addr)
{
struct alloc_pool *pool = (struct alloc_pool *) p;
struct pool_extent *cur;
struct pool_extent *prev;
if (!pool)
return;
if (!len)
len = pool->quantum;
else if (pool->quantum > 1 && len % pool->quantum)
len += pool->quantum - len % pool->quantum;
if (!addr && pool->live)
{
pool->live->next = pool->free;
pool->free = pool->live;
pool->live = NULL;
return;
}
pool->n_freed++;
pool->b_freed += len;
cur = pool->live;
if (cur
&& addr >= cur->start
&& addr < PTR_ADD(cur->start, pool->size))
{
if (addr == PTR_ADD(cur->start, cur->free))
{
if (pool->flags & POOL_CLEAR)
memset(addr, 0, len);
pool->b_freed += len;
} else {
cur->bound += len;
}
if (cur->free + cur->bound >= pool->size)
{
size_t sqew;
cur->free = pool->size;
cur->bound = 0;
if (pool->flags & POOL_QALIGN && pool->quantum > 1
&& (sqew = (size_t)PTR_ADD(cur->start, cur->free) % pool->quantum))
{
cur->bound += sqew;
cur->free -= sqew;
}
}
return;
}
for (prev = NULL, cur = pool->free; cur; prev = cur, cur = cur->next)
{
if (addr >= cur->start
&& addr < PTR_ADD(cur->start, pool->size))
break;
}
if (!cur)
return;
if (prev)
{
prev->next = cur->next;
cur->next = pool->free;
pool->free = cur;
}
cur->bound += len;
if (cur->free + cur->bound >= pool->size)
{
pool->free = cur->next;
free(cur->start);
if (!(pool->flags & POOL_APPEND))
free(cur);
pool->e_freed++;
}
return;
}
#define FDPRINT(label, value) \
snprintf(buf, BUFSIZ, label, value), \
write(fd, buf, strlen(buf));
#define FDEXTSTAT(ext) \
snprintf(buf, BUFSIZ, " %12ld %5ld\n", \
(long) ext->free, \
(long) ext->bound), \
write(fd, buf, strlen(buf))
void
pool_stats(alloc_pool_t p, int fd, int summarize)
{
struct alloc_pool *pool = (struct alloc_pool *) p;
struct pool_extent *cur;
char buf[BUFSIZ];
if (!pool)
return;
FDPRINT(" Extent size: %12ld\n", (long) pool->size);
FDPRINT(" Alloc quantum: %12ld\n", (long) pool->quantum);
FDPRINT(" Extents created: %12ld\n", pool->e_created);
FDPRINT(" Extents freed: %12ld\n", pool->e_freed);
FDPRINT(" Alloc count: %12.0f\n", (double) pool->n_allocated);
FDPRINT(" Free Count: %12.0f\n", (double) pool->n_freed);
FDPRINT(" Alloc bytes: %12.0f\n", (double) pool->b_allocated);
FDPRINT(" Free bytes: %12.0f\n", (double) pool->b_freed);
if (summarize)
return;
if (!pool->live && !pool->free)
return;
write(fd, "\n", 1);
if (pool->live)
{
FDEXTSTAT(pool->live);
}
strcpy(buf, " FREE BOUND\n");
write(fd, buf, strlen(buf));
for (cur = pool->free; cur; cur = cur->next)
{
FDEXTSTAT(cur);
}
}

20
lib/pool_alloc.h Normal file
View File

@@ -0,0 +1,20 @@
#include <stddef.h>
#define POOL_CLEAR (1<<0) /* zero fill allocations */
#define POOL_QALIGN (1<<1) /* align data to quanta */
#define POOL_INTERN (1<<2) /* Allocate extent structures */
#define POOL_APPEND (1<<3) /* or appended to extent data */
typedef void *alloc_pool_t;
alloc_pool_t pool_create(size_t size, size_t quantum, void (*bomb)(char *), int flags);
void pool_destroy(alloc_pool_t pool);
void *pool_alloc(alloc_pool_t pool, size_t size, char *bomb);
void pool_free(alloc_pool_t pool, size_t size, void *addr);
#define pool_talloc(pool, type, count, bomb) \
((type *)pool_alloc(pool, sizeof(type) * count, bomb))
#define pool_tfree(pool, type, count, addr) \
(pool_free(pool, sizeof(type) * count, addr))

View File

@@ -101,14 +101,14 @@ typedef struct
char *motd_file;
char *log_file;
char *pid_file;
int syslog_facility;
char *socket_options;
int syslog_facility;
int max_verbosity;
} global;
static global Globals;
/*
* This structure describes a single service.
*/
@@ -268,6 +268,7 @@ static struct parm_struct parm_table[] =
{"socket options", P_STRING, P_GLOBAL, &Globals.socket_options,NULL, 0},
{"log file", P_STRING, P_GLOBAL, &Globals.log_file, NULL, 0},
{"pid file", P_STRING, P_GLOBAL, &Globals.pid_file, NULL, 0},
{"max verbosity", P_INTEGER, P_GLOBAL, &Globals.max_verbosity, NULL, 0},
{"timeout", P_INTEGER, P_LOCAL, &sDefault.timeout, NULL, 0},
{"max connections", P_INTEGER, P_LOCAL, &sDefault.max_connections,NULL, 0},
@@ -304,10 +305,11 @@ Initialise the global parameter structure.
***************************************************************************/
static void init_globals(void)
{
memset(&Globals, 0, sizeof(Globals));
memset(&Globals, 0, sizeof Globals);
#ifdef LOG_DAEMON
Globals.syslog_facility = LOG_DAEMON;
#endif
Globals.max_verbosity = 1;
}
/***************************************************************************
@@ -347,6 +349,7 @@ FN_GLOBAL_STRING(lp_log_file, &Globals.log_file)
FN_GLOBAL_STRING(lp_pid_file, &Globals.pid_file)
FN_GLOBAL_STRING(lp_socket_options, &Globals.socket_options)
FN_GLOBAL_INTEGER(lp_syslog_facility, &Globals.syslog_facility)
FN_GLOBAL_INTEGER(lp_max_verbosity, &Globals.max_verbosity)
FN_LOCAL_STRING(lp_name, name)
FN_LOCAL_STRING(lp_comment, comment)

122
log.c
View File

@@ -27,10 +27,18 @@
*/
#include "rsync.h"
extern int am_daemon;
extern int am_server;
extern int am_sender;
extern int quiet;
extern int module_id;
extern int msg_fd_out;
extern char *auth_user;
extern char *log_format;
static int log_initialised;
static char *logfname;
static FILE *logfile;
static int log_error_fd = -1;
struct stats stats;
int log_got_error=0;
@@ -77,61 +85,6 @@ static char const *rerr_name(int code)
return NULL;
}
struct err_list {
struct err_list *next;
char *buf;
int len;
int written; /* how many bytes we have written so far */
};
static struct err_list *err_list_head;
static struct err_list *err_list_tail;
/* add an error message to the pending error list */
static void err_list_add(int code, char *buf, int len)
{
struct err_list *el;
el = new(struct err_list);
if (!el) exit_cleanup(RERR_MALLOC);
el->next = NULL;
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);
el->len = len+4;
el->written = 0;
if (err_list_tail) {
err_list_tail->next = el;
} else {
err_list_head = el;
}
err_list_tail = el;
}
/* try to push errors off the error list onto the wire */
void err_list_push(void)
{
if (log_error_fd == -1) return;
while (err_list_head) {
struct err_list *el = err_list_head;
int n = write(log_error_fd, el->buf+el->written, el->len - el->written);
/* don't check for an error if the best way of handling the error is
* to ignore it */
if (n == -1) break;
if (n > 0) {
el->written += n;
}
if (el->written == el->len) {
free(el->buf);
err_list_head = el->next;
if (!err_list_head) err_list_tail = NULL;
free(el);
}
}
}
static void logit(int priority, char *buf)
{
@@ -203,27 +156,18 @@ void log_close(void)
}
}
/* setup the error file descriptor - used when we are a server
* that is receiving files */
void set_error_fd(int fd)
{
log_error_fd = fd;
set_nonblocking(log_error_fd);
}
/* this is the underlying (unformatted) rsync debugging function. Call
* it with FINFO, FERROR or FLOG */
void rwrite(enum logcode code, char *buf, int len)
{
FILE *f=NULL;
extern int am_daemon;
extern int am_server;
extern int quiet;
/* recursion can happen with certain fatal conditions */
if (quiet && code == FINFO) return;
if (quiet && code == FINFO)
return;
if (len < 0) exit_cleanup(RERR_MESSAGEIO);
if (len < 0)
exit_cleanup(RERR_MESSAGEIO);
buf[len] = 0;
@@ -232,17 +176,15 @@ void rwrite(enum logcode code, char *buf, int len)
return;
}
/* first try to pass it off to our sibling */
if (am_server && log_error_fd != -1) {
err_list_add(code, buf, len);
err_list_push();
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)) {
return;
if (am_server) {
/* Pass it to non-server side, perhaps through our sibling. */
if (msg_fd_out >= 0) {
send_msg((enum msgcode)code, buf, len);
return;
}
if (!am_daemon
&& io_multiplex_write((enum msgcode)code, buf, len))
return;
}
/* otherwise, if in daemon mode and either we are not a server
@@ -379,7 +321,6 @@ void rsyserr(enum logcode code, int errcode, const char *format, ...)
void rflush(enum logcode code)
{
FILE *f = NULL;
extern int am_daemon;
if (am_daemon) {
return;
@@ -394,7 +335,6 @@ void rflush(enum logcode code)
}
if (code == FINFO) {
extern int am_server;
if (am_server)
f = stderr;
else
@@ -413,15 +353,10 @@ static void log_formatted(enum logcode code,
char *format, char *op, struct file_struct *file,
struct stats *initial_stats)
{
extern int module_id;
extern char *auth_user;
char buf[1024];
char buf2[1024];
char *p, *s, *n;
size_t l;
extern struct stats stats;
extern int am_sender;
extern int am_daemon;
int64 b;
/* We expand % codes one by one in place in buf. We don't
@@ -451,8 +386,8 @@ static void log_formatted(enum logcode code,
break;
case 'o': n = op; break;
case 'f':
snprintf(buf2, sizeof(buf2), "%s/%s",
file->basedir?file->basedir:"",
pathjoin(buf2, sizeof buf2,
file->basedir ? file->basedir : "",
f_name(file));
clean_fname(buf2);
n = buf2;
@@ -519,10 +454,6 @@ static void log_formatted(enum logcode code,
/* log the outgoing transfer of a file */
void log_send(struct file_struct *file, struct stats *initial_stats)
{
extern int module_id;
extern int am_server;
extern char *log_format;
if (lp_transfer_logging(module_id)) {
log_formatted(FLOG, lp_log_format(module_id), "send", file, initial_stats);
} else if (log_format && !am_server) {
@@ -533,10 +464,6 @@ void log_send(struct file_struct *file, struct stats *initial_stats)
/* log the incoming transfer of a file */
void log_recv(struct file_struct *file, struct stats *initial_stats)
{
extern int module_id;
extern int am_server;
extern char *log_format;
if (lp_transfer_logging(module_id)) {
log_formatted(FLOG, lp_log_format(module_id), "recv", file, initial_stats);
} else if (log_format && !am_server) {
@@ -556,7 +483,6 @@ void log_recv(struct file_struct *file, struct stats *initial_stats)
void log_exit(int code, const char *file, int line)
{
if (code == 0) {
extern struct stats stats;
rprintf(FLOG,"wrote %.0f bytes read %.0f bytes total size %.0f\n",
(double)stats.total_written,
(double)stats.total_read,

212
main.c
View File

@@ -24,14 +24,40 @@
time_t starttime = 0;
extern struct stats stats;
extern char *files_from;
extern int filesfrom_fd;
extern char *remote_filesfrom_file;
extern int am_root;
extern int am_server;
extern int am_sender;
extern int am_generator;
extern int am_daemon;
extern int verbose;
extern int blocking_io;
extern int cvs_exclude;
extern int delete_mode;
extern int delete_excluded;
extern int delete_after;
extern int daemon_over_rsh;
extern int do_stats;
extern int dry_run;
extern int list_only;
extern int local_server;
extern int log_got_error;
extern int module_id;
extern int orig_umask;
extern int preserve_hard_links;
extern int protocol_version;
extern int recurse;
extern int relative_paths;
extern int rsync_port;
extern int read_batch;
extern int write_batch;
extern int filesfrom_fd;
extern pid_t cleanup_child_pid;
extern char *files_from;
extern char *remote_filesfrom_file;
extern char *rsync_path;
extern char *shell_cmd;
extern struct file_list *batch_flist;
/* there's probably never more than at most 2 outstanding child processes,
* but set it higher just in case.
@@ -55,7 +81,7 @@ void wait_process(pid_t pid, int *status)
while ((waited_pid = waitpid(pid, status, WNOHANG)) == 0) {
msleep(20);
io_flush();
io_flush(FULL_FLUSH);
}
if ((waited_pid == -1) && (errno == ECHILD)) {
@@ -82,8 +108,6 @@ void wait_process(pid_t pid, int *status)
static void report(int f)
{
time_t t = time(NULL);
extern int do_stats;
int send_stats;
if (do_stats && verbose > 1) {
/* These come out from every process */
@@ -91,14 +115,16 @@ static void report(int f)
show_flist_stats();
}
if (am_generator)
return;
if (am_daemon) {
log_exit(0, __FILE__, __LINE__);
if (f == -1 || !am_sender) return;
}
send_stats = verbose || protocol_version >= 20;
if (am_server) {
if (am_sender && send_stats) {
if (am_sender) {
int64 w;
/* store total_written in a temporary
* because write_longint changes it */
@@ -112,7 +138,7 @@ static void report(int f)
/* this is the client */
if (!am_sender && send_stats) {
if (!am_sender) {
int64 r;
stats.total_written = read_longint(f);
/* store total_read in a temporary, read_longint changes it */
@@ -122,12 +148,6 @@ static void report(int f)
}
if (do_stats) {
if (!am_sender && !send_stats) {
/* missing the bytes written by the generator */
rprintf(FINFO, "\nCannot show stats as receiver because remote protocol version is less than 20\n");
rprintf(FINFO, "Use --stats -v to show stats\n");
return;
}
rprintf(FINFO,"\nNumber of files: %d\n", stats.num_files);
rprintf(FINFO,"Number of files transferred: %d\n",
stats.num_transferred_files);
@@ -175,12 +195,14 @@ static void show_malloc_stats(void)
getpid(),
am_server ? "server " : "",
am_daemon ? "daemon " : "",
am_sender ? "sender" : "receiver");
who_am_i());
rprintf(FINFO, " arena: %10d (bytes from sbrk)\n", mi.arena);
rprintf(FINFO, " ordblks: %10d (chunks not in use)\n", mi.ordblks);
rprintf(FINFO, " smblks: %10d\n", mi.smblks);
rprintf(FINFO, " hblks: %10d (chunks from mmap)\n", mi.hblks);
rprintf(FINFO, " hblkhd: %10d (bytes from mmap)\n", mi.hblkhd);
rprintf(FINFO, " allmem: %10d (bytes from sbrk + mmap)\n",
mi.arena + mi.hblkhd);
rprintf(FINFO, " usmblks: %10d\n", mi.usmblks);
rprintf(FINFO, " fsmblks: %10d\n", mi.fsmblks);
rprintf(FINFO, " uordblks: %10d (bytes used)\n", mi.uordblks);
@@ -191,18 +213,14 @@ static void show_malloc_stats(void)
/* Start the remote shell. cmd may be NULL to use the default. */
static pid_t do_cmd(char *cmd,char *machine,char *user,char *path,int *f_in,int *f_out)
static pid_t do_cmd(char *cmd, char *machine, char *user, char *path,
int *f_in, int *f_out)
{
int i, argc = 0;
char *args[100];
int i,argc=0;
pid_t ret;
char *tok,*dir=NULL;
char *tok, *dir = NULL;
int dash_l_set = 0;
extern int local_server;
extern char *rsync_path;
extern int blocking_io;
extern int daemon_over_rsh;
extern int read_batch;
if (!read_batch && !local_server) {
char *rsh_env = getenv(RSYNC_RSH_ENV);
@@ -214,9 +232,8 @@ static pid_t do_cmd(char *cmd,char *machine,char *user,char *path,int *f_in,int
if (!cmd)
goto oom;
for (tok=strtok(cmd," ");tok;tok=strtok(NULL," ")) {
for (tok = strtok(cmd, " "); tok; tok = strtok(NULL, " "))
args[argc++] = tok;
}
/* check to see if we've already been given '-l user' in
* the remote-shell command */
@@ -260,6 +277,11 @@ static pid_t do_cmd(char *cmd,char *machine,char *user,char *path,int *f_in,int
if (!daemon_over_rsh && path && *path)
args[argc++] = path;
if (argc >= (int)(sizeof args / sizeof args[0])) {
rprintf(FERROR, "internal: args[] overflowed in do_cmd()\n");
exit_cleanup(RERR_MALLOC); /* XXX Need better RERR? */
}
args[argc] = NULL;
if (verbose > 3) {
@@ -287,13 +309,10 @@ oom:
}
static char *get_local_name(struct file_list *flist,char *name)
{
STRUCT_STAT st;
int e;
extern int orig_umask;
if (verbose > 2)
rprintf(FINFO,"get_local_name count=%d %s\n",
@@ -304,7 +323,7 @@ static char *get_local_name(struct file_list *flist,char *name)
if (do_stat(name,&st) == 0) {
if (S_ISDIR(st.st_mode)) {
if (!push_dir(name, 0)) {
if (!push_dir(name)) {
rprintf(FERROR, "push_dir %s failed: %s (1)\n",
full_fname(name), strerror(errno));
exit_cleanup(RERR_FILESELECT);
@@ -330,7 +349,7 @@ static char *get_local_name(struct file_list *flist,char *name)
rprintf(FINFO,"created directory %s\n",name);
}
if (!push_dir(name, 0)) {
if (!push_dir(name)) {
rprintf(FERROR, "push_dir %s failed: %s (2)\n",
full_fname(name), strerror(errno));
exit_cleanup(RERR_FILESELECT);
@@ -340,20 +359,18 @@ static char *get_local_name(struct file_list *flist,char *name)
}
static void do_server_sender(int f_in, int f_out, int argc,char *argv[])
{
int i;
struct file_list *flist;
char *dir = argv[0];
extern int relative_paths;
extern int recurse;
if (verbose > 2)
rprintf(FINFO,"server_sender starting pid=%d\n",(int)getpid());
if (verbose > 2) {
rprintf(FINFO, "server_sender starting pid=%ld\n",
(long)getpid());
}
if (!relative_paths && !push_dir(dir, 0)) {
if (!relative_paths && !push_dir(dir)) {
rprintf(FERROR, "push_dir %s failed: %s (3)\n",
full_fname(dir), strerror(errno));
exit_cleanup(RERR_FILESELECT);
@@ -380,14 +397,16 @@ static void do_server_sender(int f_in, int f_out, int argc,char *argv[])
exit_cleanup(0);
}
io_start_buffering_in(f_in);
io_start_buffering_out(f_out);
send_files(flist,f_out,f_in);
io_flush();
io_flush(FULL_FLUSH);
report(f_out);
if (protocol_version >= 24) {
/* final goodbye message */
read_int(f_in);
}
io_flush();
read_int(f_in);
}
io_flush(FULL_FLUSH);
exit_cleanup(0);
}
@@ -396,12 +415,7 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
{
int pid;
int status=0;
int recv_pipe[2];
int error_pipe[2];
extern int preserve_hard_links;
extern int delete_after;
extern int recurse;
extern int delete_mode;
if (preserve_hard_links)
init_hard_links(flist);
@@ -413,20 +427,14 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
}
}
if (fd_pair(recv_pipe) < 0) {
rprintf(FERROR,"pipe failed in do_recv\n");
exit_cleanup(RERR_SOCKETIO);
}
if (fd_pair(error_pipe) < 0) {
rprintf(FERROR,"error pipe failed in do_recv\n");
exit_cleanup(RERR_SOCKETIO);
}
io_flush();
io_flush(NORMAL_FLUSH);
if ((pid=do_fork()) == 0) {
close(recv_pipe[0]);
close(error_pipe[0]);
if (f_in != f_out) close(f_out);
@@ -434,41 +442,42 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
io_multiplexing_close();
/* set place to send errors */
set_error_fd(error_pipe[1]);
set_msg_fd_out(error_pipe[1]);
recv_files(f_in,flist,local_name,recv_pipe[1]);
io_flush();
recv_files(f_in,flist,local_name);
io_flush(FULL_FLUSH);
report(f_in);
write_int(recv_pipe[1],1);
close(recv_pipe[1]);
io_flush();
send_msg(MSG_DONE, "", 0);
io_flush(FULL_FLUSH);
/* finally we go to sleep until our parent kills us
* with a USR2 signal. We sleep for a short time as on
* some OSes a signal won't interrupt a sleep! */
while (msleep(20))
;
while (1)
msleep(20);
}
close(recv_pipe[1]);
am_generator = 1;
close(error_pipe[1]);
if (f_in != f_out) close(f_in);
io_start_buffering(f_out);
io_start_buffering_out(f_out);
io_set_error_fd(error_pipe[0]);
set_msg_fd_in(error_pipe[0]);
generate_files(f_out,flist,local_name,recv_pipe[0]);
generate_files(f_out, flist, local_name);
read_int(recv_pipe[0]);
close(recv_pipe[0]);
get_redo_num(); /* Read final MSG_DONE and any prior messages. */
report(-1);
io_flush(FULL_FLUSH);
if (protocol_version >= 24) {
/* send a final goodbye message */
write_int(f_out, -1);
}
io_flush();
io_flush(FULL_FLUSH);
io_set_error_fd(-1);
set_msg_fd_in(-1);
kill(pid, SIGUSR2);
wait_process(pid, &status);
return status;
@@ -479,16 +488,13 @@ static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
{
int status;
struct file_list *flist;
char *local_name=NULL;
char *local_name = NULL;
char *dir = NULL;
extern int delete_mode;
extern int delete_excluded;
extern int module_id;
extern int read_batch;
extern struct file_list *batch_flist;
if (verbose > 2)
rprintf(FINFO,"server_recv(%d) starting pid=%d\n",argc,(int)getpid());
if (verbose > 2) {
rprintf(FINFO, "server_recv(%d) starting pid=%ld\n",
argc, (long)getpid());
}
if (am_daemon && lp_read_only(module_id) && !am_sender) {
rprintf(FERROR,"ERROR: module is read only\n");
@@ -501,13 +507,14 @@ static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
dir = argv[0];
argc--;
argv++;
if (!am_daemon && !push_dir(dir, 0)) {
if (!am_daemon && !push_dir(dir)) {
rprintf(FERROR, "push_dir %s failed: %s (4)\n",
full_fname(dir), strerror(errno));
exit_cleanup(RERR_FILESELECT);
}
}
io_start_buffering_in(f_in);
if (delete_mode && !delete_excluded)
recv_exclude_list(f_in);
@@ -551,9 +558,6 @@ int child_main(int argc, char *argv[])
void start_server(int f_in, int f_out, int argc, char *argv[])
{
extern int cvs_exclude;
extern int read_batch;
setup_protocol(f_out, f_in);
set_nonblocking(f_in);
@@ -585,10 +589,6 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
struct file_list *flist = NULL;
int status = 0, status2 = 0;
char *local_name = NULL;
extern pid_t cleanup_child_pid;
extern int write_batch;
extern int read_batch;
extern struct file_list *batch_flist;
cleanup_child_pid = pid;
if (read_batch)
@@ -603,21 +603,21 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
io_start_multiplex_in(f_in);
if (am_sender) {
extern int cvs_exclude;
extern int delete_mode;
extern int delete_excluded;
io_start_buffering_out(f_out);
if (cvs_exclude)
add_cvs_excludes();
if (delete_mode && !delete_excluded)
send_exclude_list(f_out);
if (remote_filesfrom_file)
filesfrom_fd = f_in;
if (!read_batch) /* dw -- don't write to pipe */
if (!read_batch) /* don't write to pipe */
flist = send_file_list(f_out,argc,argv);
if (verbose > 3)
rprintf(FINFO,"file list sent\n");
io_flush(NORMAL_FLUSH);
send_files(flist,f_out,f_in);
io_flush(FULL_FLUSH);
if (protocol_version >= 24) {
/* final goodbye message */
read_int(f_in);
@@ -625,15 +625,15 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
if (pid != -1) {
if (verbose > 3)
rprintf(FINFO,"client_run waiting on %d\n", (int) pid);
io_flush();
io_flush(FULL_FLUSH);
wait_process(pid, &status);
}
report(-1);
io_flush(FULL_FLUSH);
exit_cleanup(status);
}
if (argc == 0) {
extern int list_only;
list_only = 1;
}
@@ -660,7 +660,7 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
if (pid != -1) {
if (verbose > 3)
rprintf(FINFO,"client_run2 waiting on %d\n", (int) pid);
io_flush();
io_flush(FULL_FLUSH);
wait_process(pid, &status);
}
@@ -700,11 +700,6 @@ static int start_client(int argc, char *argv[])
int ret;
pid_t pid;
int f_in,f_out;
extern int local_server;
extern char *shell_cmd;
extern int rsync_port;
extern int daemon_over_rsh;
extern int read_batch;
int rc;
/* Don't clobber argv[] so that ps(1) can still show the right
@@ -833,7 +828,7 @@ static int start_client(int argc, char *argv[])
}
if (shell_machine) {
p = strchr(shell_machine,'@');
p = strrchr(shell_machine,'@');
if (p) {
*p = 0;
shell_user = shell_machine;
@@ -855,7 +850,6 @@ static int start_client(int argc, char *argv[])
}
if (argc == 0 && !am_sender) {
extern int list_only;
list_only = 1;
}
@@ -888,7 +882,6 @@ static RETSIGTYPE sigusr1_handler(UNUSED(int val))
static RETSIGTYPE sigusr2_handler(UNUSED(int val))
{
extern int log_got_error;
if (log_got_error) _exit(RERR_PARTIAL);
_exit(0);
}
@@ -971,11 +964,7 @@ static RETSIGTYPE rsync_panic_handler(UNUSED(int whatsig))
int main(int argc,char *argv[])
{
extern int am_root;
extern int orig_umask;
extern int dry_run;
int ret;
extern int write_batch;
int orig_argc;
char **orig_argv;
@@ -993,7 +982,7 @@ int main(int argc,char *argv[])
#endif /* def MAINTAINER_MODE */
starttime = time(NULL);
am_root = (getuid() == 0);
am_root = (MY_UID() == 0);
memset(&stats, 0, sizeof(stats));
@@ -1025,7 +1014,9 @@ int main(int argc,char *argv[])
* (implemented by forking "pwd" and reading its output) doesn't
* work when there are other child processes. Also, on all systems
* that implement getcwd that way "pwd" can't be found after chroot. */
push_dir(NULL,0);
push_dir(NULL);
init_flist();
if (write_batch && !am_server) {
write_batch_argvs_file(orig_argc, orig_argv);
@@ -1042,13 +1033,6 @@ int main(int argc,char *argv[])
if (dry_run)
verbose = MAX(verbose,1);
#ifndef SUPPORT_LINKS
if (!am_server && preserve_links) {
rprintf(FERROR,"ERROR: symbolic links not supported\n");
exit_cleanup(RERR_UNSUPPORTED);
}
#endif
if (am_server) {
set_nonblocking(STDIN_FILENO);
set_nonblocking(STDOUT_FILENO);

89
match.c
View File

@@ -26,7 +26,7 @@ extern int do_progress;
typedef unsigned short tag;
#define TABLESIZE (1<<16)
#define NULL_TAG (-1)
#define NULL_TAG ((size_t)-1)
static int false_alarms;
static int tag_hits;
@@ -41,12 +41,12 @@ extern struct stats stats;
struct target {
tag t;
int i;
size_t i;
};
static struct target *targets;
static int *tag_table;
static size_t *tag_table;
#define gettag2(s1,s2) (((s1) + (s2)) & 0xFFFF)
#define gettag(sum) gettag2((sum)&0xFFFF,(sum)>>16)
@@ -59,16 +59,16 @@ static int compare_targets(struct target *t1,struct target *t2)
static void build_hash_table(struct sum_struct *s)
{
int i;
size_t i;
if (!tag_table)
tag_table = new_array(int, TABLESIZE);
tag_table = new_array(size_t, TABLESIZE);
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++) {
for (i = 0; i < s->count; i++) {
targets[i].i = i;
targets[i].t = gettag(s->sums[i].sum1);
}
@@ -78,7 +78,7 @@ static void build_hash_table(struct sum_struct *s)
for (i = 0; i < TABLESIZE; i++)
tag_table[i] = NULL_TAG;
for (i = s->count-1; i >= 0; i--)
for (i = s->count; i-- > 0; )
tag_table[targets[i].t] = i;
}
@@ -105,7 +105,7 @@ static void matched(int f,struct sum_struct *s,struct map_struct *buf,
OFF_T j;
if (verbose > 2 && i >= 0)
rprintf(FINFO,"match at %.0f last_match=%.0f j=%d len=%d n=%.0f\n",
rprintf(FINFO,"match at %.0f last_match=%.0f j=%d len=%u n=%.0f\n",
(double)offset,(double)last_match,i,s->sums[i].len,(double)n);
send_token(f,i,buf,last_match,n,i<0?0:s->sums[i].len);
@@ -130,72 +130,78 @@ static void matched(int f,struct sum_struct *s,struct map_struct *buf,
if (buf && do_progress) {
show_progress(last_match, buf->file_size);
if (i == -1) end_progress(buf->file_size);
if (i == -1)
end_progress(buf->file_size);
}
}
static void hash_search(int f,struct sum_struct *s,
struct map_struct *buf,OFF_T len)
struct map_struct *buf, OFF_T len)
{
OFF_T offset, end;
int j,k, last_i;
unsigned int k;
size_t last_i;
char sum2[SUM_LENGTH];
uint32 s1, s2, sum;
schar *map;
/* last_i is used to encourage adjacent matches, allowing the RLL coding of the
output to work more efficiently */
last_i = -1;
last_i = (size_t)-1;
if (verbose > 2)
rprintf(FINFO,"hash search b=%ld len=%.0f\n",
(long) s->blength, (double)len);
if (verbose > 2) {
rprintf(FINFO,"hash search b=%u len=%.0f\n",
s->blength, (double)len);
}
k = MIN(len, (OFF_T)s->blength);
k = MIN(len, s->blength);
map = (schar *)map_ptr(buf,0,k);
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);
rprintf(FINFO, "sum=%.8x k=%u\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);
if (verbose > 3) {
rprintf(FINFO, "hash search s->blength=%u len=%.0f count=%.0f\n",
s->blength, (double)len, (double)s->count);
}
do {
tag t = gettag2(s1,s2);
int done_csum2 = 0;
size_t j = tag_table[t];
j = tag_table[t];
if (verbose > 4)
rprintf(FINFO,"offset=%.0f sum=%08x\n",(double)offset,sum);
if (j == NULL_TAG) {
if (j == NULL_TAG)
goto null_tag;
}
sum = (s1 & 0xffff) | (s2 << 16);
tag_hits++;
for (; j < (int) s->count && targets[j].t == t; j++) {
int l, i = targets[j].i;
for (; j < s->count && targets[j].t == t; j++) {
unsigned int l;
size_t i = targets[j].i;
if (sum != s->sums[i].sum1) continue;
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;
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);
rprintf(FINFO,"potential match at %.0f target=%.0f %.0f sum=%08x\n",
(double)offset,(double)j,(double)i,sum);
if (!done_csum2) {
map = (schar *)map_ptr(buf,offset,l);
@@ -210,11 +216,13 @@ 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 < (int) s->count && targets[j].t == t; j++) {
int i2 = targets[j].i;
for (j++; j < s->count && targets[j].t == t; j++) {
size_t 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;
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 */
i = i2;
@@ -226,8 +234,8 @@ static void hash_search(int f,struct sum_struct *s,
matched(f,s,buf,offset,i);
offset += s->sums[i].len - 1;
k = MIN((OFF_T)s->blength, len-offset);
map = (schar *)map_ptr(buf,offset,k);
k = MIN(s->blength, len-offset);
map = (schar *)map_ptr(buf, offset, k);
sum = get_checksum1((char *)map, k);
s1 = sum & 0xFFFF;
s2 = sum >> 16;
@@ -237,7 +245,7 @@ static void hash_search(int f,struct sum_struct *s,
null_tag:
/* Trim off the first byte from the checksum */
map = (schar *)map_ptr(buf,offset,k+1);
map = (schar *)map_ptr(buf, offset, k+1);
s1 -= map[0] + CHAR_OFFSET;
s2 -= k * (map[0]+CHAR_OFFSET);
@@ -245,9 +253,8 @@ static void hash_search(int f,struct sum_struct *s,
if (k < (len-offset)) {
s1 += (map[k]+CHAR_OFFSET);
s2 += s1;
} else {
} else
--k;
}
/* By matching early we avoid re-reading the
data 3 times in the case where a token
@@ -284,7 +291,7 @@ static void hash_search(int f,struct sum_struct *s,
void match_sums(int f, struct sum_struct *s, struct map_struct *buf, OFF_T len)
{
char file_sum[MD4_SUM_LENGTH];
extern int write_batch; /* dw */
extern int write_batch;
last_match = 0;
false_alarms = 0;
@@ -319,7 +326,7 @@ void match_sums(int f, struct sum_struct *s, struct map_struct *buf, OFF_T len)
if (verbose > 2)
rprintf(FINFO,"sending file_sum\n");
write_buf(f,file_sum,MD4_SUM_LENGTH);
if (write_batch) /* dw */
if (write_batch)
write_batch_delta_file(file_sum, MD4_SUM_LENGTH);
if (targets) {

View File

@@ -58,7 +58,7 @@ BEGIN {
next;
}
!/^OFF_T|^size_t|^off_t|^pid_t|^unsigned|^mode_t|^DIR|^user|^int|^char|^uint|^struct|^BOOL|^void|^time/ {
!/^OFF_T|^size_t|^off_t|^pid_t|^unsigned|^mode_t|^DIR|^user|^int|^char|^uint|^struct|^BOOL|^void|^time|^const/ {
next;
}

378
options.c
View File

@@ -21,7 +21,9 @@
#include "rsync.h"
#include "popt.h"
extern struct exclude_struct **exclude_list;
extern int sanitize_paths;
extern char curr_dir[MAXPATHLEN];
extern struct exclude_list_struct exclude_list;
int make_backups = 0;
@@ -46,17 +48,17 @@ int preserve_gid = 0;
int preserve_times = 0;
int update_only = 0;
int cvs_exclude = 0;
int dry_run=0;
int local_server=0;
int ignore_times=0;
int delete_mode=0;
int delete_excluded=0;
int one_file_system=0;
int dry_run = 0;
int local_server = 0;
int ignore_times = 0;
int delete_mode = 0;
int delete_excluded = 0;
int one_file_system = 0;
int protocol_version = PROTOCOL_VERSION;
int sparse_files=0;
int do_compression=0;
int am_root=0;
int orig_umask=0;
int sparse_files = 0;
int do_compression = 0;
int am_root = 0;
int orig_umask = 0;
int relative_paths = -1;
int implied_dirs = 1;
int numeric_ids = 0;
@@ -66,6 +68,7 @@ int read_only = 0;
int module_id = -1;
int am_server = 0;
int am_sender = 0;
int am_generator = 0;
char *files_from = NULL;
int filesfrom_fd = -1;
char *remote_filesfrom_file = NULL;
@@ -73,21 +76,22 @@ int eol_nulls = 0;
int recurse = 0;
int am_daemon = 0;
int daemon_over_rsh = 0;
int do_stats=0;
int do_progress=0;
int keep_partial=0;
int safe_symlinks=0;
int copy_unsafe_links=0;
int block_size=0;
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;
int modify_window=0;
int blocking_io=-1;
int do_stats = 0;
int do_progress = 0;
int keep_partial = 0;
int safe_symlinks = 0;
int copy_unsafe_links = 0;
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;
int modify_window = 0;
int blocking_io = -1;
int checksum_seed = 0;
unsigned int block_size = 0;
/** Network address family. **/
@@ -106,6 +110,7 @@ int write_batch = 0;
int read_batch = 0;
int backup_dir_len = 0;
int backup_suffix_len;
unsigned int backup_dir_remainder;
char *backup_suffix = NULL;
char *tmpdir = NULL;
@@ -116,6 +121,7 @@ char *log_format = NULL;
char *password_file = NULL;
char *rsync_path = RSYNC_PATH;
char *backup_dir = NULL;
char backup_dir_buf[MAXPATHLEN];
int rsync_port = RSYNC_PORT;
int link_dest = 0;
@@ -124,8 +130,11 @@ int quiet = 0;
int always_checksum = 0;
int list_only = 0;
#define FIXED_CHECKSUM_SEED 32761
#define MAX_BATCH_PREFIX_LEN 256 /* Must be less than MAXPATHLEN-13 */
char *batch_prefix = NULL;
static int daemon_opt; /* sets am_daemon after option error-reporting */
static int modify_window_set;
/** Local address to bind. As a character string because it's
@@ -165,7 +174,7 @@ static void print_rsync_version(enum logcode f)
rprintf(f, "<http://rsync.samba.org/>\n");
rprintf(f, "Capabilities: %d-bit files, %ssocketpairs, "
"%shard links, %ssymlinks, batchfiles, \n",
(int) (sizeof(OFF_T) * 8),
(int) (sizeof (OFF_T) * 8),
got_socketpair, hardlinks, links);
/* Note that this field may not have type ino_t. It depends
@@ -173,8 +182,8 @@ static void print_rsync_version(enum logcode f)
* macros. */
rprintf(f, " %sIPv6, %d-bit system inums, %d-bit internal inums\n",
ipv6,
(int) (sizeof(dumstat->st_ino) * 8),
(int) (sizeof(INO64_T) * 8));
(int) (sizeof dumstat->st_ino * 8),
(int) (sizeof (uint64) * 8));
#ifdef MAINTAINER_MODE
rprintf(f, " panic action: \"%s\"\n",
get_panic_action());
@@ -223,9 +232,9 @@ void usage(enum logcode F)
rprintf(F," --suffix=SUFFIX backup suffix (default %s w/o --backup-dir)\n",BACKUP_SUFFIX);
rprintf(F," -u, --update update only (don't overwrite newer files)\n");
rprintf(F," -l, --links copy symlinks as symlinks\n");
rprintf(F," -L, --copy-links copy the referent of symlinks\n");
rprintf(F," --copy-unsafe-links copy links outside the source tree\n");
rprintf(F," --safe-links ignore links outside the destination tree\n");
rprintf(F," -L, --copy-links copy the referent of all symlinks\n");
rprintf(F," --copy-unsafe-links copy the referent of \"unsafe\" symlinks\n");
rprintf(F," --safe-links ignore \"unsafe\" symlinks\n");
rprintf(F," -H, --hard-links preserve hard links\n");
rprintf(F," -p, --perms preserve permissions\n");
rprintf(F," -o, --owner preserve owner (root only)\n");
@@ -244,13 +253,13 @@ void usage(enum logcode F)
rprintf(F," --ignore-existing ignore files that already exist on 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");
rprintf(F," --ignore-errors delete even if there are IO errors\n");
rprintf(F," --delete-after receiver deletes after transferring, not before\n");
rprintf(F," --ignore-errors delete even if there are I/O errors\n");
rprintf(F," --max-delete=NUM don't delete more than NUM files\n");
rprintf(F," --partial keep partially transferred files\n");
rprintf(F," --force force deletion of directories even if not empty\n");
rprintf(F," --numeric-ids don't map uid/gid values by user/group name\n");
rprintf(F," --timeout=TIME set IO timeout in seconds\n");
rprintf(F," --timeout=TIME set I/O timeout in seconds\n");
rprintf(F," -I, --ignore-times turn off mod time & file size quick check\n");
rprintf(F," --size-only ignore mod time for quick check (use size)\n");
rprintf(F," --modify-window=NUM compare mod times with reduced accuracy\n");
@@ -267,12 +276,12 @@ void usage(enum logcode F)
rprintf(F," --files-from=FILE read FILE for list of source-file names\n");
rprintf(F," -0 --from0 all *-from file lists are delimited by nulls\n");
rprintf(F," --version print version number\n");
rprintf(F," --daemon run as a rsync daemon\n");
rprintf(F," --daemon run as an rsync daemon\n");
rprintf(F," --no-detach do not detach from the parent\n");
rprintf(F," --address=ADDRESS bind to the specified address\n");
rprintf(F," --config=FILE specify alternate rsyncd.conf file\n");
rprintf(F," --port=PORT specify alternate rsyncd port number\n");
rprintf(F," --blocking-io use blocking IO for the remote shell\n");
rprintf(F," --blocking-io use blocking I/O for the remote shell\n");
rprintf(F," --no-blocking-io turn off --blocking-io\n");
rprintf(F," --stats give some file transfer stats\n");
rprintf(F," --progress show progress during transfer\n");
@@ -296,7 +305,8 @@ void usage(enum logcode F)
enum {OPT_VERSION = 1000, OPT_SENDER, OPT_EXCLUDE, OPT_EXCLUDE_FROM,
OPT_DELETE_AFTER, OPT_DELETE_EXCLUDED, OPT_LINK_DEST,
OPT_INCLUDE, OPT_INCLUDE_FROM, OPT_MODIFY_WINDOW,
OPT_READ_BATCH, OPT_WRITE_BATCH};
OPT_READ_BATCH, OPT_WRITE_BATCH,
OPT_REFUSED_BASE = 9000};
static struct poptOption long_options[] = {
/* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
@@ -351,10 +361,10 @@ static struct poptOption long_options[] = {
{"timeout", 0, POPT_ARG_INT, &io_timeout, 0, 0, 0 },
{"temp-dir", 'T', POPT_ARG_STRING, &tmpdir, 0, 0, 0 },
{"compare-dest", 0, POPT_ARG_STRING, &compare_dest, 0, 0, 0 },
{"link-dest", 0, POPT_ARG_STRING, 0, OPT_LINK_DEST, 0, 0 },
{"link-dest", 0, POPT_ARG_STRING, &compare_dest, OPT_LINK_DEST, 0, 0 },
/* TODO: Should this take an optional int giving the compression level? */
{"compress", 'z', POPT_ARG_NONE, &do_compression, 0, 0, 0 },
{"daemon", 0, POPT_ARG_NONE, &am_daemon, 0, 0, 0 },
{"daemon", 0, POPT_ARG_NONE, &daemon_opt, 0, 0, 0 },
{"no-detach", 0, POPT_ARG_NONE, &no_detach, 0, 0, 0 },
{"stats", 0, POPT_ARG_NONE, &do_stats, 0, 0, 0 },
{"progress", 0, POPT_ARG_NONE, &do_progress, 0, 0, 0 },
@@ -407,33 +417,34 @@ void option_error(void)
/**
* Check to see if we should refuse this option
* Tweak the option table to disable all options that the rsyncd.conf
* file has told us to refuse.
**/
static int check_refuse_options(char *ref, int opt)
static void set_refuse_options(char *bp)
{
int i, len;
char *p;
const char *name;
struct poptOption *op;
char *cp;
for (i=0; long_options[i].longName; i++) {
if (long_options[i].val == opt) break;
}
if (!long_options[i].longName) return 0;
name = long_options[i].longName;
len = strlen(name);
while ((p = strstr(ref,name))) {
if ((p==ref || p[-1]==' ') &&
(p[len] == ' ' || p[len] == 0)) {
snprintf(err_buf,sizeof(err_buf),
"The '%s' option is not supported by this server\n", name);
return 1;
while (1) {
if ((cp = strchr(bp, ' ')) != NULL)
*cp= '\0';
for (op = long_options; ; op++) {
if (!op->longName) {
rprintf(FLOG,
"Unknown option %s in \"refuse options\" setting\n",
bp);
break;
}
if (strcmp(bp, op->longName) == 0) {
op->val = (op - long_options)+OPT_REFUSED_BASE;
break;
}
}
ref += len;
if (!cp)
break;
*cp = ' ';
bp = cp + 1;
}
return 0;
}
@@ -460,8 +471,12 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
{
int opt;
char *ref = lp_refuse_options(module_id);
const char *arg;
poptContext pc;
if (ref && *ref)
set_refuse_options(ref);
/* TODO: Call poptReadDefaultConfig; handle errors. */
/* The context leaks in case of an error, but if there's a
@@ -469,10 +484,6 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
pc = poptGetContext(RSYNC_NAME, *argc, *argv, long_options, 0);
while ((opt = poptGetNextOpt(pc)) != -1) {
if (ref) {
if (check_refuse_options(ref, opt)) return 0;
}
/* most options are handled automatically by popt;
* only special cases are returned and listed here. */
@@ -499,53 +510,41 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
break;
case OPT_EXCLUDE:
add_exclude(&exclude_list, poptGetOptArg(pc),
ADD_EXCLUDE);
add_exclude(&exclude_list, poptGetOptArg(pc), 0);
break;
case OPT_INCLUDE:
add_exclude(&exclude_list, poptGetOptArg(pc),
ADD_INCLUDE);
XFLG_DEF_INCLUDE);
break;
case OPT_EXCLUDE_FROM:
add_exclude_file(&exclude_list, poptGetOptArg(pc),
MISSING_FATAL, ADD_EXCLUDE);
arg = poptGetOptArg(pc);
if (sanitize_paths)
arg = alloc_sanitize_path(arg, curr_dir);
add_exclude_file(&exclude_list, arg,
XFLG_FATAL_ERRORS);
break;
case OPT_INCLUDE_FROM:
add_exclude_file(&exclude_list, poptGetOptArg(pc),
MISSING_FATAL, ADD_INCLUDE);
arg = poptGetOptArg(pc);
if (sanitize_paths)
arg = alloc_sanitize_path(arg, curr_dir);
add_exclude_file(&exclude_list, arg,
XFLG_FATAL_ERRORS | XFLG_DEF_INCLUDE);
break;
case 'h':
usage(FINFO);
exit_cleanup(0);
case 'H':
#if SUPPORT_HARD_LINKS
preserve_hard_links=1;
#else
/* FIXME: Don't say "server" if this is
* happening on the client. */
/* FIXME: Why do we have the duplicated
* rprintf? Everybody who gets this message
* ought to send it to the client and also to
* the logs. */
snprintf(err_buf, sizeof err_buf,
"hard links are not supported on this %s\n",
am_server ? "server" : "client");
rprintf(FERROR, "ERROR: %s", err_buf);
return 0;
#endif /* SUPPORT_HARD_LINKS */
break;
case 'v':
verbose++;
break;
case 'q':
if (frommain) quiet++;
if (frommain)
quiet++;
break;
case OPT_SENDER:
@@ -564,16 +563,17 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
case OPT_WRITE_BATCH:
/* popt stores the filename in batch_prefix for us */
write_batch = 1;
checksum_seed = FIXED_CHECKSUM_SEED;
break;
case OPT_READ_BATCH:
/* popt stores the filename in batch_prefix for us */
read_batch = 1;
checksum_seed = FIXED_CHECKSUM_SEED;
break;
case OPT_LINK_DEST:
#if HAVE_LINK
compare_dest = (char *)poptGetOptArg(pc);
link_dest = 1;
break;
#else
@@ -584,24 +584,66 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
return 0;
#endif
default:
/* FIXME: If --daemon is specified, then errors for later
* parameters seem to disappear. */
snprintf(err_buf, sizeof(err_buf),
"%s%s: %s\n",
am_server ? "on remote machine: " : "",
poptBadOption(pc, POPT_BADOPTION_NOALIAS),
poptStrerror(opt));
/* A large opt value means that set_refuse_options()
* turned this option off (opt-BASE is its index). */
if (opt >= OPT_REFUSED_BASE) {
struct poptOption *op =
&long_options[opt-OPT_REFUSED_BASE];
int n = snprintf(err_buf, sizeof err_buf,
"This server does not support --%s\n",
op->longName) - 1;
if (op->shortName) {
snprintf(err_buf+n, sizeof err_buf-n,
" (-%c)\n", op->shortName);
}
} else {
snprintf(err_buf, sizeof err_buf,
"%s%s: %s\n",
am_server ? "on remote machine: " : "",
poptBadOption(pc, POPT_BADOPTION_NOALIAS),
poptStrerror(opt));
}
return 0;
}
}
#if !SUPPORT_LINKS
if (preserve_links && !am_sender) {
snprintf(err_buf, sizeof err_buf,
"symlinks are not supported on this %s\n",
am_server ? "server" : "client");
rprintf(FERROR, "ERROR: %s", err_buf);
return 0;
}
#endif
#if !SUPPORT_HARD_LINKS
if (preserve_hard_links) {
snprintf(err_buf, sizeof err_buf,
"hard links are not supported on this %s\n",
am_server ? "server" : "client");
rprintf(FERROR, "ERROR: %s", err_buf);
return 0;
}
#endif
if (write_batch && read_batch) {
rprintf(FERROR,
"write-batch and read-batch can not be used together\n");
exit_cleanup(RERR_SYNTAX);
}
if (batch_prefix && strlen(batch_prefix) > MAX_BATCH_PREFIX_LEN) {
rprintf(FERROR,
"the batch-file prefix must be %d characters or less.\n",
MAX_BATCH_PREFIX_LEN);
exit_cleanup(RERR_SYNTAX);
}
if (tmpdir && strlen(tmpdir) >= MAXPATHLEN - 10) {
rprintf(FERROR, "the --temp-dir path is WAY too long.\n");
exit_cleanup(RERR_SYNTAX);
}
if (do_compression && (write_batch || read_batch)) {
rprintf(FERROR,
@@ -625,17 +667,54 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
if (relative_paths < 0)
relative_paths = files_from? 1 : 0;
*argv = poptGetArgs(pc);
if (*argv)
*argc = count_args(*argv);
else
*argc = 0;
if (sanitize_paths) {
int i;
for (i = *argc; i-- > 0; )
(*argv)[i] = alloc_sanitize_path((*argv)[i], NULL);
if (tmpdir)
tmpdir = alloc_sanitize_path(tmpdir, curr_dir);
if (compare_dest)
compare_dest = alloc_sanitize_path(compare_dest, curr_dir);
if (backup_dir)
backup_dir = alloc_sanitize_path(backup_dir, curr_dir);
if (files_from)
files_from = alloc_sanitize_path(files_from, curr_dir);
}
if (daemon_opt) {
daemon_opt = 0;
am_daemon = 1;
return 1;
}
if (!backup_suffix)
backup_suffix = backup_dir? "" : BACKUP_SUFFIX;
backup_suffix = backup_dir ? "" : BACKUP_SUFFIX;
backup_suffix_len = strlen(backup_suffix);
if (strchr(backup_suffix, '/') != NULL) {
rprintf(FERROR, "--suffix cannot contain slashes: %s\n",
backup_suffix);
exit_cleanup(RERR_SYNTAX);
}
if (backup_dir)
backup_dir_len = strlen(backup_dir);
else if (!backup_suffix_len) {
if (backup_dir) {
backup_dir_len = strlcpy(backup_dir_buf, backup_dir, sizeof backup_dir_buf);
backup_dir_remainder = sizeof backup_dir_buf - backup_dir_len;
if (backup_dir_remainder < 32) {
rprintf(FERROR, "the --backup-dir path is WAY too long.\n");
exit_cleanup(RERR_SYNTAX);
}
if (backup_dir_buf[backup_dir_len - 1] != '/') {
backup_dir_buf[backup_dir_len++] = '/';
backup_dir_buf[backup_dir_len] = '\0';
}
if (verbose > 1 && !am_sender)
rprintf(FINFO, "backup_dir is %s\n", backup_dir_buf);
} else if (!backup_suffix_len && (!am_server || !am_sender)) {
rprintf(FERROR,
"--suffix cannot be a null string without --backup-dir\n");
exit_cleanup(RERR_SYNTAX);
@@ -644,15 +723,9 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
if (do_progress && !verbose)
verbose = 1;
*argv = poptGetArgs(pc);
if (*argv)
*argc = count_args(*argv);
else
*argc = 0;
if (files_from) {
char *colon;
if (*argc != 2) {
if (*argc != 2 && !(am_server && am_sender && *argc == 1)) {
usage(FERROR);
exit_cleanup(RERR_SYNTAX);
}
@@ -672,9 +745,6 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
exit_cleanup(RERR_SYNTAX);
}
} else {
extern int sanitize_paths;
if (sanitize_paths)
sanitize_path(strdup(files_from), NULL);
filesfrom_fd = open(files_from, O_RDONLY|O_BINARY);
if (filesfrom_fd < 0) {
rsyserr(FERROR, errno,
@@ -701,13 +771,7 @@ void server_options(char **args,int *argc)
{
int ac = *argc;
static char argstr[50];
static char bsize[30];
static char iotime[30];
static char mdelete[30];
static char mwindow[30];
static char bw[50];
/* Leave room for ``--(write|read)-batch='' */
static char fext[MAXPATHLEN + 15];
char *arg;
int i, x;
@@ -728,7 +792,7 @@ void server_options(char **args,int *argc)
x = 1;
argstr[0] = '-';
for (i=0;i<verbose;i++)
for (i = 0; i < verbose; i++)
argstr[x++] = 'v';
/* the -q option is intentionally left out */
@@ -787,37 +851,38 @@ void server_options(char **args,int *argc)
argstr[x] = 0;
if (x != 1) args[ac++] = argstr;
if (x != 1)
args[ac++] = argstr;
if (block_size) {
snprintf(bsize,sizeof(bsize),"-B%d",block_size);
args[ac++] = bsize;
if (asprintf(&arg, "-B%u", block_size) < 0)
goto oom;
args[ac++] = arg;
}
if (max_delete && am_sender) {
snprintf(mdelete,sizeof(mdelete),"--max-delete=%d",max_delete);
args[ac++] = mdelete;
if (asprintf(&arg, "--max-delete=%d", max_delete) < 0)
goto oom;
args[ac++] = arg;
}
if (batch_prefix != NULL) {
char *fmt = "";
if (write_batch)
fmt = "--write-batch=%s";
else
if (read_batch)
fmt = "--read-batch=%s";
snprintf(fext,sizeof(fext),fmt,batch_prefix);
args[ac++] = fext;
if (batch_prefix) {
char *r_or_w = write_batch ? "write" : "read";
if (asprintf(&arg, "--%s-batch=%s", r_or_w, batch_prefix) < 0)
goto oom;
args[ac++] = arg;
}
if (io_timeout) {
snprintf(iotime,sizeof(iotime),"--timeout=%d",io_timeout);
args[ac++] = iotime;
if (asprintf(&arg, "--timeout=%d", io_timeout) < 0)
goto oom;
args[ac++] = arg;
}
if (bwlimit) {
snprintf(bw,sizeof(bw),"--bwlimit=%d",bwlimit);
args[ac++] = bw;
if (asprintf(&arg, "--bwlimit=%d", bwlimit) < 0)
goto oom;
args[ac++] = arg;
}
if (backup_dir) {
@@ -826,28 +891,25 @@ void server_options(char **args,int *argc)
}
/* Only send --suffix if it specifies a non-default value. */
if (strcmp(backup_suffix, backup_dir? "" : BACKUP_SUFFIX) != 0) {
char *s = new_array(char, 9+backup_suffix_len+1);
if (!s)
out_of_memory("server_options");
if (strcmp(backup_suffix, backup_dir ? "" : BACKUP_SUFFIX) != 0) {
/* We use the following syntax to avoid weirdness with '~'. */
sprintf(s, "--suffix=%s", backup_suffix);
args[ac++] = s;
if (asprintf(&arg, "--suffix=%s", backup_suffix) < 0)
goto oom;
args[ac++] = arg;
}
if (delete_mode && !delete_excluded)
args[ac++] = "--delete";
if (delete_excluded)
args[ac++] = "--delete-excluded";
else if (delete_mode)
args[ac++] = "--delete";
if (size_only)
args[ac++] = "--size-only";
if (modify_window_set) {
snprintf(mwindow,sizeof(mwindow),"--modify-window=%d",
modify_window);
args[ac++] = mwindow;
if (asprintf(&arg, "--modify-window=%d", modify_window) < 0)
goto oom;
args[ac++] = arg;
}
if (keep_partial)
@@ -904,6 +966,10 @@ void server_options(char **args,int *argc)
}
*argc = ac;
return;
oom:
out_of_memory("server_options");
}
/**
@@ -915,12 +981,14 @@ char *find_colon(char *s)
char *p, *p2;
p = strchr(s,':');
if (!p) return NULL;
if (!p)
return NULL;
/* now check to see if there is a / in the string before the : - if there is then
discard the colon on the assumption that the : is part of a filename */
p2 = strchr(s,'/');
if (p2 && p2 < p) return NULL;
if (p2 && p2 < p)
return NULL;
return p;
}

View File

@@ -1,6 +1,6 @@
Summary: Program for efficient remote updates of files.
Name: rsync
Version: 2.6.0
Version: 2.6.2
Release: 1
Copyright: GPL
Group: Applications/Networking

13
pipe.c
View File

@@ -21,6 +21,13 @@
#include "rsync.h"
extern int am_sender;
extern int am_server;
extern int blocking_io;
extern int orig_umask;
extern int read_batch;
extern int filesfrom_fd;
/**
* Create a child connected to use on stdin/stdout.
*
@@ -39,7 +46,6 @@ 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;
if (verbose >= 2) {
print_child_argv(command);
@@ -58,7 +64,6 @@ pid_t piped_child(char **command, int *f_in, int *f_out)
}
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 ||
@@ -98,10 +103,6 @@ pid_t local_child(int argc, char **argv,int *f_in,int *f_out,
pid_t pid;
int to_child_pipe[2];
int from_child_pipe[2];
extern int read_batch;
extern int am_sender;
extern int am_server;
extern int filesfrom_fd;
if (fd_pair(to_child_pipe) < 0 ||
fd_pair(from_child_pipe) < 0) {

View File

@@ -5,5 +5,3 @@ config.h
config.log
config.status
dummy
rsync
zlib/dummy

View File

@@ -907,10 +907,10 @@ int poptGetNextOpt(poptContext con)
#ifndef DBL_EPSILON
#define DBL_EPSILON 2.2204460492503131e-16
#endif
#define _ABS(a) ((((a) - 0.0) < DBL_EPSILON) ? -(a) : (a))
if ((_ABS(aDouble) - FLT_MAX) > DBL_EPSILON)
#define MY_ABS(a) ((((a) - 0.0) < DBL_EPSILON) ? -(a) : (a))
if ((MY_ABS(aDouble) - FLT_MAX) > DBL_EPSILON)
return POPT_ERROR_OVERFLOW;
if ((FLT_MIN - _ABS(aDouble)) > DBL_EPSILON)
if ((FLT_MIN - MY_ABS(aDouble)) > DBL_EPSILON)
return POPT_ERROR_OVERFLOW;
*((float *) opt->arg) = aDouble;
}
@@ -1055,7 +1055,7 @@ poptContext poptFreeContext(poptContext con)
}
int poptAddAlias(poptContext con, struct poptAlias alias,
/*@unused@*/ int flags)
/*@unused@*/ UNUSED(int flags))
{
poptItem item = (poptItem) alloca(sizeof(*item));
memset(item, 0, sizeof(*item));

View File

@@ -363,7 +363,7 @@ int poptDupArgv(int argc, /*@null@*/ const char **argv,
* @retval argcPtr address of returned no. of arguments
* @retval argvPtr address of returned argument array
*/
int poptParseArgvString(const char * s,
int poptParseArgvString(const unsigned char * s,
/*@out@*/ int * argcPtr, /*@out@*/ const char *** argvPtr)
/*@modifies *argcPtr, *argvPtr @*/;

View File

@@ -10,7 +10,7 @@
#include "poptint.h"
/*@-compmempass@*/ /* FIX: item->option.longName kept, not dependent. */
static void configLine(poptContext con, char * line)
static void configLine(poptContext con, unsigned char * line)
/*@modifies con @*/
{
/*@-type@*/
@@ -92,9 +92,9 @@ static void configLine(poptContext con, char * line)
int poptReadConfigFile(poptContext con, const char * fn)
{
const char * file, * chptr, * end;
char * buf;
/*@dependent@*/ char * dst;
const unsigned char * file, * chptr, * end;
unsigned char * buf;
/*@dependent@*/ unsigned char * dst;
int fd, rc;
off_t fileLength;
@@ -159,7 +159,8 @@ int poptReadConfigFile(poptContext con, const char * fn)
return 0;
}
int poptReadDefaultConfig(poptContext con, /*@unused@*/ int useEnv) {
int poptReadDefaultConfig(poptContext con, /*@unused@*/ UNUSED(int useEnv))
{
char * fn, * home;
int rc;

View File

@@ -17,9 +17,9 @@
* @param key option(s)
*/
static void displayArgs(poptContext con,
/*@unused@*/ enum poptCallbackReason foo,
/*@unused@*/ UNUSED(enum poptCallbackReason foo),
struct poptOption * key,
/*@unused@*/ const char * arg, /*@unused@*/ void * data)
/*@unused@*/ UNUSED(const char * arg), /*@unused@*/ UNUSED(void * data))
/*@globals fileSystem@*/
/*@modifies fileSystem@*/
{
@@ -84,7 +84,7 @@ getTableTranslationDomain(/*@null@*/ const struct poptOption *table)
/*@observer@*/ /*@null@*/ static const char *const
getArgDescrip(const struct poptOption * opt,
/*@-paramuse@*/ /* FIX: wazzup? */
/*@null@*/ const char * translation_domain)
/*@null@*/ UNUSED(const char * translation_domain))
/*@=paramuse@*/
/*@*/
{
@@ -115,7 +115,7 @@ static /*@only@*/ /*@null@*/ char *
singleOptionDefaultValue(int lineLength,
const struct poptOption * opt,
/*@-paramuse@*/ /* FIX: i18n macros disable with lclint */
/*@null@*/ const char * translation_domain)
/*@null@*/ UNUSED(const char * translation_domain))
/*@=paramuse@*/
/*@*/
{
@@ -191,11 +191,11 @@ static void singleOptionHelp(FILE * fp, int maxLeftCol,
{
int indentLength = maxLeftCol + 5;
int lineLength = 79 - indentLength;
const char * help = D_(translation_domain, opt->descrip);
const unsigned char * help = D_(translation_domain, opt->descrip);
const char * argDescrip = getArgDescrip(opt, translation_domain);
int helpLength;
char * defs = NULL;
char * left;
unsigned char * defs = NULL;
unsigned char * left;
int nb = maxLeftCol + 1;
/* Make sure there's more than enough room in target buffer. */
@@ -314,7 +314,7 @@ static void singleOptionHelp(FILE * fp, int maxLeftCol,
helpLength = strlen(help);
while (helpLength > lineLength) {
const char * ch;
const unsigned char * ch;
char format[10];
ch = help + lineLength - 1;
@@ -475,7 +475,7 @@ static int showHelpIntro(poptContext con, FILE * fp)
return len;
}
void poptPrintHelp(poptContext con, FILE * fp, /*@unused@*/ int flags)
void poptPrintHelp(poptContext con, FILE * fp, /*@unused@*/ UNUSED(int flags))
{
int leftColWidth;
@@ -634,7 +634,7 @@ static int showShortOptions(const struct poptOption * opt, FILE * fp,
return strlen(s) + 4;
}
void poptPrintUsage(poptContext con, FILE * fp, /*@unused@*/ int flags)
void poptPrintUsage(poptContext con, FILE * fp, /*@unused@*/ UNUSED(int flags))
{
int cursor;

View File

@@ -51,10 +51,10 @@ int poptDupArgv(int argc, const char **argv,
return 0;
}
int poptParseArgvString(const char * s, int * argcPtr, const char *** argvPtr)
int poptParseArgvString(const unsigned char * s, int * argcPtr, const char *** argvPtr)
{
const char * src;
char quote = '\0';
const unsigned char * src;
unsigned char quote = '\0';
int argvAlloced = POPT_ARGV_ARRAY_GROW_DELTA;
const char ** argv = malloc(sizeof(*argv) * argvAlloced);
int argc = 0;

View File

@@ -19,6 +19,14 @@
#include <unistd.h>
#endif
#if !defined(__GNUC__) || defined(APPLE)
/* Apparently the OS X port of gcc gags on __attribute__.
*
* <http://www.opensource.apple.com/bugs/X/gcc/2512150.html> */
#define __attribute__(x)
#endif
#ifdef __NeXT
/* access macros are not declared in non posix mode in unistd.h -
don't try to use posix on NeXTstep 3.3 ! */
@@ -69,5 +77,6 @@ char *alloca ();
#define xstrdup(_str) strdup(_str)
#endif /* HAVE_MCHECK_H && defined(__GNUC__) */
#define UNUSED(x) x __attribute__((__unused__))
#include "popt.h"

View File

@@ -21,14 +21,23 @@
#include "rsync.h"
static OFF_T last_ofs;
static struct timeval print_time;
static struct timeval start_time;
static OFF_T start_ofs;
extern struct stats stats;
extern int am_server;
#define PROGRESS_HISTORY_SECS 5
struct progress_history {
struct timeval time;
OFF_T ofs;
};
static struct progress_history ph_start;
static struct progress_history ph_list[PROGRESS_HISTORY_SECS];
static int newest_hpos, oldest_hpos;
static unsigned long msdiff(struct timeval *t1, struct timeval *t2)
{
return (t2->tv_sec - t1->tv_sec) * 1000
return (t2->tv_sec - t1->tv_sec) * 1000L
+ (t2->tv_usec - t1->tv_usec) / 1000;
}
@@ -43,19 +52,29 @@ static unsigned long msdiff(struct timeval *t1, struct timeval *t2)
static void rprint_progress(OFF_T ofs, OFF_T size, struct timeval *now,
int is_last)
{
int pct = (ofs == size) ? 100 : (int)((100.0*ofs)/size);
unsigned long diff = msdiff(&start_time, now);
double rate = diff ? (double) (ofs-start_ofs) * 1000.0 / diff / 1024.0 : 0;
char eol[256];
const char *units;
/* If we've finished transferring this file, show the time taken;
* otherwise show expected time to complete. That's kind of
* inconsistent, but people can probably cope. Hopefully we'll
* get more consistent and complete progress reporting soon. --
* mbp */
double remain = is_last ? (double) diff / 1000.0
: rate ? (double) (size-ofs) / rate / 1000.0 : 0.0;
int pct = ofs == size ? 100 : (int) (100.0 * ofs / size);
unsigned long diff;
double rate, remain;
int remain_h, remain_m, remain_s;
if (is_last) {
/* Compute stats based on the starting info. */
diff = msdiff(&ph_start.time, now);
if (!diff)
diff = 1;
rate = (double) (ofs - ph_start.ofs) * 1000.0 / diff / 1024.0;
/* Switch to total time taken for our last update. */
remain = (double) diff / 1000.0;
} else {
/* Compute stats based on recent progress. */
diff = msdiff(&ph_list[oldest_hpos].time, now);
rate = diff ? (double) (ofs - ph_list[oldest_hpos].ofs) * 1000.0
/ diff / 1024.0 : 0;
remain = rate ? (double) (size - ofs) / rate / 1000.0 : 0.0;
}
if (rate > 1024*1024) {
rate /= 1024.0 * 1024.0;
units = "GB/s";
@@ -70,50 +89,66 @@ static void rprint_progress(OFF_T ofs, OFF_T size, struct timeval *now,
remain_m = (int) (remain / 60.0) % 60;
remain_h = (int) (remain / 3600.0);
if (is_last) {
snprintf(eol, sizeof eol, " (%d, %.1f%% of %d)\n",
stats.num_transferred_files,
(float)((stats.current_file_index+1) * 100)
/ stats.num_files,
stats.num_files);
} else
strcpy(eol, "\r");
rprintf(FINFO, "%12.0f %3d%% %7.2f%s %4d:%02d:%02d%s",
(double) ofs, pct, rate, units,
remain_h, remain_m, remain_s,
is_last ? "\n" : "\r");
remain_h, remain_m, remain_s, eol);
}
void end_progress(OFF_T size)
{
extern int am_server;
if (!am_server) {
struct timeval now;
gettimeofday(&now, NULL);
rprint_progress(size, size, &now, True);
}
last_ofs = 0;
start_ofs = 0;
print_time.tv_sec = print_time.tv_usec = 0;
start_time.tv_sec = start_time.tv_usec = 0;
memset(&ph_start, 0, sizeof ph_start);
}
void show_progress(OFF_T ofs, OFF_T size)
{
extern int am_server;
struct timeval now;
if (!start_time.tv_sec) {
gettimeofday(&now, NULL);
start_time.tv_sec = now.tv_sec;
start_time.tv_usec = now.tv_usec;
start_ofs = ofs;
if (am_server)
return;
if (am_server)
return;
gettimeofday(&now, NULL);
if (!ph_start.time.tv_sec) {
int i;
/* Try to guess the real starting time when the sender started
* to send us data by using the time we last received some data
* in the last file (if it was recent enough). */
if (msdiff(&ph_list[newest_hpos].time, &now) <= 1500) {
ph_start.time = ph_list[newest_hpos].time;
ph_start.ofs = 0;
} else {
ph_start.time.tv_sec = now.tv_sec;
ph_start.time.tv_usec = now.tv_usec;
ph_start.ofs = ofs;
}
for (i = 0; i < PROGRESS_HISTORY_SECS; i++)
ph_list[i] = ph_start;
}
else {
if (am_server)
if (msdiff(&ph_list[newest_hpos].time, &now) < 1000)
return;
gettimeofday(&now, NULL);
newest_hpos = oldest_hpos;
oldest_hpos = (oldest_hpos + 1) % PROGRESS_HISTORY_SECS;
ph_list[newest_hpos].time.tv_sec = now.tv_sec;
ph_list[newest_hpos].time.tv_usec = now.tv_usec;
ph_list[newest_hpos].ofs = ofs;
}
if (ofs > last_ofs + 1000 && msdiff(&print_time, &now) > 250) {
rprint_progress(ofs, size, &now, False);
last_ofs = ofs;
print_time.tv_sec = now.tv_sec;
print_time.tv_usec = now.tv_usec;
}
rprint_progress(ofs, size, &now, False);
}

View File

@@ -23,13 +23,15 @@
extern int verbose;
extern int recurse;
extern int delete_mode;
extern int protocol_version;
extern int delete_after;
extern int max_delete;
extern int csum_length;
extern struct stats stats;
extern int dry_run;
extern int am_server;
extern int relative_paths;
extern int preserve_hard_links;
extern int preserve_perms;
extern int cvs_exclude;
extern int io_error;
extern char *tmpdir;
@@ -39,49 +41,10 @@ extern int do_progress;
extern char *backup_dir;
extern char *backup_suffix;
extern int backup_suffix_len;
static struct delete_list {
DEV64_T dev;
INO64_T inode;
} *delete_list;
static int dlist_len, dlist_alloc_len;
/* yuck! This function wouldn't have been necessary if I had the sorting
* algorithm right. Unfortunately fixing the sorting algorithm would introduce
* a backward incompatibility as file list indexes are sent over the link.
*/
static int delete_already_done(struct file_list *flist,int j)
{
int i;
STRUCT_STAT st;
if (link_stat(f_name(flist->files[j]), &st)) return 1;
for (i = 0; i < dlist_len; i++) {
if (st.st_ino == delete_list[i].inode &&
(DEV64_T)st.st_dev == delete_list[i].dev)
return 1;
}
return 0;
}
static void add_delete_entry(struct file_struct *file)
{
if (dlist_len == dlist_alloc_len) {
dlist_alloc_len += 1024;
delete_list = realloc_array(delete_list, struct delete_list,
dlist_alloc_len);
if (!delete_list) out_of_memory("add_delete_entry");
}
delete_list[dlist_len].dev = file->dev;
delete_list[dlist_len].inode = file->inode;
dlist_len++;
if (verbose > 3)
rprintf(FINFO,"added %s to delete list\n", f_name(file));
}
extern int cleanup_got_literal;
extern int module_id;
extern int ignore_errors;
extern int orig_umask;
static void delete_one(char *fn, int is_dir)
{
@@ -112,17 +75,13 @@ static int is_backup_file(char *fn)
}
/* this deletes any files on the receiving side that are not present
* on the sending side. For version 1.6.4 I have changed the behaviour
* to match more closely what most people seem to expect of this option */
/* This deletes any files on the receiving side that are not present
* on the sending side. */
void delete_files(struct file_list *flist)
{
struct file_list *local_file_list;
int i, j;
char *name;
extern int module_id;
extern int ignore_errors;
extern int max_delete;
char *argv[1], fbuf[MAXPATHLEN];
static int deletion_count;
if (cvs_exclude)
@@ -133,30 +92,25 @@ void delete_files(struct file_list *flist)
return;
}
for (j=0;j<flist->count;j++) {
if (!S_ISDIR(flist->files[j]->mode) ||
!(flist->files[j]->flags & FLAG_DELETE)) continue;
if (protocol_version < 19 &&
delete_already_done(flist, j)) continue;
name = strdup(f_name(flist->files[j]));
if (!(local_file_list = send_file_list(-1,1,&name))) {
free(name);
for (j = 0; j < flist->count; j++) {
if (!(flist->files[j]->flags & FLAG_TOP_DIR)
|| !S_ISDIR(flist->files[j]->mode))
continue;
argv[0] = f_name_to(flist->files[j], fbuf);
if (!(local_file_list = send_file_list(-1, 1, argv)))
continue;
}
if (verbose > 1)
rprintf(FINFO,"deleting in %s\n", name);
rprintf(FINFO, "deleting in %s\n", fbuf);
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 &&
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])) {
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 (flist_find(flist,local_file_list->files[i]) < 0) {
char *f = f_name(local_file_list->files[i]);
if (make_backups && (backup_dir || !is_backup_file(f))) {
(void) make_backup(f);
@@ -170,7 +124,6 @@ void delete_files(struct file_list *flist)
}
}
flist_free(local_file_list);
free(name);
}
}
@@ -203,8 +156,8 @@ static int get_tmpname(char *fnametmp, char *fname)
int maxname;
if (tmpdir) {
strlcpy(fnametmp, tmpdir, MAXPATHLEN - 2);
length = strlen(fnametmp);
/* Note: this can't overflow, so the return value is safe */
length = strlcpy(fnametmp, tmpdir, MAXPATHLEN - 2);
fnametmp[length++] = '/';
fnametmp[length] = '\0'; /* always NULL terminated */
}
@@ -216,9 +169,8 @@ static int get_tmpname(char *fnametmp, char *fname)
/* copy up to and including the slash */
strlcpy(fnametmp, fname, length + 1);
}
} else {
} else
f = fname;
}
fnametmp[length++] = '.';
fnametmp[length] = '\0'; /* always NULL terminated */
@@ -237,7 +189,7 @@ static int get_tmpname(char *fnametmp, char *fname)
}
static int receive_data(int f_in,struct map_struct *buf,int fd,char *fname,
static int receive_data(int f_in,struct map_struct *mapbuf,int fd,char *fname,
OFF_T total_size)
{
int i;
@@ -254,13 +206,11 @@ static int receive_data(int f_in,struct map_struct *buf,int fd,char *fname,
sum_init();
for (i=recv_token(f_in,&data); i != 0; i=recv_token(f_in,&data)) {
while ((i = recv_token(f_in, &data)) != 0) {
if (do_progress)
show_progress(offset, total_size);
if (i > 0) {
extern int cleanup_got_literal;
if (verbose > 3) {
rprintf(FINFO,"data recv %d at %.0f\n",
i,(double)offset);
@@ -292,8 +242,8 @@ static int receive_data(int f_in,struct map_struct *buf,int fd,char *fname,
rprintf(FINFO,"chunk[%d] of size %d at %.0f offset=%.0f\n",
i,len,(double)offset2,(double)offset);
if (buf) {
map = map_ptr(buf,offset2,len);
if (mapbuf) {
map = map_ptr(mapbuf,offset2,len);
see_token(map, len);
sum_update(map,len);
@@ -307,6 +257,8 @@ static int receive_data(int f_in,struct map_struct *buf,int fd,char *fname,
offset += len;
}
flush_write_file(fd);
if (do_progress)
end_progress(total_size);
@@ -333,41 +285,42 @@ static int receive_data(int f_in,struct map_struct *buf,int fd,char *fname,
* main routine for receiver process.
*
* Receiver process runs on the same host as the generator process. */
int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
int recv_files(int f_in,struct file_list *flist,char *local_name)
{
int fd1,fd2;
STRUCT_STAT st;
char *fname;
char *fname, fbuf[MAXPATHLEN];
char template[MAXPATHLEN];
char fnametmp[MAXPATHLEN];
char *fnamecmp;
char fnamecmpbuf[MAXPATHLEN];
struct map_struct *buf;
struct map_struct *mapbuf;
int i;
struct file_struct *file;
int phase=0;
int recv_ok;
extern struct stats stats;
extern int preserve_perms;
extern int delete_after;
extern int orig_umask;
struct stats initial_stats;
if (verbose > 2) {
rprintf(FINFO,"recv_files(%d) starting\n",flist->count);
}
if (flist->hlink_pool) {
pool_destroy(flist->hlink_pool);
flist->hlink_pool = NULL;
}
while (1) {
cleanup_disable();
i = read_int(f_in);
if (i == -1) {
if (phase==0) {
if (phase == 0) {
phase++;
csum_length = SUM_LENGTH;
if (verbose > 2)
rprintf(FINFO,"recv_files phase=%d\n",phase);
write_int(f_gen,-1);
send_msg(MSG_DONE, "", 0);
continue;
}
break;
@@ -380,13 +333,16 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
}
file = flist->files[i];
fname = f_name(file);
stats.current_file_index = i;
stats.num_transferred_files++;
stats.total_transferred_size += file->length;
cleanup_got_literal = 0;
if (local_name)
fname = local_name;
else
fname = f_name_to(file, fbuf);
if (dry_run) {
if (!am_server && verbose) { /* log transfer */
@@ -405,10 +361,10 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
/* open the file */
fd1 = do_open(fnamecmp, O_RDONLY, 0);
if ((fd1 == -1) && (compare_dest != NULL)) {
if (fd1 == -1 && compare_dest != NULL) {
/* try the file at compare_dest instead */
snprintf(fnamecmpbuf,MAXPATHLEN,"%s/%s",
compare_dest,fname);
pathjoin(fnamecmpbuf, sizeof fnamecmpbuf,
compare_dest, fname);
fnamecmp = fnamecmpbuf;
fd1 = do_open(fnamecmp, O_RDONLY, 0);
}
@@ -437,7 +393,7 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
if (fd1 != -1 && !S_ISREG(st.st_mode)) {
close(fd1);
fd1 = -1;
buf = NULL;
mapbuf = NULL;
}
if (fd1 != -1 && !preserve_perms) {
@@ -448,20 +404,19 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
}
if (fd1 != -1 && st.st_size > 0) {
buf = map_file(fd1,st.st_size);
mapbuf = map_file(fd1,st.st_size);
if (verbose > 2)
rprintf(FINFO,"recv mapped %s of size %.0f\n",fnamecmp,(double)st.st_size);
} else {
buf = NULL;
}
} else
mapbuf = NULL;
if (!get_tmpname(fnametmp,fname)) {
if (buf) unmap_file(buf);
if (mapbuf) unmap_file(mapbuf);
if (fd1 != -1) close(fd1);
continue;
}
strlcpy(template, fnametmp, sizeof(template));
strlcpy(template, fnametmp, sizeof template);
/* we initially set the perms without the
* setuid/setgid bits to ensure that there is no race
@@ -476,34 +431,38 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
* transferred, but that may not be the case with -R */
if (fd2 == -1 && relative_paths && errno == ENOENT &&
create_directory_path(fnametmp, orig_umask) == 0) {
strlcpy(fnametmp, template, sizeof(fnametmp));
strlcpy(fnametmp, template, sizeof fnametmp);
fd2 = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS);
}
if (fd2 == -1) {
rprintf(FERROR, "mkstemp %s failed: %s\n",
full_fname(fnametmp), strerror(errno));
receive_data(f_in,buf,-1,NULL,file->length);
if (buf) unmap_file(buf);
receive_data(f_in,mapbuf,-1,NULL,file->length);
if (mapbuf) unmap_file(mapbuf);
if (fd1 != -1) close(fd1);
continue;
}
cleanup_set(fnametmp, fname, file, buf, fd1, fd2);
cleanup_set(fnametmp, fname, file, mapbuf, fd1, fd2);
if (!am_server && verbose) { /* log transfer */
rprintf(FINFO, "%s\n", fname);
}
/* recv file data */
recv_ok = receive_data(f_in,buf,fd2,fname,file->length);
recv_ok = receive_data(f_in,mapbuf,fd2,fname,file->length);
log_recv(file, &initial_stats);
if (buf) unmap_file(buf);
if (mapbuf) unmap_file(mapbuf);
if (fd1 != -1) {
close(fd1);
}
close(fd2);
if (close(fd2) < 0) {
rprintf(FERROR, "close failed on %s: %s\n",
full_fname(fnametmp), strerror(errno));
exit_cleanup(RERR_FILEIO);
}
if (verbose > 2)
rprintf(FINFO,"renaming %s to %s\n",fnametmp,fname);
@@ -517,33 +476,21 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
rprintf(FERROR,"ERROR: file corruption in %s. File changed during transfer?\n",
full_fname(fname));
} else {
char buf[4];
if (verbose > 1)
rprintf(FINFO,"redoing %s(%d)\n",fname,i);
write_int(f_gen,i);
SIVAL(buf, 0, i);
send_msg(MSG_REDO, buf, 4);
}
}
}
if (delete_after) {
if (recurse && delete_mode && !local_name && flist->count>0) {
delete_files(flist);
}
}
if (preserve_hard_links)
do_hard_links();
/* now we need to fix any directory permissions that were
* modified during the transfer */
for (i = 0; i < flist->count; i++) {
file = flist->files[i];
if (!file->basename || !S_ISDIR(file->mode)) continue;
recv_generator(local_name?local_name:f_name(file),flist,i,-1);
}
if (delete_after && recurse && delete_mode && !local_name
&& flist->count > 0)
delete_files(flist);
if (verbose > 2)
rprintf(FINFO,"recv_files finished\n");
return 0;
}

129
rsync.c
View File

@@ -26,6 +26,9 @@ extern int verbose;
extern int dry_run;
extern int preserve_times;
extern int am_root;
extern int am_server;
extern int am_sender;
extern int am_generator;
extern int preserve_uid;
extern int preserve_gid;
extern int preserve_perms;
@@ -61,28 +64,28 @@ int delete_file(char *fname)
#else
ret = do_stat(fname, &st);
#endif
if (ret) {
if (ret)
return -1;
}
if (!S_ISDIR(st.st_mode)) {
if (robust_unlink(fname) == 0 || errno == ENOENT) return 0;
if (robust_unlink(fname) == 0 || errno == ENOENT)
return 0;
rprintf(FERROR, "delete_file: unlink %s failed: %s\n",
full_fname(fname), strerror(errno));
return -1;
}
if (do_rmdir(fname) == 0 || errno == ENOENT) return 0;
if (!force_delete || !recurse ||
(errno != ENOTEMPTY && errno != EEXIST)) {
if (do_rmdir(fname) == 0 || errno == ENOENT)
return 0;
if (!force_delete || !recurse
|| (errno != ENOTEMPTY && errno != EEXIST)) {
rprintf(FERROR, "delete_file: rmdir %s failed: %s\n",
full_fname(fname), strerror(errno));
return -1;
}
/* now we do a recsursive delete on the directory ... */
d = opendir(fname);
if (!d) {
if (!(d = opendir(fname))) {
rprintf(FERROR, "delete_file: opendir %s failed: %s\n",
full_fname(fname), strerror(errno));
return -1;
@@ -90,12 +93,12 @@ int delete_file(char *fname)
for (errno = 0, di = readdir(d); di; errno = 0, di = readdir(d)) {
char *dname = d_name(di);
if (strcmp(dname,".") == 0
|| strcmp(dname,"..") == 0)
if (dname[0] == '.' && (dname[1] == '\0'
|| (dname[1] == '.' && dname[2] == '\0')))
continue;
snprintf(buf, sizeof(buf), "%s/%s", fname, dname);
pathjoin(buf, sizeof buf, fname, dname);
if (verbose > 0)
rprintf(FINFO,"deleting %s\n", buf);
rprintf(FINFO, "deleting %s\n", buf);
if (delete_file(buf) != 0) {
closedir(d);
return -1;
@@ -119,40 +122,6 @@ int delete_file(char *fname)
return 0;
}
static int is_in_group(gid_t gid)
{
#ifdef GETGROUPS_T
static gid_t last_in = (gid_t) -2, last_out;
static int ngroups = -2;
static GETGROUPS_T *gidset;
int n;
if (gid == last_in)
return last_out;
if (ngroups < -1) {
/* treat failure (-1) as if not member of any group */
ngroups = getgroups(0, 0);
if (ngroups > 0) {
gidset = new_array(GETGROUPS_T, ngroups);
ngroups = getgroups(ngroups, gidset);
}
}
last_in = gid;
last_out = 0;
for (n = 0; n < ngroups; n++) {
if (gidset[n] == gid) {
last_out = 1;
break;
}
}
return last_out;
#else
return 0;
#endif
}
int set_perms(char *fname,struct file_struct *file,STRUCT_STAT *st,
int report)
{
@@ -174,38 +143,45 @@ int set_perms(char *fname,struct file_struct *file,STRUCT_STAT *st,
if (preserve_times && !S_ISLNK(st->st_mode) &&
cmp_modtime(st->st_mtime, file->modtime) != 0) {
/* don't complain about not setting times on directories
because some filesystems can't do it */
* 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));
return 0;
} else {
updated = 1;
}
updated = 1;
}
change_uid = am_root && preserve_uid && st->st_uid != file->uid;
change_gid = preserve_gid && file->gid != (gid_t) -1 && \
st->st_gid != file->gid;
if (change_gid && !am_root) {
/* enforce bsd-style group semantics: non-root can only
change to groups that the user is a member of */
change_gid = is_in_group(file->gid);
}
change_gid = preserve_gid && file->gid != GID_NONE
&& st->st_gid != file->gid;
if (change_uid || change_gid) {
if (verbose > 2) {
if (change_uid) {
rprintf(FINFO,
"set uid of %s from %ld to %ld\n",
fname, (long)st->st_uid, (long)file->uid);
}
if (change_gid) {
rprintf(FINFO,
"set gid of %s from %ld to %ld\n",
fname, (long)st->st_gid, (long)file->gid);
}
}
if (do_lchown(fname,
change_uid?file->uid:st->st_uid,
change_gid?file->gid:st->st_gid) != 0) {
change_uid ? file->uid : st->st_uid,
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));
* unless have the privilege */
rprintf(FERROR, "%s %s failed: %s\n",
change_uid ? "chown" : "chgrp",
full_fname(fname), strerror(errno));
return 0;
}
/* a lchown had been done - we have to re-stat if the
destination had the setuid or setgid bits set due
to the side effect of the chown call */
* destination had the setuid or setgid bits set due
* to the side effect of the chown call */
if (st->st_mode & (S_ISUID | S_ISGID)) {
link_stat(fname, st);
}
@@ -254,27 +230,24 @@ void sig_int(void)
and ownership */
void finish_transfer(char *fname, char *fnametmp, struct file_struct *file)
{
int ret;
if (make_backups && !make_backup(fname))
return;
/* move tmp file over real file */
if (robust_rename(fnametmp,fname) != 0) {
if (errno == EXDEV) {
/* 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));
} else {
set_perms(fname,file,NULL,0);
}
} else {
rprintf(FERROR,"rename %s -> \"%s\": %s\n",
full_fname(fnametmp), fname, strerror(errno));
}
ret = robust_rename(fnametmp, fname, file->mode & INITACCESSPERMS);
if (ret < 0) {
rprintf(FERROR, "%s %s -> \"%s\": %s\n",
ret == -2 ? "copy" : "rename",
full_fname(fnametmp), fname, strerror(errno));
do_unlink(fnametmp);
} else {
set_perms(fname,file,NULL,0);
}
}
const char *who_am_i(void)
{
return am_sender ? "sender" : am_generator ? "generator" : "receiver";
}

192
rsync.h
View File

@@ -27,7 +27,7 @@
#define RSYNC_RSH_IO_ENV "RSYNC_RSH_IO"
#define RSYNC_NAME "rsync"
#define RSYNCD_SYSCONF "/etc/rsyncd.conf"
/* RSYNCD_SYSCONF is now set in config.h */
#define RSYNCD_USERCONF "rsyncd.conf"
#define DEFAULT_LOCK_FILE "/var/run/rsyncd.lock"
@@ -39,19 +39,30 @@
incompatible with older versions :-( */
#define CHAR_OFFSET 0
/* These flags are only used during the flist transfer. */
#define FLAG_DELETE (1<<0)
#define SAME_MODE (1<<1)
#define SAME_RDEV (1<<2)
#define SAME_UID (1<<3)
#define SAME_GID (1<<4)
#define SAME_DIR (1<<5)
#define SAME_NAME SAME_DIR
#define LONG_NAME (1<<6)
#define SAME_TIME (1<<7)
#define XMIT_TOP_DIR (1<<0)
#define XMIT_SAME_MODE (1<<1)
#define XMIT_EXTENDED_FLAGS (1<<2)
#define XMIT_SAME_RDEV_pre28 XMIT_EXTENDED_FLAGS /* Only in protocols < 28 */
#define XMIT_SAME_UID (1<<3)
#define XMIT_SAME_GID (1<<4)
#define XMIT_SAME_NAME (1<<5)
#define XMIT_LONG_NAME (1<<6)
#define XMIT_SAME_TIME (1<<7)
#define XMIT_SAME_RDEV_MAJOR (1<<8)
#define XMIT_HAS_IDEV_DATA (1<<9)
#define XMIT_SAME_DEV (1<<10)
#define XMIT_RDEV_MINOR_IS_SMALL (1<<11)
/* These flags are used in the live flist data. */
#define FLAG_TOP_DIR (1<<0)
#define FLAG_HLINK_EOL (1<<1) /* generator only */
#define FLAG_MOUNT_POINT (1<<2) /* sender only */
/* update this if you make incompatible changes */
#define PROTOCOL_VERSION 27
#define PROTOCOL_VERSION 28
/* 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
@@ -70,8 +81,8 @@
* 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 MIN_PROTOCOL_VERSION 20
#define OLD_PROTOCOL_VERSION 25
#define MAX_PROTOCOL_VERSION 40
#define RSYNC_PORT 873
@@ -93,16 +104,27 @@
#define SERVER_EXCLUDES 1
#define ALL_EXCLUDES 2
#define MISSING_OK 0
#define MISSING_FATAL 1
#define XFLG_FATAL_ERRORS (1<<0)
#define XFLG_DEF_INCLUDE (1<<1)
#define XFLG_WORDS_ONLY (1<<2)
#define XFLG_WORD_SPLIT (1<<3)
#define ADD_INCLUDE 1
#define ADD_EXCLUDE 0
#define FULL_FLUSH 1
#define NORMAL_FLUSH 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. */
enum logcode {FNONE=0, FERROR=1, FINFO=2, FLOG=3 };
/* Log-message categories. FLOG is only used on the daemon side to
* output messages to the log file. */
enum logcode { FERROR=1, FINFO=2, FLOG=3 };
/* Messages types that are sent over the message channel. The logcode
* values must all be present here with identical numbers. */
enum msgcode {
MSG_DATA=0, /* raw data on the multiplexed stream */
MSG_ERROR=FERROR, MSG_INFO=FINFO, MSG_LOG=FLOG, /* remote logging */
MSG_REDO=4, /* reprocess indicated flist index */
MSG_DONE=5, /* current phase is done */
};
#include "errcode.h"
@@ -224,12 +246,19 @@ enum logcode {FNONE=0, FERROR=1, FINFO=2, FLOG=3 };
# endif
#endif
#if MAJOR_IN_MKDEV
#include <sys/mkdev.h>
#elif MAJOR_IN_SYSMACROS
#include <sys/sysmacros.h>
#endif
#ifdef HAVE_COMPAT_H
#include <compat.h>
#endif
#include <assert.h>
#include "lib/pool_alloc.h"
#define BOOL int
@@ -316,17 +345,14 @@ enum logcode {FNONE=0, FERROR=1, FINFO=2, FLOG=3 };
* device numbers will be truncated. But it's a kind of silly thing
* to do anyhow.
*
* FIXME: In future, we should probable split the device number into
* major/minor, and transfer the two parts as 32-bit ints. That gives
* you somewhat more of a chance that they'll come from a big machine
* to a little one in a useful way.
*
* FIXME: Really we need an unsigned type, and we perhaps ought to
* cope with platforms on which this is an unsigned int or even a
* struct. Later.
* FIXME: I don't think the code in flist.c has ever worked on a system
* where dev_t is a struct.
*/
#define INO64_T uint64
#define DEV64_T uint64
struct idev {
uint64 inode;
uint64 dev;
};
#ifndef MIN
#define MIN(a,b) ((a)<(b)?(a):(b))
@@ -362,47 +388,76 @@ enum logcode {FNONE=0, FERROR=1, FINFO=2, FLOG=3 };
#define IN_LOOPBACKNET 127
#endif
#define GID_NONE (gid_t) -1
#define HL_CHECK_MASTER 0
#define HL_SKIP 1
struct hlink {
int hlindex;
struct file_struct *next;
};
#define F_DEV link_u.idev->dev
#define F_INODE link_u.idev->inode
#define F_HLINDEX link_u.links->hlindex
#define F_NEXT link_u.links->next
struct file_struct {
unsigned flags;
time_t modtime;
union {
dev_t rdev; /* The device number, if this is a device */
char *sum; /* Only a normal file can have a checksum */
char *link; /* Points to symlink string, if a symlink */
} u;
OFF_T length;
mode_t mode;
INO64_T inode;
/** Device this file lives upon */
DEV64_T dev;
/** If this is a device node, the device number. */
DEV64_T rdev;
uid_t uid;
gid_t gid;
char *basename;
char *dirname;
char *basedir;
char *link;
char *sum;
union {
struct idev *idev;
struct hlink *links;
} link_u;
time_t modtime;
uid_t uid;
gid_t gid;
mode_t mode;
uchar flags; /* this item MUST remain last */
};
/*
* Start the flist array at FLIST_START entries and grow it
* by doubling until FLIST_LINEAR then grow by FLIST_LINEAR
*/
#define FLIST_START (32 * 1024)
#define FLIST_LINEAR (FLIST_START * 512)
#define ARENA_SIZE (32 * 1024)
/*
* Extent size for allocation pools A minimum size of 128KB
* is needed to mmap them so that freeing will release the
* space to the OS.
*
* Larger sizes reduce leftover fragments and speed free calls
* (when they happen) Smaller sizes increase the chance of
* freed allocations freeing whole extents.
*/
#define FILE_EXTENT (256 * 1024)
#define HLINK_EXTENT (128 * 1024)
struct string_area {
char *base;
char *end;
char *current;
struct string_area *next;
};
#define WITH_HLINK 1
#define WITHOUT_HLINK 0
struct file_list {
int count;
int malloced;
alloc_pool_t file_pool;
alloc_pool_t hlink_pool;
struct file_struct **files;
struct string_area *string_area;
};
struct sum_buf {
OFF_T offset; /**< offset in file of this chunk */
int len; /**< length of chunk of file */
unsigned int len; /**< length of chunk of file */
int i; /**< index of this chunk */
uint32 sum1; /**< simple checksum */
char sum2[SUM_LENGTH]; /**< checksum */
@@ -411,9 +466,9 @@ struct sum_buf {
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 */
unsigned int blength; /**< block_length */
unsigned int remainder; /**< flength % block_length */
int s2length; /**< sum2_length */
struct sum_buf *sums; /**< points to info for each chunk */
};
@@ -436,6 +491,7 @@ struct map_struct {
#define MATCHFLG_WILD2_PREFIX (1<<2) /* pattern starts with '**' */
#define MATCHFLG_ABS_PATH (1<<3) /* path-match on absolute path */
struct exclude_struct {
struct exclude_struct *next;
char *pattern;
int match_flags;
int include;
@@ -443,6 +499,12 @@ struct exclude_struct {
int slash_cnt;
};
struct exclude_list_struct {
struct exclude_struct *head;
struct exclude_struct *tail;
char *debug_type;
};
struct stats {
int64 total_size;
int64 total_transferred_size;
@@ -453,6 +515,7 @@ struct stats {
int flist_size;
int num_files;
int num_transferred_files;
int current_file_index;
};
@@ -535,6 +598,10 @@ extern int errno;
#define STDERR_FILENO 2
#endif
#ifndef S_IRUSR
#define S_IRUSR 0400
#endif
#ifndef S_IWUSR
#define S_IWUSR 0200
#endif
@@ -667,6 +734,17 @@ size_t strlcat(char *d, const char *s, size_t bufsize);
#define exit_cleanup(code) _exit_cleanup(code, __FILE__, __LINE__)
#ifdef HAVE_GETEUID
#define MY_UID() geteuid()
#else
#define MY_UID() getuid()
#endif
#ifdef HAVE_GETEGID
#define MY_GID() getegid()
#else
#define MY_GID() getgid()
#endif
extern int verbose;

323
rsync.yo
View File

@@ -1,5 +1,5 @@
mailto(rsync-bugs@samba.org)
manpage(rsync)(1)(1 Jan 2004)()()
manpage(rsync)(1)(30 Apr 2004)()()
manpagename(rsync)(faster, flexible replacement for rcp)
manpagesynopsis()
@@ -61,11 +61,11 @@ itemize(
it() for copying from a remote rsync server to the local
machine. This is invoked when the source path contains a ::
separator or a rsync:// URL.
separator or an rsync:// URL.
it() for copying from the local machine to a remote rsync
server. This is invoked when the destination path contains a ::
separator or a rsync:// URL.
separator or an rsync:// URL.
it() for copying from a remote machine using a remote shell
program as the transport, using rsync server on the remote
@@ -77,7 +77,7 @@ itemize(
using a remote shell program as the transport, using rsync
server on the remote machine. This is invoked when the
destination path contains a :: separator and the
--rsh=COMMMAND option is also provided.
--rsh=COMMAND option is also provided.
it() for listing files on a remote machine. This is done the
same way as rsync transfers except that you leave off the
@@ -111,7 +111,7 @@ manpagesection(USAGE)
You use rsync in the same way you use rcp. You must specify a source
and a destination, one of which may be remote.
Perhaps the best way to explain the syntax is some examples:
Perhaps the best way to explain the syntax is with some examples:
quote(rsync *.c foo:src/)
@@ -126,7 +126,7 @@ quote(rsync -avz foo:src/bar /data/tmp)
This would recursively transfer all files from the directory src/bar on the
machine foo into the /data/tmp/bar directory on the local machine. The
files are transferred in "archive" mode, which ensures that symbolic
links, devices, attributes, permissions, ownerships etc are preserved
links, devices, attributes, permissions, ownerships, etc. are preserved
in the transfer. Additionally, compression will be used to reduce the
size of data portions of the transfer.
@@ -162,15 +162,15 @@ running on TCP port 873.
You may establish the connection via a web proxy by setting the
environment variable RSYNC_PROXY to a hostname:port pair pointing to
your web proxy. Note that your web proxy's configuration must allow
proxying to port 873.
your web proxy. Note that your web proxy's configuration must support
proxy connections to port 873.
Using rsync in this way is the same as using it with a remote shell except
that:
itemize(
it() you use a double colon :: instead of a single colon to
separate the hostname from the path or a rsync:// URL.
separate the hostname from the path or an rsync:// URL.
it() the remote server may print a message of the day when you
connect.
@@ -217,7 +217,7 @@ used to check against the rsyncd.conf on the remote host.
manpagesection(RUNNING AN RSYNC SERVER)
An rsync server is configured using a config file. Please see the
An rsync server is configured using a configuration file. Please see the
rsyncd.conf(5) man page for more information. By default the configuration
file is called /etc/rsyncd.conf, unless rsync is running over a remote
shell program and is not running as root; in that case, the default name
@@ -290,9 +290,9 @@ verb(
--suffix=SUFFIX backup suffix (default ~ w/o --backup-dir)
-u, --update update only (don't overwrite newer files)
-l, --links copy symlinks as symlinks
-L, --copy-links copy the referent of symlinks
--copy-unsafe-links copy links outside the source tree
--safe-links ignore links outside the destination tree
-L, --copy-links copy the referent of all symlinks
--copy-unsafe-links copy the referent of "unsafe" symlinks
--safe-links ignore "unsafe" symlinks
-H, --hard-links preserve hard links
-p, --perms preserve permissions
-o, --owner preserve owner (root only)
@@ -311,13 +311,13 @@ verb(
--ignore-existing ignore files that already exist on receiver
--delete delete files that don't exist on sender
--delete-excluded also delete excluded files on receiver
--delete-after delete after transferring, not before
--ignore-errors delete even if there are IO errors
--delete-after receiver deletes after transfer, not before
--ignore-errors delete even if there are I/O errors
--max-delete=NUM don't delete more than NUM files
--partial keep partially transferred files
--force force deletion of dirs even if not empty
--numeric-ids don't map uid/gid values by user/group name
--timeout=TIME set IO timeout in seconds
--timeout=TIME set I/O timeout in seconds
-I, --ignore-times turn off mod time & file size quick check
--size-only ignore mod time for quick check (use size)
--modify-window=NUM compare mod times with reduced accuracy
@@ -334,12 +334,12 @@ verb(
--files-from=FILE read FILE for list of source-file names
-0 --from0 all file lists are delimited by nulls
--version print version number
--daemon run as a rsync daemon
--daemon run as an rsync daemon
--no-detach do not detach from the parent
--address=ADDRESS bind to the specified address
--config=FILE specify alternate rsyncd.conf file
--port=PORT specify alternate rsyncd port number
--blocking-io use blocking IO for the remote shell
--blocking-io use blocking I/O for the remote shell
--no-blocking-io turn off --blocking-io
--stats give some file transfer stats
--progress show progress during transfer
@@ -384,9 +384,9 @@ dit(bf(-I, --ignore-times)) Normally rsync will skip any files that are
already the same size and have the same modification time-stamp.
This option turns off this "quick check" behavior.
dit(bf(--size-only)) Normally rsync will skip any files that are
dit(bf(--size-only)) Normally rsync will not transfer any files that are
already the same size and have the same modification time-stamp. With the
--size-only option files will be skipped if they have the same size,
--size-only option, files will not be transferred if they have the same size,
regardless of timestamp. This is useful when starting to use rsync
after using another mirroring system which may not preserve timestamps
exactly.
@@ -402,7 +402,7 @@ dit(bf(-c, --checksum)) This forces the sender to checksum all files using
a 128-bit MD4 checksum before transfer. The checksum is then
explicitly checked on the receiver and any files of the same name
which already exist and have the same checksum and size on the
receiver are skipped. This option can be quite slow.
receiver are not transferred. This option can be quite slow.
dit(bf(-a, --archive)) This is equivalent to -rlptgoD. It is a quick
way of saying you want recursion and want to preserve almost
@@ -458,6 +458,8 @@ very useful for incremental backups. You can additionally
specify a backup suffix using the --suffix option
(otherwise the files backed up in the specified directory
will keep their original filenames).
If DIR is a relative path, it is relative to the destination directory
(which changes in a recursive transfer).
dit(bf(--suffix=SUFFIX)) This option allows you to override the default
backup suffix used with the --backup (-b) option. The default suffix is a ~
@@ -467,19 +469,26 @@ dit(bf(-u, --update)) This forces rsync to skip any files for which the
destination file already exists and has a date later than the source
file.
In the currently implementation, a difference of file format is always
considered to be important enough for an update, no matter what date
is on the objects. In other words, if the source has a directory or a
symlink where the destination has a file, the transfer would occur
regardless of the timestamps. This might change in the future (feel
free to comment on this on the mailing list if you have an opinion).
dit(bf(-l, --links)) When symlinks are encountered, recreate the
symlink on the destination.
dit(bf(-L, --copy-links)) When symlinks are encountered, the file that
they point to is copied, rather than the symlink.
they point to (the referent) is copied, rather than the symlink.
dit(bf(--copy-unsafe-links)) This tells rsync to copy the referent of
symbolic links that point outside the source tree. Absolute symlinks
symbolic links that point outside the copied tree. Absolute symlinks
are also treated like ordinary files, and so are any symlinks in the
source path itself when --relative is used.
dit(bf(--safe-links)) This tells rsync to ignore any symbolic links
which point outside the destination tree. All absolute symlinks are
which point outside the copied tree. All absolute symlinks are
also ignored. Using this option in conjunction with --relative may
give unexpected results.
@@ -496,7 +505,7 @@ dit(bf(-W, --whole-file)) With this option the incremental rsync algorithm
is not used and the whole file is sent as-is instead. The transfer may be
faster if this option is used when the bandwidth between the source and
target machines is higher than the bandwidth to disk (especially when the
"disk" is actually a networked file system). This is the default when both
"disk" is actually a networked filesystem). This is the default when both
the source and target are on the local machine.
dit(bf(--no-whole-file)) Turn off --whole-file, for use when it is the
@@ -512,15 +521,16 @@ other files (including updated files) retain their existing permissions
dit(bf(-o, --owner)) This option causes rsync to set the owner of the
destination file to be the same as the source file. On most systems,
only the super-user can set file ownership. Note that if the remote system
is a daemon using chroot, the --numeric-ids option is implied because the
remote system cannot get access to the usernames from /etc/passwd.
only the super-user can set file ownership. By default, the preservation
is done by name, but may fall back to using the ID number in some
circumstances. See the --numeric-ids option for a full discussion.
dit(bf(-g, --group)) This option causes rsync to set the group of the
destination file to be the same as the source file. If the receiving
program is not running as the super-user, only groups that the
receiver is a member of will be preserved (by group name, not group id
number).
receiver is a member of will be preserved. By default, the preservation
is done by name, but may fall back to using the ID number in some
circumstances. See the --numeric-ids option for a full discussion.
dit(bf(-D, --devices)) This option causes rsync to transfer character and
block device information to the remote system to recreate these
@@ -569,7 +579,7 @@ This option can be dangerous if used incorrectly! It is a very good idea
to run first using the dry run option (-n) to see what files would be
deleted to make sure important files aren't listed.
If the sending side detects any IO errors then the deletion of any
If the sending side detects any I/O errors then the deletion of any
files at the destination will be automatically disabled. This is to
prevent temporary filesystem failures (such as NFS errors) on the
sending side causing a massive deletion of files on the
@@ -580,13 +590,13 @@ receiving side that are not on the sending side, this tells rsync to also
delete any files on the receiving side that are excluded (see --exclude).
Implies --delete.
dit(bf(--delete-after)) By default rsync does file deletions before
transferring files to try to ensure that there is sufficient space on
the receiving filesystem. If you want to delete after transferring
then use the --delete-after switch. Implies --delete.
dit(bf(--delete-after)) By default rsync does file deletions on the
receiving side before transferring files to try to ensure that there is
sufficient space on the receiving filesystem. If you want to delete
after transferring, use the --delete-after switch. Implies --delete.
dit(bf(--ignore-errors)) Tells --delete to go ahead and delete files
even when there are IO errors.
even when there are I/O errors.
dit(bf(--force)) This options tells rsync to delete directories even if
they are not empty when they are to be replaced by non-directories. This
@@ -602,7 +612,7 @@ remote copies of rsync. Typically, rsync is configured to use ssh by
default, but you may prefer to use rsh on a local network.
If this option is used with bf([user@]host::module/path), then the
remote shell em(COMMMAND) will be used to run an rsync server on the
remote shell em(COMMAND) will be used to run an rsync server on the
remote host, and all data will be transmitted through that remote
shell connection, rather than through a direct socket connection to a
running rsync server on the remote host. See the section "CONNECTING
@@ -633,16 +643,17 @@ a file should be ignored.
The exclude list is initialized to:
quote(RCS/ SCCS/ CVS/ .svn/ CVS.adm RCSLOG cvslog.* tags TAGS .make.state
.nse_depinfo *~ #* .#* ,* *.old *.bak *.BAK *.orig *.rej .del-*
*.a *.o *.obj *.so *.Z *.elc *.ln core)
quote(RCS SCCS CVS CVS.adm RCSLOG cvslog.* tags TAGS .make.state
.nse_depinfo *~ #* .#* ,* _$* *$ *.old *.bak *.BAK *.orig *.rej
.del-* *.a *.olb *.o *.obj *.so *.exe *.Z *.elc *.ln core .svn/)
then files listed in a $HOME/.cvsignore are added to the list and any
files listed in the CVSIGNORE environment variable (space delimited).
files listed in the CVSIGNORE environment variable (all cvsignore names
are delimited by whitespace).
Finally, any file is ignored if it is in the same directory as a
.cvsignore file and matches one of the patterns listed therein. See
the bf(cvs(1)) manual for more information.
.cvsignore file and matches one of the patterns listed therein.
See the bf(cvs(1)) manual for more information.
dit(bf(--exclude=PATTERN)) This option allows you to selectively exclude
certain files from the list of files to be transferred. This is most
@@ -651,8 +662,7 @@ useful in combination with a recursive transfer.
You may use as many --exclude options on the command line as you like
to build up the list of files to exclude.
See the EXCLUDE PATTERNS section for information on the syntax of
this option.
See the EXCLUDE PATTERNS section for detailed information on this option.
dit(bf(--exclude-from=FILE)) This option is similar to the --exclude
option, but instead it adds all exclude patterns listed in the file
@@ -664,8 +674,7 @@ dit(bf(--include=PATTERN)) This option tells rsync to not exclude the
specified pattern of filenames. This is useful as it allows you to
build up quite complex exclude/include rules.
See the EXCLUDE PATTERNS section for information on the syntax of
this option.
See the EXCLUDE PATTERNS section for detailed information on this option.
dit(bf(--include-from=FILE)) This specifies a list of include patterns
from a file.
@@ -711,6 +720,8 @@ was located on the remote "src" host.
dit(bf(-0, --from0)) This tells rsync that the filenames it reads from a
file are terminated by a null ('\0') character, not a NL, CR, or CR+LF.
This affects --exclude-from, --include-from, and --files-from.
It does not affect --cvs-exclude (since all names read from a .cvsignore
file are split on whitespace).
dit(bf(-T, --temp-dir=DIR)) This option instructs rsync to use DIR as a
scratch directory when creating temporary copies of the files
@@ -728,14 +739,19 @@ although this skips files that haven't changed; see also --link-dest).
This option increases the usefulness of --partial because partially
transferred files will remain in the new temporary destination until they
have a chance to be completed. If DIR is a relative path, it is relative
to the destination directory.
to the destination directory (which changes in a recursive transfer).
dit(bf(--link-dest=DIR)) This option behaves like bf(--compare-dest) but
also will create hard links from em(DIR) to the destination directory for
unchanged files. Files with changed ownership or permissions will not be
linked.
Like bf(--compare-dest) if DIR is a relative path, it is relative
to the destination directory.
to the destination directory (which changes in a recursive transfer).
An example:
verb(
rsync -av --link-dest=$PWD/prior_dir host:src_dir/ new_dir/
)
dit(bf(-z, --compress)) With this option, rsync compresses any data from
the files that it sends to the destination machine. This
@@ -748,19 +764,22 @@ compressing transport, as it takes advantage of the implicit
information sent for matching data blocks.
dit(bf(--numeric-ids)) With this option rsync will transfer numeric group
and user ids rather than using user and group names and mapping them
and user IDs rather than using user and group names and mapping them
at both ends.
By default rsync will use the user name and group name to determine
By default rsync will use the username and groupname to determine
what ownership to give files. The special uid 0 and the special group
0 are never mapped via user/group names even if the --numeric-ids
option is not specified.
If the source system is a daemon using chroot, or if a user or group
name does not exist on the destination system, then the numeric id
from the source system is used instead.
If a user or group has no name on the source system or it has no match
on the destination system, then the numeric ID
from the source system is used instead. See also the comments on the
"use chroot" setting in the rsyncd.conf manpage for information on how
the chroot setting affects rsync's ability to look up the names of the
users and groups and what you can do about it.
dit(bf(--timeout=TIMEOUT)) This option allows you to set a maximum IO
dit(bf(--timeout=TIMEOUT)) This option allows you to set a maximum I/O
timeout in seconds. If no data is transferred for the specified time
then rsync will exit. The default is 0, which means no timeout.
@@ -799,11 +818,11 @@ the default is rsyncd.conf in the current directory (typically $HOME).
dit(bf(--port=PORT)) This specifies an alternate TCP port number to use
rather than the default port 873.
dit(bf(--blocking-io)) This tells rsync to use blocking IO when launching
dit(bf(--blocking-io)) This tells rsync to use blocking I/O when launching
a remote shell transport. If the remote shell is either rsh or remsh,
rsync defaults to using
blocking IO, otherwise it defaults to using non-blocking IO. (Note that
ssh prefers non-blocking IO.)
blocking I/O, otherwise it defaults to using non-blocking I/O. (Note that
ssh prefers non-blocking I/O.)
dit(bf(--no-blocking-io)) Turn off --blocking-io, for use when it is the
default.
@@ -828,13 +847,36 @@ showing the progress of the transfer. This gives a bored user
something to watch.
Implies --verbose without incrementing verbosity.
When the file is transferring, the data looks like this:
verb(
782448 63% 110.64kB/s 0:00:04
)
This tells you the current file size, the percentage of the transfer that
is complete, the current calculated file-completion rate (including both
data over the wire and data being matched locally), and the estimated time
remaining in this transfer.
After the a file is complete, it the data looks like this:
verb(
1238099 100% 146.38kB/s 0:00:08 (5, 57.1% of 396)
)
This tells you the final file size, that it's 100% complete, the final
transfer rate for the file, the amount of elapsed time it took to transfer
the file, and the addition of a total-transfer summary in parentheses.
These additional numbers tell you how many files have been updated, and
what percent of the total number of files has been scanned.
dit(bf(-P)) The -P option is equivalent to --partial --progress. I
found myself typing that combination quite often so I created an
option to make it easier.
dit(bf(--password-file)) This option allows you to provide a password
in a file for accessing a remote rsync server. Note that this option
is only useful when accessing a rsync server using the built in
is only useful when accessing an rsync server using the built in
transport, not when using a remote shell as the transport. The file
must not be world readable. It should contain just the password as a
single line.
@@ -844,7 +886,7 @@ transfer rate in kilobytes per second. This option is most effective when
using rsync with large files (several megabytes and up). Due to the nature
of rsync transfers, blocks of data are sent, then if rsync determines the
transfer was too fast, it will wait before sending the next data block. The
result is an average transfer rate equalling the specified limit. A value
result is an average transfer rate equaling the specified limit. A value
of zero specifies no limit.
dit(bf(--write-batch=PREFIX)) Generate a set of files that can be
@@ -862,7 +904,7 @@ manpagesection(EXCLUDE PATTERNS)
The exclude and include patterns specified to rsync allow for flexible
selection of which files to transfer and which files to skip.
rsync builds an ordered list of include/exclude options as specified on
Rsync builds an ordered list of include/exclude options as specified on
the command line. Rsync checks each file and directory
name against each exclude/include pattern in turn. The first matching
pattern is acted on. If it is an exclude pattern, then that file is
@@ -870,16 +912,61 @@ skipped. If it is an include pattern then that filename is not
skipped. If no matching include/exclude pattern is found then the
filename is not skipped.
The filenames matched against the exclude/include patterns
are relative to the destination directory, or "top
directory", so patterns should not include the path elements
of the source or destination directories. The only way in
which a pattern will match the absolute path of a file or
directory is if the source path is the root directory.
The filenames matched against the exclude/include patterns are relative
to the "root of the transfer". If you think of the transfer as a
subtree of names that are being sent from sender to receiver, the root
is where the tree starts to be duplicated in the destination directory.
This root governs where patterns that start with a / match (see below).
Note that when used with -r (which is implied by -a), every subcomponent of
every path is visited from top down, so include/exclude patterns get
Because the matching is relative to the transfer-root, changing the
trailing slash on a source path or changing your use of the --relative
option affects the path you need to use in your matching (in addition to
changing how much of the file tree is duplicated on the destination
system). The following examples demonstrate this.
Let's say that we want to match two source files, one with an absolute
path of "/home/me/foo/bar", and one with a path of "/home/you/bar/baz".
Here is how the various command choices differ for a 2-source transfer:
verb(
Example cmd: rsync -a /home/me /home/you /dest
+/- pattern: /me/foo/bar
+/- pattern: /you/bar/baz
Target file: /dest/me/foo/bar
Target file: /dest/you/bar/baz
Example cmd: rsync -a /home/me/ /home/you/ /dest
+/- pattern: /foo/bar (note missing "me")
+/- pattern: /bar/baz (note missing "you")
Target file: /dest/foo/bar
Target file: /dest/bar/baz
Example cmd: rsync -a --relative /home/me/ /home/you /dest
+/- pattern: /home/me/foo/bar (note full path)
+/- pattern: /home/you/bar/baz (ditto)
Target file: /dest/home/me/foo/bar
Target file: /dest/home/you/bar/baz
Example cmd: cd /home; rsync -a --relative me/foo you/ /dest
+/- pattern: /me/foo/bar (starts at specified path)
+/- pattern: /you/bar/baz (ditto)
Target file: /dest/me/foo/bar
Target file: /dest/you/bar/baz
)
The easiest way to see what name you should include/exclude is to just
look at the output when using --verbose and put a / in front of the name
(use the --dry-run option if you're not yet ready to copy any files).
Note that, when using the --recursive (-r) option (which is implied by -a),
every subcomponent of
every path is visited from the top down, so include/exclude patterns get
applied recursively to each subcomponent.
The exclude patterns actually short-circuit the directory traversal stage
when rsync finds the files to send. If a pattern excludes a particular
parent directory, it can render a deeper include pattern ineffectual
because rsync did not descend through that excluded section of the
hierarchy.
Note also that the --include and --exclude options take one pattern
each. To add multiple patterns use the --include-from and
@@ -893,16 +980,15 @@ itemize(
start of the filename, otherwise it is matched against the end of
the filename.
This is the equivalent of a leading ^ in regular expressions.
Thus "/foo" would match a file called "foo" at the top of the
transferred tree.
Thus "/foo" would match a file called "foo" at the transfer-root
(see above for how this is different from the filesystem-root).
On the other hand, "foo" would match any file called "foo"
anywhere in the tree because the algorithm is applied recursively from
top down; it behaves as if each path component gets a turn at being the
end of the file name.
The leading / does not make the pattern an absolute pathname.
it() if the pattern ends with a / then it will only match a
directory, not a file, link or device.
directory, not a file, link, or device.
it() if the pattern contains a wildcard character from the set
*?[ then expression matching is applied using the shell filename
@@ -920,11 +1006,11 @@ itemize(
it() if the pattern starts with "+ " (a plus followed by a space)
then it is always considered an include pattern, even if specified as
part of an exclude option. The "+ " part is discarded before matching.
part of an exclude option. The prefix is discarded before matching.
it() if the pattern starts with "- " (a minus followed by a space)
then it is always considered an exclude pattern, even if specified as
part of an include option. The "- " part is discarded before matching.
part of an include option. The prefix is discarded before matching.
it() if the pattern is a single exclamation mark ! then the current
include/exclude list is reset, removing all previously defined patterns.
@@ -932,25 +1018,45 @@ itemize(
The +/- rules are most useful in a list that was read from a file, allowing
you to have a single exclude list that contains both include and exclude
options.
options in the proper order.
If you end an exclude list with --exclude '*', note that since the
algorithm is applied recursively that unless you explicitly include
parent directories of files you want to include then the algorithm
will stop at the parent directories and never see the files below
them. To include all directories, use --include '*/' before the
--exclude '*'.
Remember that the matching occurs at every step in the traversal of the
directory hierarchy, so you must be sure that all the parent directories of
the files you want to include are not excluded. This is particularly
important when using a trailing '*' rule. For instance, this won't work:
Here are some exclude/include examples:
verb(
+ /some/path/this-file-will-not-be-found
+ /file-is-included
- *
)
This fails because the parent directory "some" is excluded by the '*' rule,
so rsync never visits any of the files in the "some" or "some/path"
directories. One solution is to ask for all directories in the hierarchy
to be included by using a single rule: --include='*/' (put it somewhere
before the --exclude='*' rule). Another solution is to add specific
include rules for all the parent dirs that need to be visited. For
instance, this set of rules works fine:
verb(
+ /some/
+ /some/path/
+ /some/path/this-file-is-found
+ /file-also-included
- *
)
Here are some examples of exclude/include matching:
itemize(
it() --exclude "*.o" would exclude all filenames matching *.o
it() --exclude "/foo" would exclude a file called foo in the top directory
it() --exclude "/foo" would exclude a file called foo in the transfer-root directory
it() --exclude "foo/" would exclude any directory called foo
it() --exclude "/foo/*/bar" would exclude any file called bar two
levels below a directory called foo in the top directory
levels below a directory called foo in the transfer-root directory
it() --exclude "/foo/**/bar" would exclude any file called bar two
or more levels below a directory called foo in the top directory
or more levels below a directory called foo in the transfer-root directory
it() --include "*/" --include "*.c" --exclude "*" would include all
directories and C source files
it() --include "foo/" --include "foo/bar.c" --exclude "*" would include
@@ -961,7 +1067,7 @@ itemize(
manpagesection(BATCH MODE)
bf(Note:) Batch mode should be considered experimental in this version
of rsync. The interface or behaviour may change before it stabilizes.
of rsync. The interface or behavior may change before it stabilizes.
Batch mode can be used to apply the same set of updates to many
identical systems. Suppose one has a tree which is replicated on a
@@ -1004,11 +1110,11 @@ once, instead of sending the same data to every host individually.
Example:
verb(
$ rsync --write-batch=pfx -a /source/dir/ /adest/dir/
$ rcp pfx.rsync_* remote:
$ ssh remote rsync --read-batch=pfx -a /bdest/dir/
# or alternatively
$ ssh remote ./pfx.rsync_argvs /bdest/dir/
$ rsync --write-batch=pfx -a /source/dir/ /adest/dir/
$ rcp pfx.rsync_* remote:
$ ssh remote rsync --read-batch=pfx -a /bdest/dir/
# or alternatively
$ ssh remote ./pfx.rsync_argvs /bdest/dir/
)
In this example, rsync is used to update /adest/dir/ with /source/dir/
@@ -1043,7 +1149,7 @@ reports.
manpagesection(SYMBOLIC LINKS)
Three basic behaviours are possible when rsync encounters a symbolic
Three basic behaviors are possible when rsync encounters a symbolic
link in the source directory.
By default, symbolic links are not transferred at all. A message
@@ -1062,7 +1168,7 @@ ensure the rsync module they copy does not include symbolic links to
bf(/etc/passwd) in the public section of the site. Using
bf(--copy-unsafe-links) will cause any links to be copied as the file
they point to on the destination. Using bf(--safe-links) will cause
unsafe links to be ommitted altogether.
unsafe links to be omitted altogether.
Symbolic links are considered unsafe if they are absolute symlinks
(start with bf(/)), empty, or if they contain enough bf("..")
@@ -1104,11 +1210,11 @@ dit(bf(2)) Protocol incompatibility
dit(bf(3)) Errors selecting input/output files, dirs
dit(bf(4)) Requested action not supported: an attempt
was made to manipulate 64-bit files on a platform that cannot support
them; or an option was speciifed that is supported by the client and
them; or an option was specified that is supported by the client and
not by the server.
dit(bf(5)) Error starting client-server protocol
dit(bf(10)) Error in socket IO
dit(bf(11)) Error in file IO
dit(bf(10)) Error in socket I/O
dit(bf(11)) Error in file I/O
dit(bf(12)) Error in rsync protocol data stream
dit(bf(13)) Errors with program diagnostics
dit(bf(14)) Error in IPC code
@@ -1137,12 +1243,13 @@ redirect your rsync client to use a web proxy when connecting to a
rsync daemon. You should set RSYNC_PROXY to a hostname:port pair.
dit(bf(RSYNC_PASSWORD)) Setting RSYNC_PASSWORD to the required
password allows you to run authenticated rsync connections to a rsync
password allows you to run authenticated rsync connections to an rsync
daemon without user intervention. Note that this does not supply a
password to a shell transport such as ssh.
dit(bf(USER) or bf(LOGNAME)) The USER or LOGNAME environment variables
are used to determine the default username sent to a rsync server.
are used to determine the default username sent to an rsync server.
If neither is set, the username defaults to "nobody".
dit(bf(HOME)) The HOME environment variable is used to find the user's
default .cvsignore file.
@@ -1163,11 +1270,11 @@ manpagebugs()
times are transferred as unix time_t values
When transferring to FAT filesystmes rsync may resync
When transferring to FAT filesystems rsync may re-sync
unmodified files.
See the comments on the --modify-window option.
file permissions, devices etc are transferred as native numerical
file permissions, devices, etc. are transferred as native numerical
values
see also the comments on the --delete option
@@ -1199,19 +1306,13 @@ Thanks to Richard Brent, Brendan Mackay, Bill Waite, Stephen Rothwell
and David Bell for helpful suggestions, patches and testing of rsync.
I've probably missed some people, my apologies if I have.
Especial thanks also to: David Dykstra, Jos Backus, Sebastian Krahmer.
Especial thanks also to: David Dykstra, Jos Backus, Sebastian Krahmer,
Martin Pool, Wayne Davison.
manpageauthor()
rsync was written by Andrew Tridgell <tridge@samba.org> and Paul
Mackerras.
rsync is now maintained by Martin Pool <mbp@samba.org>.
rsync was originally written by Andrew Tridgell and Paul Mackerras.
Many people have later contributed to it.
Mailing lists for support and development are available at
url(http://lists.samba.org)(lists.samba.org)
If you suspect you have found a security vulnerability in rsync,
please send it directly to Martin Pool and Andrew Tridgell. For other
enquiries, please use the mailing list.

View File

@@ -1,5 +1,5 @@
mailto(rsync-bugs@samba.org)
manpage(rsyncd.conf)(5)(1 Jan 2004)()()
manpage(rsyncd.conf)(5)(30 Apr 2004)()()
manpagename(rsyncd.conf)(configuration file for rsync server)
manpagesynopsis()
@@ -93,7 +93,7 @@ useful on systems (such as AIX) where syslog() doesn't work for
chrooted programs.
dit(bf(pid file)) The "pid file" option tells the rsync daemon to write
its process id to that file.
its process ID to that file.
dit(bf(syslog facility)) The "syslog facility" option allows you to
specify the syslog facility name to use when logging messages from the
@@ -135,11 +135,31 @@ to the "path" before starting the file transfer with the client. This has
the advantage of extra protection against possible implementation security
holes, but it has the disadvantages of requiring super-user privileges,
of not being able to follow symbolic links outside of the new root path
when reading, and of implying the --numeric-ids option because /etc/passwd
becomes inaccessible. When "use chroot" is false, for security reasons
when reading, and of complicating the preservation of usernames and groups
(see below). When "use chroot" is false, for security reasons,
symlinks may only be relative paths pointing to other files within the root
path, and leading slashes are removed from absolute paths. The default for
"use chroot" is true.
path, and leading slashes are removed from most absolute paths (options
such as --backup-dir, --compare-dest, etc. interpret an absolute path as
rooted in the module's "path" dir, just as if chroot was specified).
The default for "use chroot" is true.
In order to preserve usernames and groupnames, rsync needs to be able to
use the standard library functions for looking up names and IDs (i.e.
getpwuid(), getgrgid(), getpwname(), and getgrnam()). This means a
process in the chroot namespace will need to have access to the resources
used by these library functions (traditionally /etc/passwd and
/etc/group). If these resources are not available, rsync will only be
able to copy the IDs, just as if the --numeric-ids option had been
specified.
Note that you are free to setup user/group information in the chroot area
differently from your normal system. For example, you could abbreviate
the list of users and groups. Also, you can protect this information
from being downloaded by adding an exclude rule to the rsync.conf file
(e.g. "exclude = /etc/"). To protect it from being changed by an upload
(if the module is not read only), be sure to set the permissions (or
owner) on the files and/or parent directories so that they cannot be
written by the daemon.
dit(bf(max connections)) The "max connections" option allows you to
specify the maximum number of simultaneous connections you will allow.
@@ -164,13 +184,13 @@ listed when the client asks for a listing of available modules. By
setting this to false you can create hidden modules. The default is
for modules to be listable.
dit(bf(uid)) The "uid" option specifies the user name or user id that
dit(bf(uid)) The "uid" option specifies the user name or user ID that
file transfers to and from that module should take place as when the daemon
was run as root. In combination with the "gid" option this determines what
file permissions are available. The default is uid -2, which is normally
the user "nobody".
dit(bf(gid)) The "gid" option specifies the group name or group id that
dit(bf(gid)) The "gid" option specifies the group name or group ID that
file transfers to and from that module should take place as when the daemon
was run as root. This complements the "uid" option. The default is gid -2,
which is normally the group "nobody".
@@ -229,7 +249,7 @@ connect without a password (this is called "anonymous rsync").
See also the bf(CONNECTING TO AN RSYNC SERVER OVER A REMOTE SHELL
PROGRAM) section in rsync(1) for information on how handle an
rsyncd.conf-level username that differs from the remote-shell-level
username when using a remote shell to connect to a rsync server.
username when using a remote shell to connect to an rsync server.
dit(bf(secrets file)) The "secrets file" option specifies the name of
a file that contains the username:password pairs used for
@@ -247,7 +267,7 @@ by "other"; see "strict modes".
dit(bf(strict modes)) The "strict modes" option determines whether or not
the permissions on the secrets file will be checked. If "strict modes" is
true, then the secrets file must not be readable by any user id other
true, then the secrets file must not be readable by any user ID other
than the one that the rsync daemon is running under. If "strict modes" is
false, the check is not performed. The default is true. This option
was added to accommodate rsync running on the Windows operating system.
@@ -306,10 +326,10 @@ rejected. See the "hosts allow" option for more information.
The default is no "hosts deny" option, which means all hosts can connect.
dit(bf(ignore errors)) The "ignore errors" option tells rsyncd to
ignore IO errors on the server when deciding whether to run the delete
ignore I/O errors on the server when deciding whether to run the delete
phase of the transfer. Normally rsync skips the --delete step if any
IO errors have occurred in order to prevent disasterous deletion due
to a temporary resource shortage or other IO error. In some cases this
I/O errors have occurred in order to prevent disasterous deletion due
to a temporary resource shortage or other I/O error. In some cases this
test is counter productive so you can use this option to turn off this
behaviour.
@@ -334,7 +354,7 @@ itemize(
it() %h for the remote host name
it() %a for the remote IP address
it() %l for the length of the file in bytes
it() %p for the process id of this rsync session
it() %p for the process ID of this rsync session
it() %o for the operation, which is either "send" or "recv"
it() %f for the filename
it() %P for the module path
@@ -353,7 +373,7 @@ A perl script called rsyncstats to summarize this format is included
in the rsync source code distribution.
dit(bf(timeout)) The "timeout" option allows you to override the
clients choice for IO timeout for this module. Using this option you
clients choice for I/O timeout for this module. Using this option you
can ensure that rsync won't wait on a dead client forever. The timeout
is specified in seconds. A value of zero means no timeout and is the
default. A good choice for anonymous rsync servers may be 600 (giving
@@ -415,7 +435,7 @@ where command would be
quote(rsync --server --daemon .)
NOTE: rsync's argument parsing expects the trailing ".", so make sure
that it's there. If you want to use a rsyncd.conf(5)-style
that it's there. If you want to use an rsyncd.conf(5)-style
configuration file other than the default, you can added a
--config option to the em(command):

View File

@@ -142,7 +142,7 @@ echo "$0 running in `pwd`"
echo " rsync_bin=$rsync_bin"
echo " srcdir=$srcdir"
testuser=`whoami || echo UNKNOWN`
testuser=`id -un || whoami || echo UNKNOWN`
echo " testuser=$testuser"
echo " os=`uname -a`"
@@ -220,6 +220,11 @@ do
echo "----- $testbase log follows"
cat "$scratchdir/test.log"
echo "----- $testbase log ends"
if [ -f "$scratchdir/rsyncd.log" ]; then
echo "----- $testbase rsyncd.log follows"
cat "$scratchdir/rsyncd.log"
echo "----- $testbase rsyncd.log ends"
fi
fi
case $result in

View File

@@ -25,6 +25,8 @@ extern struct stats stats;
extern int io_error;
extern int dry_run;
extern int am_server;
extern int am_daemon;
extern int protocol_version;
/**
@@ -34,12 +36,8 @@ extern int am_server;
* and transmits them to the receiver. The sender process runs on the
* machine holding the source files.
**/
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) {
@@ -71,10 +69,10 @@ static struct sum_struct *receive_sums(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);
if (verbose > 3) {
rprintf(FINFO, "count=%ld n=%u rem=%u\n",
(long)s->count, s->blength, s->remainder);
}
if (s->count == 0)
return(s);
@@ -120,19 +118,19 @@ void send_files(struct file_list *flist, int f_out, int f_in)
int phase = 0;
extern struct stats stats;
struct stats initial_stats;
extern int write_batch; /* dw */
extern int read_batch; /* dw */
int checksums_match; /* dw */
int buff_len; /* dw */
char buff[CHUNK_SIZE]; /* dw */
int j; /* dw */
int done; /* dw */
extern int write_batch;
extern int read_batch;
int checksums_match;
int buff_len;
char buff[CHUNK_SIZE];
int j;
int done;
if (verbose > 2)
rprintf(FINFO, "send_files starting\n");
while (1) {
int offset = 0;
unsigned int offset;
i = read_int(f_in);
if (i == -1) {
@@ -155,22 +153,18 @@ void send_files(struct file_list *flist, int f_out, int f_in)
file = flist->files[i];
stats.current_file_index = i;
stats.num_transferred_files++;
stats.total_transferred_size += file->length;
fname[0] = 0;
if (file->basedir) {
strlcpy(fname, file->basedir, MAXPATHLEN);
if (strlen(fname) == MAXPATHLEN-1) {
io_error |= IOERR_GENERAL;
rprintf(FERROR, "send_files failed on long-named directory %s\n",
full_fname(fname));
return;
}
strlcat(fname, "/", MAXPATHLEN);
offset = strlen(file->basedir)+1;
}
strlcat(fname, f_name(file), MAXPATHLEN);
/* N.B. We're sure that this fits, so offset is OK. */
offset = strlcpy(fname, file->basedir, sizeof fname);
if (!offset || fname[offset-1] != '/')
fname[offset++] = '/';
} else
offset = 0;
f_name_to(file, fname + offset);
if (verbose > 2)
rprintf(FINFO, "send_files(%d, %s)\n", i, fname);
@@ -193,15 +187,18 @@ void send_files(struct file_list *flist, int f_out, int f_in)
}
if (write_batch)
write_batch_csum_info(&i, flist->count, s);
write_batch_csum_info(&i, s);
if (!read_batch) {
fd = do_open(fname, O_RDONLY, 0);
if (fd == -1) {
if (errno == ENOENT) {
enum logcode c = am_daemon
&& protocol_version < 28 ? FERROR
: FINFO;
io_error |= IOERR_VANISHED;
rprintf(FINFO, "file has vanished: %s\n",
full_fname(fname));
rprintf(c, "file has vanished: %s\n",
full_fname(fname));
} else {
io_error |= IOERR_GENERAL;
rprintf(FERROR, "send_files failed to open %s: %s\n",
@@ -233,7 +230,7 @@ void send_files(struct file_list *flist, int f_out, int f_in)
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);
}
@@ -247,11 +244,11 @@ void send_files(struct file_list *flist, int f_out, int f_in)
set_compression(fname);
if (read_batch) { /* dw */
if (read_batch) {
/* 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) );
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);
@@ -263,7 +260,7 @@ void send_files(struct file_list *flist, int f_out, int f_in)
write_sum_head(f_out, s);
done = 0;
while (!done) {
read_batch_delta_file( (char *) &buff_len, sizeof(int) );
read_batch_delta_file((char*)&buff_len, sizeof (int));
write_int(f_out, buff_len);
if (buff_len == 0) {
done = 1;
@@ -288,7 +285,7 @@ void send_files(struct file_list *flist, int f_out, int f_in)
log_send(file, &initial_stats);
}
if (!read_batch) { /* dw */
if (!read_batch) {
if (buf) {
j = unmap_file(buf);
if (j) {
@@ -313,7 +310,7 @@ void send_files(struct file_list *flist, int f_out, int f_in)
match_report();
write_int(f_out, -1);
if (write_batch || read_batch) { /* dw */
if (write_batch || read_batch) {
close_batch_csums_file();
close_batch_delta_file();
}

432
socket.c
View File

@@ -1,20 +1,20 @@
/* -*- 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.
@@ -22,7 +22,7 @@
/**
* @file socket.c
*
*
* Socket functions used in rsync.
*
* This file is now converted to use the new-style getaddrinfo()
@@ -36,21 +36,45 @@
/**
* Establish a proxy connection on an open socket to a web proxy by
* using the HTTP CONNECT method.
* using the CONNECT method. If proxy_user and proxy_pass are not NULL,
* they are used to authenticate to the proxy using the "Basic"
* proxy-authorization protocol
**/
static int establish_proxy_connection(int fd, char *host, int port)
static int establish_proxy_connection(int fd, char *host, int port,
char *proxy_user, char *proxy_pass)
{
char buffer[1024];
char *cp;
char *cp, buffer[1024];
char *authhdr, authbuf[1024];
int len;
snprintf(buffer, sizeof(buffer), "CONNECT %s:%d HTTP/1.0\r\n\r\n", host, port);
if (write(fd, buffer, strlen(buffer)) != (int) strlen(buffer)) {
if (proxy_user && proxy_pass) {
stringjoin(buffer, sizeof buffer,
proxy_user, ":", proxy_pass, NULL);
len = strlen(buffer);
if ((len*8 + 5) / 6 >= (int)sizeof authbuf) {
rprintf(FERROR,
"authentication information is too long\n");
return -1;
}
base64_encode(buffer, len, authbuf);
authhdr = "\r\nProxy-Authorization: Basic ";
} else {
*authbuf = '\0';
authhdr = "";
}
snprintf(buffer, sizeof buffer, "CONNECT %s:%d HTTP/1.0%s%s\r\n\r\n",
host, port, authhdr, authbuf);
len = strlen(buffer);
if (write(fd, buffer, len) != len) {
rprintf(FERROR, "failed to write to proxy: %s\n",
strerror(errno));
return -1;
}
for (cp = buffer; cp < &buffer[sizeof(buffer) - 1]; cp++) {
for (cp = buffer; cp < &buffer[sizeof buffer - 1]; cp++) {
if (read(fd, cp, 1) != 1) {
rprintf(FERROR, "failed to read from proxy: %s\n",
strerror(errno));
@@ -70,8 +94,7 @@ static int establish_proxy_connection(int fd, char *host, int port)
buffer);
return -1;
}
for (cp = &buffer[5]; isdigit(* (unsigned char *) cp) || (*cp == '.'); cp++)
;
for (cp = &buffer[5]; isdigit(*(uchar*)cp) || *cp == '.'; cp++) {}
while (*cp == ' ')
cp++;
if (*cp != '2') {
@@ -81,8 +104,7 @@ static int establish_proxy_connection(int fd, char *host, int port)
}
/* throw away the rest of the HTTP header */
while (1) {
for (cp = buffer; cp < &buffer[sizeof(buffer) - 1];
cp++) {
for (cp = buffer; cp < &buffer[sizeof buffer - 1]; cp++) {
if (read(fd, cp, 1) != 1) {
rprintf(FERROR, "failed to read from proxy: %s\n",
strerror(errno));
@@ -91,9 +113,9 @@ static int establish_proxy_connection(int fd, char *host, int port)
if (*cp == '\n')
break;
}
if ((cp > buffer) && (*cp == '\n'))
if (cp > buffer && *cp == '\n')
cp--;
if ((cp == buffer) && ((*cp == '\n') || (*cp == '\r')))
if (cp == buffer && (*cp == '\n' || *cp == '\r'))
break;
}
return 0;
@@ -104,14 +126,13 @@ static int establish_proxy_connection(int fd, char *host, int port)
* Try to set the local address for a newly-created socket. Return -1
* if this fails.
**/
int try_bind_local(int s,
int ai_family, int ai_socktype,
int try_bind_local(int s, int ai_family, int ai_socktype,
const char *bind_address)
{
int error;
struct addrinfo bhints, *bres_all, *r;
memset(&bhints, 0, sizeof(bhints));
memset(&bhints, 0, sizeof bhints);
bhints.ai_family = ai_family;
bhints.ai_socktype = ai_socktype;
bhints.ai_flags = AI_PASSIVE;
@@ -160,42 +181,59 @@ int open_socket_out(char *host, int port, const char *bind_address,
int af_hint)
{
int type = SOCK_STREAM;
int error;
int s;
int error, s;
struct addrinfo hints, *res0, *res;
char portbuf[10];
char *h;
char *h, *cp;
int proxied = 0;
char buffer[1024];
char *cp;
char *proxy_user = NULL, *proxy_pass = NULL;
/* if we have a RSYNC_PROXY env variable then redirect our
* connetcion via a web proxy at the given address. The format
* is hostname:port */
* connetcion via a web proxy at the given address. */
h = getenv("RSYNC_PROXY");
proxied = (h != NULL) && (*h != '\0');
proxied = h != NULL && *h != '\0';
if (proxied) {
strlcpy(buffer, h, sizeof(buffer));
cp = strchr(buffer, ':');
if (cp == NULL) {
strlcpy(buffer, h, sizeof buffer);
/* Is the USER:PASS@ prefix present? */
if ((cp = strchr(buffer, '@')) != NULL) {
*cp++ = '\0';
/* The remainder is the HOST:PORT part. */
h = cp;
if ((cp = strchr(buffer, ':')) == NULL) {
rprintf(FERROR,
"invalid proxy specification: should be USER:PASS@HOST:PORT\n");
return -1;
}
*cp++ = '\0';
proxy_user = buffer;
proxy_pass = cp;
} else {
/* The whole buffer is the HOST:PORT part. */
h = buffer;
}
if ((cp = strchr(h, ':')) == NULL) {
rprintf(FERROR,
"invalid proxy specification: should be HOST:PORT\n");
return -1;
}
*cp++ = '\0';
strcpy(portbuf, cp);
h = buffer;
strlcpy(portbuf, cp, sizeof portbuf);
if (verbose >= 2) {
rprintf(FINFO, "connection via http proxy %s port %s\n",
h, portbuf);
}
} else {
snprintf(portbuf, sizeof(portbuf), "%d", port);
snprintf(portbuf, sizeof portbuf, "%d", port);
h = host;
}
memset(&hints, 0, sizeof(hints));
memset(&hints, 0, sizeof hints);
hints.ai_family = af_hint;
hints.ai_socktype = type;
error = getaddrinfo(h, portbuf, &hints, &res0);
@@ -215,26 +253,26 @@ int open_socket_out(char *host, int port, const char *bind_address,
if (s < 0)
continue;
if (bind_address)
if (try_bind_local(s, res->ai_family, type,
bind_address) == -1) {
close(s);
s = -1;
continue;
}
if (bind_address
&& try_bind_local(s, res->ai_family, type,
bind_address) == -1) {
close(s);
s = -1;
continue;
}
if (connect(s, res->ai_addr, res->ai_addrlen) < 0) {
close(s);
s = -1;
continue;
}
if (proxied &&
establish_proxy_connection(s, host, port) != 0) {
if (proxied
&& establish_proxy_connection(s, host, port,
proxy_user, proxy_pass) != 0) {
close(s);
s = -1;
continue;
} else
break;
}
break;
}
freeaddrinfo(res0);
if (s < 0) {
@@ -258,18 +296,19 @@ int open_socket_out(char *host, int port, const char *bind_address,
*
* @param bind_address Local address to use. Normally NULL to get the stack default.
**/
int open_socket_out_wrapped (char *host,
int port,
const char *bind_address,
int af_hint)
int open_socket_out_wrapped(char *host, int port, const char *bind_address,
int af_hint)
{
char *prog;
char *prog = getenv("RSYNC_CONNECT_PROG");
if ((prog = getenv ("RSYNC_CONNECT_PROG")) != NULL)
return sock_exec (prog);
else
return open_socket_out (host, port, bind_address,
af_hint);
if (verbose >= 2) {
rprintf(FINFO, "%sopening tcp connection to %s port %d\n",
prog ? "Using RSYNC_CONNECT_PROG instead of " : "",
host, port);
}
if (prog)
return sock_exec(prog);
return open_socket_out(host, port, bind_address, af_hint);
}
@@ -279,72 +318,94 @@ int open_socket_out_wrapped (char *host,
*
* Try to be better about handling the results of getaddrinfo(): when
* opening an inbound socket, we might get several address results,
* e.g. for the machine's ipv4 and ipv6 name.
*
* e.g. for the machine's ipv4 and ipv6 name.
*
* If binding a wildcard, then any one of them should do. If an address
* was specified but it's insufficiently specific then that's not our
* fault.
*
* fault.
*
* However, some of the advertized addresses may not work because e.g. we
* don't have IPv6 support in the kernel. In that case go on and try all
* addresses until one succeeds.
*
*
* @param bind_address Local address to bind, or NULL to allow it to
* default.
**/
static int open_socket_in(int type, int port, const char *bind_address,
int af_hint)
static int *open_socket_in(int type, int port, const char *bind_address,
int af_hint)
{
int one=1;
int s;
int s, *sp, *socks, maxs;
struct addrinfo hints, *all_ai, *resp;
char portbuf[10];
int error;
memset(&hints, 0, sizeof(hints));
memset(&hints, 0, sizeof hints);
hints.ai_family = af_hint;
hints.ai_socktype = type;
hints.ai_flags = AI_PASSIVE;
snprintf(portbuf, sizeof(portbuf), "%d", port);
snprintf(portbuf, sizeof portbuf, "%d", port);
error = getaddrinfo(bind_address, portbuf, &hints, &all_ai);
if (error) {
rprintf(FERROR, RSYNC_NAME ": getaddrinfo: bind address %s: %s\n",
bind_address, gai_strerror(error));
return -1;
return NULL;
}
/* Count max number of sockets we might open. */
for (maxs = 0, resp = all_ai; resp; resp = resp->ai_next, maxs++) {}
socks = new_array(int, maxs + 1);
if (!socks) {
rprintf(FERROR,
RSYNC_NAME "couldn't allocate memory for sockets");
return NULL;
}
/* We may not be able to create the socket, if for example the
* machine knows about IPv6 in the C library, but not in the
* kernel. */
sp = socks + 1; /* Leave room for count at start of array. */
for (resp = all_ai; resp; resp = resp->ai_next) {
s = socket(resp->ai_family, resp->ai_socktype,
resp->ai_protocol);
if (s == -1)
if (s == -1) {
/* See if there's another address that will work... */
continue;
}
setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
(char *)&one, sizeof one);
/* now we've got a socket - we need to bind it */
if (bind(s, all_ai->ai_addr, all_ai->ai_addrlen) < 0) {
#ifdef IPV6_V6ONLY
if (resp->ai_family == AF_INET6) {
setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
(char *)&one, sizeof one);
}
#endif
/* Now we've got a socket - we need to bind it. */
if (bind(s, resp->ai_addr, resp->ai_addrlen) < 0) {
/* Nope, try another */
close(s);
continue;
}
freeaddrinfo(all_ai);
return s;
*sp++ = s;
}
*socks = sp - socks - 1; /* Save count. */
rprintf(FERROR, RSYNC_NAME ": open inbound socket on port %d failed: "
"%s\n",
port,
strerror(errno));
if (all_ai)
freeaddrinfo(all_ai);
freeaddrinfo(all_ai);
return -1;
if (*socks == 0) {
rprintf(FERROR,
RSYNC_NAME ": open inbound socket on port %d failed: "
"%s\n", port, strerror(errno));
free(socks);
return NULL;
}
return socks;
}
@@ -354,55 +415,64 @@ static int open_socket_in(int type, int port, const char *bind_address,
int is_a_socket(int fd)
{
int v;
socklen_t l;
l = sizeof(int);
socklen_t l = sizeof (int);
/* Parameters to getsockopt, setsockopt etc are very
* unstandardized across platforms, so don't be surprised if
* there are compiler warnings on e.g. SCO OpenSwerver or AIX.
* It seems they all eventually get the right idea.
*
* Debian says: ``The fifth argument of getsockopt and
* setsockopt is in reality an int [*] (and this is what BSD
* 4.* and libc4 and libc5 have). Some POSIX confusion
* resulted in the present socklen_t. The draft standard has
* not been adopted yet, but glibc2 already follows it and
* also has socklen_t [*]. See also accept(2).''
*
* We now return to your regularly scheduled programming. */
return(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&v, &l) == 0);
/* Parameters to getsockopt, setsockopt etc are very
* unstandardized across platforms, so don't be surprised if
* there are compiler warnings on e.g. SCO OpenSwerver or AIX.
* It seems they all eventually get the right idea.
*
* Debian says: ``The fifth argument of getsockopt and
* setsockopt is in reality an int [*] (and this is what BSD
* 4.* and libc4 and libc5 have). Some POSIX confusion
* resulted in the present socklen_t. The draft standard has
* not been adopted yet, but glibc2 already follows it and
* also has socklen_t [*]. See also accept(2).''
*
* We now return to your regularly scheduled programming. */
return getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&v, &l) == 0;
}
static RETSIGTYPE sigchld_handler(UNUSED(int val))
{
signal(SIGCHLD, sigchld_handler);
#ifdef WNOHANG
while (waitpid(-1, NULL, WNOHANG) > 0) {}
#endif
signal(SIGCHLD, sigchld_handler);
}
void start_accept_loop(int port, int (*fn)(int, int))
{
int s;
fd_set deffds;
int *sp, maxfd, i, j;
extern char *bind_address;
extern int default_af_hint;
/* open an incoming socket */
s = open_socket_in(SOCK_STREAM, port, bind_address, default_af_hint);
if (s == -1)
sp = open_socket_in(SOCK_STREAM, port, bind_address, default_af_hint);
if (sp == NULL)
exit_cleanup(RERR_SOCKETIO);
/* ready to listen */
if (listen(s, 5) == -1) {
close(s);
exit_cleanup(RERR_SOCKETIO);
FD_ZERO(&deffds);
maxfd = -1;
for (i = 1; i <= *sp; i++) {
if (listen(sp[i], 5) == -1) {
for (j = 1; j <= i; j++)
close(sp[j]);
free(sp);
exit_cleanup(RERR_SOCKETIO);
}
FD_SET(sp[i], &deffds);
if (maxfd < sp[i])
maxfd = sp[i];
}
/* now accept incoming connections - forking a new process
for each incoming connection */
* for each incoming connection */
while (1) {
fd_set fds;
pid_t pid;
@@ -411,30 +481,38 @@ void start_accept_loop(int port, int (*fn)(int, int))
socklen_t addrlen = sizeof addr;
/* close log file before the potentially very long select so
file can be trimmed by another process instead of growing
forever */
* file can be trimmed by another process instead of growing
* forever */
log_close();
FD_ZERO(&fds);
FD_SET(s, &fds);
#ifdef FD_COPY
FD_COPY(&deffds, &fds);
#else
fds = deffds;
#endif
if (select(s+1, &fds, NULL, NULL, NULL) != 1) {
if (select(maxfd + 1, &fds, NULL, NULL, NULL) != 1)
continue;
fd = -1;
for (i = 1; i <= *sp; i++) {
if (FD_ISSET(sp[i], &fds)) {
fd = accept(sp[i], (struct sockaddr *)&addr,
&addrlen);
break;
}
}
if(!FD_ISSET(s, &fds)) continue;
fd = accept(s,(struct sockaddr *)&addr,&addrlen);
if (fd == -1) continue;
if (fd < 0)
continue;
signal(SIGCHLD, sigchld_handler);
if ((pid = fork()) == 0) {
int ret;
close(s);
close(sp[i]);
/* open log file in child before possibly giving
up privileges */
* up privileges */
log_open();
ret = fn(fd, fd);
close_all();
@@ -454,6 +532,7 @@ void start_accept_loop(int port, int (*fn)(int, int))
close(fd);
}
}
free(sp);
}
@@ -499,7 +578,7 @@ struct
#endif
{NULL,0,0,0,0}};
/**
* Set user socket options
@@ -507,13 +586,16 @@ struct
void set_socket_options(int fd, char *options)
{
char *tok;
if (!options || !*options) return;
if (!options || !*options)
return;
options = strdup(options);
if (!options) out_of_memory("set_socket_options");
for (tok=strtok(options, " \t,"); tok; tok=strtok(NULL," \t,")) {
if (!options)
out_of_memory("set_socket_options");
for (tok = strtok(options, " \t,"); tok; tok = strtok(NULL," \t,")) {
int ret=0,i;
int value = 1;
char *p;
@@ -525,9 +607,10 @@ void set_socket_options(int fd, char *options)
got_value = 1;
}
for (i=0;socket_options[i].name;i++)
for (i = 0; socket_options[i].name; i++) {
if (strcmp(socket_options[i].name,tok)==0)
break;
}
if (!socket_options[i].name) {
rprintf(FERROR,"Unknown socket option %s\n",tok);
@@ -538,9 +621,10 @@ void set_socket_options(int fd, char *options)
case OPT_BOOL:
case OPT_INT:
ret = setsockopt(fd,socket_options[i].level,
socket_options[i].option,(char *)&value,sizeof(int));
socket_options[i].option,
(char *)&value, sizeof (int));
break;
case OPT_ON:
if (got_value)
rprintf(FERROR,"syntax error - %s does not take a value\n",tok);
@@ -548,11 +632,12 @@ void set_socket_options(int fd, char *options)
{
int on = socket_options[i].value;
ret = setsockopt(fd,socket_options[i].level,
socket_options[i].option,(char *)&on,sizeof(int));
socket_options[i].option,
(char *)&on, sizeof (int));
}
break;
break;
}
if (ret != 0)
rprintf(FERROR, "failed to set socket option %s: %s\n", tok,
strerror(errno));
@@ -579,15 +664,15 @@ void become_daemon(void)
#ifdef TIOCNOTTY
i = open("/dev/tty", O_RDWR);
if (i >= 0) {
ioctl(i, (int) TIOCNOTTY, (char *)0);
ioctl(i, (int)TIOCNOTTY, (char *)0);
close(i);
}
#endif /* TIOCNOTTY */
#endif
/* make sure that stdin, stdout an stderr don't stuff things
up (library functions, for example) */
for (i=0;i<3;i++) {
close(i);
* up (library functions, for example) */
for (i = 0; i < 3; i++) {
close(i);
open("/dev/null", O_RDWR);
}
}
@@ -596,7 +681,7 @@ void become_daemon(void)
/**
* This is like socketpair but uses tcp. It is used by the Samba
* regression test code.
*
*
* The function guarantees that nobody else can attach to the socket,
* or if they do that this function fails and the socket gets closed
* returns 0 on success, -1 on failure the resulting file descriptors
@@ -607,56 +692,65 @@ static int socketpair_tcp(int fd[2])
int listener;
struct sockaddr_in sock;
struct sockaddr_in sock2;
socklen_t socklen = sizeof(sock);
socklen_t socklen = sizeof sock;
int connect_done = 0;
fd[0] = fd[1] = listener = -1;
memset(&sock, 0, sizeof(sock));
if ((listener = socket(PF_INET, SOCK_STREAM, 0)) == -1) goto failed;
memset(&sock, 0, sizeof sock);
memset(&sock2, 0, sizeof(sock2));
#ifdef HAVE_SOCKADDR_LEN
sock2.sin_len = sizeof(sock2);
if ((listener = socket(PF_INET, SOCK_STREAM, 0)) == -1)
goto failed;
memset(&sock2, 0, sizeof sock2);
#if HAVE_SOCKADDR_IN_LEN
sock2.sin_len = sizeof sock2;
#endif
sock2.sin_family = PF_INET;
sock2.sin_family = PF_INET;
bind(listener, (struct sockaddr *)&sock2, sizeof(sock2));
bind(listener, (struct sockaddr *)&sock2, sizeof sock2);
if (listen(listener, 1) != 0) goto failed;
if (listen(listener, 1) != 0)
goto failed;
if (getsockname(listener, (struct sockaddr *)&sock, &socklen) != 0) goto failed;
if (getsockname(listener, (struct sockaddr *)&sock, &socklen) != 0)
goto failed;
if ((fd[1] = socket(PF_INET, SOCK_STREAM, 0)) == -1) goto failed;
if ((fd[1] = socket(PF_INET, SOCK_STREAM, 0)) == -1)
goto failed;
set_nonblocking(fd[1]);
sock.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
if (connect(fd[1],(struct sockaddr *)&sock,sizeof(sock)) == -1) {
if (errno != EINPROGRESS) goto failed;
} else {
if (connect(fd[1], (struct sockaddr *)&sock, sizeof sock) == -1) {
if (errno != EINPROGRESS)
goto failed;
} else
connect_done = 1;
}
if ((fd[0] = accept(listener, (struct sockaddr *)&sock, &socklen)) == -1) goto failed;
if ((fd[0] = accept(listener, (struct sockaddr *)&sock, &socklen)) == -1)
goto failed;
close(listener);
if (connect_done == 0) {
if (connect(fd[1],(struct sockaddr *)&sock,sizeof(sock)) != 0
&& errno != EISCONN) goto failed;
if (connect(fd[1], (struct sockaddr *)&sock, sizeof sock) != 0
&& errno != EISCONN)
goto failed;
}
set_blocking (fd[1]);
set_blocking(fd[1]);
/* all OK! */
return 0;
failed:
if (fd[0] != -1) close(fd[0]);
if (fd[1] != -1) close(fd[1]);
if (listener != -1) close(listener);
if (fd[0] != -1)
close(fd[0]);
if (fd[1] != -1)
close(fd[1]);
if (listener != -1)
close(listener);
return -1;
}
@@ -674,30 +768,22 @@ static int socketpair_tcp(int fd[2])
int sock_exec(const char *prog)
{
int fd[2];
if (socketpair_tcp(fd) != 0) {
rprintf (FERROR, RSYNC_NAME
": socketpair_tcp failed (%s)\n",
strerror(errno));
rprintf(FERROR, RSYNC_NAME ": socketpair_tcp failed (%s)\n",
strerror(errno));
return -1;
}
if (verbose >= 2)
rprintf(FINFO, "Running socket program: \"%s\"\n", prog);
if (fork() == 0) {
close(fd[0]);
close(0);
close(1);
dup(fd[1]);
dup(fd[1]);
if (verbose > 3) {
/* Can't use rprintf because we've forked. */
fprintf (stderr,
RSYNC_NAME ": execute socket program \"%s\"\n",
prog);
}
exit (system (prog));
exit(system(prog));
}
close (fd[1]);
close(fd[1]);
return fd[0];
}

View File

@@ -31,19 +31,27 @@ extern int read_only;
extern int list_only;
extern int preserve_perms;
#define CHECK_RO if (read_only || list_only) {errno = EROFS; return -1;}
#define RETURN_ERROR_IF(x,e) \
do { \
if (x) { \
errno = (e); \
return -1; \
} \
} while (0)
#define RETURN_ERROR_IF_RO_OR_LO RETURN_ERROR_IF(read_only || list_only, EROFS)
int do_unlink(char *fname)
{
if (dry_run) return 0;
CHECK_RO
RETURN_ERROR_IF_RO_OR_LO;
return unlink(fname);
}
int do_symlink(char *fname1, char *fname2)
{
if (dry_run) return 0;
CHECK_RO
RETURN_ERROR_IF_RO_OR_LO;
return symlink(fname1, fname2);
}
@@ -51,7 +59,7 @@ int do_symlink(char *fname1, char *fname2)
int do_link(char *fname1, char *fname2)
{
if (dry_run) return 0;
CHECK_RO
RETURN_ERROR_IF_RO_OR_LO;
return link(fname1, fname2);
}
#endif
@@ -59,7 +67,7 @@ int do_link(char *fname1, char *fname2)
int do_lchown(const char *path, uid_t owner, gid_t group)
{
if (dry_run) return 0;
CHECK_RO
RETURN_ERROR_IF_RO_OR_LO;
return lchown(path, owner, group);
}
@@ -67,7 +75,7 @@ int do_lchown(const char *path, uid_t owner, gid_t group)
int do_mknod(char *pathname, mode_t mode, dev_t dev)
{
if (dry_run) return 0;
CHECK_RO
RETURN_ERROR_IF_RO_OR_LO;
return mknod(pathname, mode, dev);
}
#endif
@@ -75,18 +83,16 @@ int do_mknod(char *pathname, mode_t mode, dev_t dev)
int do_rmdir(char *pathname)
{
if (dry_run) return 0;
CHECK_RO
RETURN_ERROR_IF_RO_OR_LO;
return rmdir(pathname);
}
int do_open(char *pathname, int flags, mode_t mode)
{
if (flags != O_RDONLY) {
if (dry_run) return -1;
CHECK_RO
RETURN_ERROR_IF(dry_run, 0);
RETURN_ERROR_IF_RO_OR_LO;
}
/* some systems can't handle a double / */
if (pathname[0] == '/' && pathname[1] == '/') pathname++;
return open(pathname, flags | O_BINARY, mode);
}
@@ -96,9 +102,9 @@ int do_chmod(const char *path, mode_t mode)
{
int code;
if (dry_run) return 0;
CHECK_RO
RETURN_ERROR_IF_RO_OR_LO;
code = chmod(path, mode);
if ((code != 0) && preserve_perms)
if (code != 0 && preserve_perms)
return code;
return 0;
}
@@ -107,7 +113,7 @@ int do_chmod(const char *path, mode_t mode)
int do_rename(char *fname1, char *fname2)
{
if (dry_run) return 0;
CHECK_RO
RETURN_ERROR_IF_RO_OR_LO;
return rename(fname1, fname2);
}
@@ -133,9 +139,8 @@ void trim_trailing_slashes(char *name)
int do_mkdir(char *fname, mode_t mode)
{
if (dry_run)
return 0;
CHECK_RO;
if (dry_run) return 0;
RETURN_ERROR_IF_RO_OR_LO;
trim_trailing_slashes(fname);
return mkdir(fname, mode);
}
@@ -144,22 +149,26 @@ int do_mkdir(char *fname, mode_t mode)
/* like mkstemp but forces permissions */
int do_mkstemp(char *template, mode_t perms)
{
if (dry_run) return -1;
if (read_only) {errno = EROFS; return -1;}
RETURN_ERROR_IF(dry_run, 0);
RETURN_ERROR_IF(read_only, EROFS);
#if defined(HAVE_SECURE_MKSTEMP) && defined(HAVE_FCHMOD)
{
int fd = mkstemp(template);
if (fd == -1) return -1;
if ((fchmod(fd, perms) != 0) && preserve_perms) {
if (fd == -1)
return -1;
if (fchmod(fd, perms) != 0 && preserve_perms) {
int errno_save = errno;
close(fd);
unlink(template);
errno = errno_save;
return -1;
}
return fd;
}
#else
if (!mktemp(template)) return -1;
if (!mktemp(template))
return -1;
return do_open(template, O_RDWR|O_EXCL|O_CREAT, perms);
#endif
}

View File

@@ -28,7 +28,7 @@
int modify_window = 0;
int module_id = -1;
struct exclude_struct **server_exclude_list;
struct exclude_list_struct server_exclude_list;
void rprintf(UNUSED(enum logcode code), const char *format, ...)
{
@@ -45,7 +45,7 @@ struct exclude_struct **server_exclude_list;
exit(code);
}
int check_exclude(UNUSED(struct exclude_struct **list), UNUSED(char *name),
int check_exclude(UNUSED(struct exclude_list_struct *listp), UNUSED(char *name),
UNUSED(int name_is_dir))
{
/* This function doesn't really get called in this test context, so

View File

@@ -18,8 +18,6 @@ set -x
fromdir="$scratchdir/from"
todir="$scratchdir/to"
# TODO: I guess some systems will not have 'id', and therefore we have
# to ship or emulate it.
mygrps="`rsync_getgroups`" || fail "Can't get groups"
mkdir "$fromdir"
@@ -33,6 +31,5 @@ sleep 2
checkit "$RSYNC -rtgvvv \"$fromdir/\" \"$todir/\"" "$fromdir" "$todir"
# The script would have aborted on error, so getting here means we've won.
exit 0
# last [] may have failed but if we get here then we've won

View File

@@ -33,6 +33,5 @@ chgrp 5003 "$name2" || test_skipped "Can't chgrp (probably need root)"
checkit "$RSYNC -aHvv \"$fromdir/\" \"$todir/\"" "$fromdir" "$todir"
# The script would have aborted on error, so getting here means we've won.
exit 0
# last [] may have failed but if we get here then we've won

View File

@@ -27,5 +27,7 @@ RSYNC_CONNECT_PROG="$RSYNC --config=$conf --daemon"
export RSYNC_CONNECT_PROG
hands_setup
checkit "$RSYNC -avvz localhost::test-from/ \"$TO/\"" "$FROM" "$TO"
checkit "$RSYNC -avvvvz localhost::test-from/ \"$TO/\"" "$FROM" "$TO"
# The script would have aborted on error, so getting here means we've won.
exit 0

View File

@@ -21,5 +21,7 @@ RSYNC_CONNECT_PROG="$RSYNC --config=$conf --daemon"
export RSYNC_CONNECT_PROG
hands_setup
checkit "$RSYNC -avvz \"$FROM/\" localhost::test-to/" "$FROM" "$TO"
checkit "$RSYNC -avvvvz \"$FROM/\" localhost::test-to/" "$FROM" "$TO"
# The script would have aborted on error, so getting here means we've won.
exit 0

View File

@@ -16,14 +16,23 @@ set -x
fromdir="$scratchdir/from"
todir="$scratchdir/to"
case `id -u` in
'') ;; # If "id" failed, try to continue...
0) ;;
*) test_skipped "Rsync won't copy devices unless we're root" ;;
esac
# 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 unless root"
mknod "$fromdir/char" c 41 67 || test_skipped "Can't create char device node unless root"
mknod "$fromdir/char2" c 42 68 || test_skipped "Can't create char device node unless root"
mknod "$fromdir/char3" c 42 69 || test_skipped "Can't create char device node unless root"
mknod "$fromdir/block" b 42 69 || test_skipped "Can't create block device node unless root"
mknod "$fromdir/block2" b 42 73 || test_skipped "Can't create block device node unless root"
mknod "$fromdir/block3" b 105 73 || test_skipped "Can't create block device node unless root"
checkit "$RSYNC -aHvv \"$fromdir/\" \"$todir/\"" "$fromdir" "$todir"
# The script would have aborted on error, so getting here means we've won.
exit 0
# last [] may have failed but if we get here then we've won

View File

@@ -49,5 +49,5 @@ then
test_fail "name2 was not copied exactly once"
fi
# The script would have aborted on error, so getting here means we've won.
exit 0
# last [] may have failed but if we get here then we've won

View File

@@ -14,23 +14,36 @@
set -x
HOME="$scratchdir"
CVSIGNORE='*.junk'
export HOME CVSIGNORE
# Build some files/dirs/links to copy
fromdir="$scratchdir/from"
todir="$scratchdir/to"
chkdir="$scratchdir/chk"
echo home-cvs-exclude >"$scratchdir"/.cvsignore
makepath "$fromdir/foo/down/to/you"
makepath "$fromdir/bar/down/to/foo/too"
makepath "$fromdir/mid/for/foo/and/that/is/who"
echo kept >"$fromdir/foo/file1"
echo removed >"$fromdir/foo/file2"
echo cvsout >"$fromdir/foo/file2.old"
echo keeper >"$fromdir/bar/down/to/foo/file1"
echo cvsout >"$fromdir/bar/down/to/foo/file1.bak"
echo gone >"$fromdir/bar/down/to/foo/file3"
echo lost >"$fromdir/bar/down/to/foo/file4"
echo cvsout >"$fromdir/bar/down/to/foo/file4.junk"
echo smashed >"$fromdir/bar/down/to/foo/to"
echo cvsout >"$fromdir/bar/down/to/home-cvs-exclude"
echo cvsout >"$fromdir/mid/one-in-one-out"
echo one-in-one-out >"$fromdir/mid/.cvsignore"
echo cvsin >"$fromdir/mid/one-for-all"
echo expunged >"$fromdir/mid/for/foo/extra"
echo retained >"$fromdir/mid/for/foo/keep"
echo cvsin >"$fromdir/mid/for/one-in-one-out"
ln -s too "$fromdir/bar/down/to/foo/sym"
# Setup our test exclude/include file.
@@ -72,4 +85,21 @@ $RSYNC -av --existing --include='*/' --exclude='*' "$fromdir/" "$chkdir/"
checkit "$RSYNC -avv --exclude-from=$excl \"$fromdir/\" \"$todir/\"" "$chkdir" "$todir"
# Modify the chk dir by removing cvs-ignored files and then tweaking the dir times.
rm "$chkdir"/foo/*.old
rm "$chkdir"/bar/down/to/foo/*.bak
rm "$chkdir"/bar/down/to/foo/*.junk
rm "$chkdir"/bar/down/to/home-cvs-exclude
rm "$chkdir"/mid/one-in-one-out
$RSYNC -av --existing --include='*/' --exclude='*' "$fromdir/" "$chkdir/"
# Now, test if rsync excludes the same files, this time with --cvs-exclude
# and --delete-excluded.
checkit "$RSYNC -avvC --delete-excluded --exclude-from=$excl \
\"$fromdir/\" \"$todir/\"" "$chkdir" "$todir"
# The script would have aborted on error, so getting here means we've won.
exit 0

View File

@@ -25,4 +25,5 @@ runtest "extra data" 'checkit "$RSYNC -avH ${FROM}/ ${TO}" ${FROM}/ ${TO}'
cp ${FROM}/text ${TO}/ThisShouldGo
runtest " --delete" 'checkit "$RSYNC --delete -avH ${FROM}/ ${TO}" ${FROM}/ ${TO}'
# The script would have aborted on error, so getting here means we've won.
exit 0

View File

@@ -33,6 +33,5 @@ cp "$name2" "$name4" || fail "Can't copy file"
checkit "$RSYNC -aHvv \"$fromdir/\" \"$todir/\"" "$fromdir" "$todir"
# The script would have aborted on error, so getting here means we've won.
exit 0
# last [] may have failed but if we get here then we've won

View File

@@ -19,3 +19,6 @@ touch $LONGDIR/1 || test_skipped "unable to create files in long directory"
date > ${LONGDIR}/1
ls -la / > ${LONGDIR}/2
checkit "$RSYNC --delete -avH ${FROM}/ ${TO}" ${FROM}/ ${TO}
# The script would have aborted on error, so getting here means we've won.
exit 0

51
testsuite/merge.test Normal file
View File

@@ -0,0 +1,51 @@
#! /bin/sh
# Copyright (C) 2004 by Wayne Davison <wayned@samba.org>
# This program is distributable under the terms of the GNU GPL (see
# COPYING).
# Make sure we can merge files from multiple directories into one.
. $srcdir/testsuite/rsync.fns
set -x
# Build some files/dirs/links to copy
fromdir="$scratchdir/from"
from1dir="${fromdir}1"
from2dir="${fromdir}2"
from3dir="${fromdir}3"
todir="$scratchdir/to"
chkdir="$scratchdir/chk"
mkdir "$from1dir" "$from2dir" "$from3dir"
mkdir "$from2dir"/sub1 "$from3dir"/sub1
mkdir "$from3dir"/sub2
mkdir "$chkdir" "$chkdir"/sub1 "$chkdir"/sub2
echo "one" >"$from1dir"/one
cp -p "$from1dir"/one "$from2dir"/one
cp -p "$from1dir"/one "$from3dir"/one
echo "two" >"$from1dir"/two
echo "three" >"$from2dir"/three
echo "four" >"$from3dir"/four
echo "five" >"$from1dir"/five
echo "six" >"$from3dir"/six
echo "sub1" >"$from2dir"/sub1/uno
cp -p "$from2dir"/sub1/uno "$from3dir"/sub1/uno
echo "sub2" >"$from3dir"/sub1/dos
echo "sub3" >"$from2dir"/sub1/tres
echo "subby" >"$from3dir"/sub2/subby
cp -p "$from1dir"/one "$from1dir"/two "$from2dir"/three "$from3dir"/four "$from1dir"/five "$from3dir"/six "$chkdir"
cp -p "$from2dir"/sub1/uno "$from3dir"/sub1/dos "$from2dir"/sub1/tres "$chkdir"/sub1
cp -p "$from3dir"/sub2/subby "$chkdir"/sub2
# Get rid of any directory-time differences
$RSYNC -av --existing --include='*/' --exclude='*' "$from1dir/" "$from2dir/" "$from3dir/" "$chkdir/"
checkit "$RSYNC -aHvv \"$from1dir/\" \"$from2dir/\" \"$from3dir/\" \"$todir/\"" "$chkdir" "$todir"
# The script would have aborted on error, so getting here means we've won.
exit 0

View File

@@ -196,6 +196,7 @@ pid file = $pidfile
use chroot = no
hosts allow = localhost, 127.0.0.1
log file = $logfile
max verbosity = 9
uid = 0
gid = 0

View File

@@ -35,6 +35,5 @@ then
test_fail "absolute symlink was copied"
fi
# The script would have aborted on error, so getting here means we've won.
exit 0
# last [] may have failed but if we get here then we've one

View File

@@ -24,4 +24,5 @@ diff $diffopt "$scratchdir/slash.out" - <<EOF
/Users/Wierd Macintosh Name/// Ooh, translucent plastic
EOF
# The script would have aborted on error, so getting here means we've won.
exit 0

View File

@@ -11,9 +11,10 @@
set -x
"$TOOLDIR/wildtest" >"$scratchdir/wild.out"
"$TOOLDIR/wildtest" "$srcdir/wildtest.txt" >"$scratchdir/wild.out"
diff $diffopt "$scratchdir/wild.out" - <<EOF
No wildmatch errors found.
EOF
# The script would have aborted on error, so getting here means we've won.
exit 0

30
tls.c
View File

@@ -1,16 +1,16 @@
/* -*- c-file-style: "linux" -*-
*
* 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 version
* 2 as published by the Free Software Foundation.
*
*
* 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.
@@ -86,7 +86,7 @@ static void list_file (const char *fname)
strcpy(linkbuf, " -> ");
/* const-cast required for silly UNICOS headers */
len = readlink((char *) fname, linkbuf+4, sizeof(linkbuf) - 4);
if (len == -1)
if (len == -1)
failed("readlink", fname);
else
/* it's not nul-terminated */
@@ -99,7 +99,7 @@ static void list_file (const char *fname)
if (buf.st_mtime) {
mt = gmtime(&buf.st_mtime);
sprintf(datebuf, "%04d-%02d-%02d %02d:%02d:%02d",
mt->tm_year + 1900,
mt->tm_mon + 1,
@@ -110,16 +110,18 @@ static void list_file (const char *fname)
} else {
strcpy(datebuf, " ");
}
/* TODO: Perhaps escape special characters in fname? */
/* NB: need to pass size as a double because it might be be
* too large for a long. */
printf("%s %12.0f %6ld.%-6ld %6d %s %s%s\n",
permbuf, (double) buf.st_size,
(long) buf.st_uid, (long) buf.st_gid,
buf.st_nlink,
printf("%s ", permbuf);
if (IS_DEVICE(buf.st_mode)) {
printf("%5ld,%6ld",
(long)major(buf.st_rdev),
(long)minor(buf.st_rdev));
} else /* NB: use double for size since it might not fit in a long. */
printf("%12.0f", (double)buf.st_size);
printf(" %6ld.%-6ld %6ld %s %s%s\n",
(long)buf.st_uid, (long)buf.st_gid, (long)buf.st_nlink,
datebuf, fname, linkbuf);
}

View File

@@ -202,7 +202,7 @@ send_deflated_token(int f, int token,
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(&temp_byte,sizeof(char));
write_batch_delta_file((char *)&run_start,sizeof(run_start));
}
}
@@ -210,9 +210,10 @@ send_deflated_token(int f, int token,
write_byte(f, n);
write_byte(f, n >> 8);
if (write_batch) {
write_batch_delta_file((char *)&n,sizeof(char));
temp_byte = (char)n;
write_batch_delta_file(&temp_byte,sizeof(char));
temp_byte = (char)(n >> 8);
write_batch_delta_file(&temp_byte,sizeof(temp_byte));
write_batch_delta_file(&temp_byte,sizeof(char));
}
}
last_run_end = last_token;
@@ -285,7 +286,7 @@ send_deflated_token(int f, int token,
write_byte(f, END_FLAG);
if (write_batch) {
temp_byte = END_FLAG;
write_batch_delta_file((char *)&temp_byte,sizeof(temp_byte));
write_batch_delta_file(&temp_byte,sizeof(char));
}
} else if (token != -2) {

335
uidlist.c
View File

@@ -1,17 +1,17 @@
/*
/*
Copyright (C) Andrew Tridgell 1996
Copyright (C) Paul Mackerras 1996
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
@@ -19,12 +19,19 @@
/* handle the mapping of uid/gid and user/group names between systems.
If the source username/group does not exist on the target then use
the numeric ids. Never do any mapping for uid=0 or gid=0 as these
the numeric IDs. Never do any mapping for uid=0 or gid=0 as these
are special.
*/
#include "rsync.h"
#ifdef HAVE_GETGROUPS
# if !defined(GETGROUPS_T)
# define GETGROUPS_T gid_t
# endif
#endif
extern int verbose;
extern int preserve_uid;
extern int preserve_gid;
extern int numeric_ids;
@@ -39,24 +46,26 @@ struct idlist {
static struct idlist *uidlist;
static struct idlist *gidlist;
static struct idlist *add_list(int id, char *name)
static struct idlist *add_to_list(struct idlist **root, int id, char *name,
int id2)
{
struct idlist *list = new(struct idlist);
if (!list) out_of_memory("add_list");
list->next = NULL;
list->name = strdup(name);
if (!list->name) out_of_memory("add_list");
list->id = (int)id;
return list;
struct idlist *node = new(struct idlist);
if (!node)
out_of_memory("add_to_list");
node->next = *root;
node->name = name;
node->id = id;
node->id2 = id2;
*root = node;
return node;
}
/* turn a uid into a user name */
static char *uid_to_name(uid_t uid)
{
struct passwd *pass = getpwuid(uid);
if (pass) return(pass->pw_name);
if (pass)
return strdup(pass->pw_name);
return NULL;
}
@@ -64,14 +73,15 @@ static char *uid_to_name(uid_t uid)
static char *gid_to_name(gid_t gid)
{
struct group *grp = getgrgid(gid);
if (grp) return(grp->gr_name);
if (grp)
return strdup(grp->gr_name);
return NULL;
}
static int map_uid(int id, char *name)
{
uid_t uid;
if (name_to_uid(name, &uid) && uid != 0)
if (id != 0 && name_to_uid(name, &uid))
return uid;
return id;
}
@@ -79,113 +89,180 @@ static int map_uid(int id, char *name)
static int map_gid(int id, char *name)
{
gid_t gid;
if (name_to_gid(name, &gid) && gid != 0)
if (id != 0 && name_to_gid(name, &gid))
return gid;
return id;
}
static int is_in_group(gid_t gid)
{
#ifdef HAVE_GETGROUPS
static gid_t last_in = GID_NONE, last_out;
static int ngroups = -2;
static GETGROUPS_T *gidset;
int n;
if (gid == last_in)
return last_out;
if (ngroups < -1) {
gid_t mygid = MY_GID();
if ((ngroups = getgroups(0, NULL)) < 0)
ngroups = 0;
gidset = new_array(GETGROUPS_T, ngroups+1);
if (!gidset)
out_of_memory("is_in_group");
if (ngroups > 0)
ngroups = getgroups(ngroups, gidset);
/* The default gid might not be in the list on some systems. */
for (n = 0; n < ngroups; n++) {
if (gidset[n] == mygid)
break;
}
if (n == ngroups)
gidset[ngroups++] = mygid;
if (verbose > 3) {
int pos;
char *gidbuf = new_array(char, ngroups*21+32);
if (!gidbuf)
out_of_memory("is_in_group");
sprintf(gidbuf, "process has %d gid%s: ",
ngroups, ngroups == 1? "" : "s");
pos = strlen(gidbuf);
for (n = 0; n < ngroups; n++) {
sprintf(gidbuf+pos, " %d", (int)gidset[n]);
pos += strlen(gidbuf+pos);
}
rprintf(FINFO, "%s\n", gidbuf);
free(gidbuf);
}
}
last_in = gid;
for (n = 0; n < ngroups; n++) {
if (gidset[n] == gid)
return last_out = 1;
}
return last_out = 0;
#else
static gid_t mygid = GID_NONE;
if (mygid == GID_NONE) {
mygid = MY_GID();
if (verbose > 3)
rprintf(FINFO, "process has gid %d\n", (int)mygid);
}
return gid == mygid;
#endif
}
/* Add a uid to the list of uids. Only called on receiving side. */
static struct idlist *recv_add_uid(int id, char *name)
{
int id2 = name ? map_uid(id, name) : id;
struct idlist *node;
node = add_to_list(&uidlist, id, name, id2);
if (verbose > 3) {
rprintf(FINFO, "uid %d(%s) maps to %d\n",
id, name ? name : "", id2);
}
return node;
}
/* Add a gid to the list of gids. Only called on receiving side. */
static struct idlist *recv_add_gid(int id, char *name)
{
int id2 = name ? map_gid(id, name) : id;
struct idlist *node;
if (!am_root && !is_in_group(id2))
id2 = GID_NONE;
node = add_to_list(&gidlist, id, name, id2);
if (verbose > 3) {
rprintf(FINFO, "gid %d(%s) maps to %d\n",
id, name ? name : "", id2);
}
return node;
}
/* this function is a definate candidate for a faster algorithm */
static uid_t match_uid(uid_t uid)
{
static uid_t last_in, last_out;
struct idlist *list = uidlist;
struct idlist *list;
if (uid == last_in) return last_out;
if (uid == 0)
return 0;
if (uid == last_in)
return last_out;
last_in = uid;
while (list) {
if (list->id == (int)uid) {
last_out = (uid_t)list->id2;
return last_out;
}
list = list->next;
for (list = uidlist; list; list = list->next) {
if (list->id == (int)uid)
return last_out = (uid_t)list->id2;
}
last_out = uid;
return last_out;
return last_out = uid;
}
static gid_t match_gid(gid_t gid)
{
static gid_t last_in, last_out;
struct idlist *list = gidlist;
static gid_t last_in = GID_NONE, last_out = GID_NONE;
struct idlist *list;
if (gid == last_in) return last_out;
if (gid == GID_NONE)
return GID_NONE;
if (gid == last_in)
return last_out;
last_in = gid;
while (list) {
if (list->id == (int)gid) {
last_out = (gid_t)list->id2;
return last_out;
}
list = list->next;
for (list = gidlist; list; list = list->next) {
if (list->id == (int)gid)
return last_out = (gid_t)list->id2;
}
if (am_root)
last_out = gid;
else
last_out = (gid_t) -1;
return last_out;
list = recv_add_gid(gid, NULL);
return last_out = list->id2;
}
/* add a uid to the list of uids */
/* Add a uid to the list of uids. Only called on sending side. */
void add_uid(uid_t uid)
{
struct idlist *list = uidlist;
char *name;
struct idlist *list;
if (numeric_ids) return;
/* don't map root */
if (uid==0) return;
if (!list) {
if (!(name = uid_to_name(uid))) return;
uidlist = add_list((int)uid, name);
if (uid == 0) /* don't map root */
return;
for (list = uidlist; list; list = list->next) {
if (list->id == (int)uid)
return;
}
while (list->next) {
if (list->id == (int)uid) return;
list = list->next;
}
if (list->id == (int)uid) return;
if (!(name = uid_to_name(uid))) return;
list->next = add_list((int)uid, name);
add_to_list(&uidlist, (int)uid, uid_to_name(uid), 0);
}
/* add a gid to the list of gids */
/* Add a gid to the list of gids. Only called on sending side. */
void add_gid(gid_t gid)
{
struct idlist *list = gidlist;
char *name;
struct idlist *list;
if (numeric_ids) return;
/* don't map root */
if (gid==0) return;
if (!list) {
if (!(name = gid_to_name(gid))) return;
gidlist = add_list((int)gid, name);
if (gid == 0) /* don't map root */
return;
for (list = gidlist; list; list = list->next) {
if (list->id == (int)gid)
return;
}
while (list->next) {
if (list->id == (int)gid) return;
list = list->next;
}
if (list->id == (int)gid) return;
if (!(name = gid_to_name(gid))) return;
list->next = add_list((int)gid, name);
add_to_list(&gidlist, (int)gid, gid_to_name(gid), 0);
}
@@ -194,102 +271,80 @@ void send_uid_list(int f)
{
struct idlist *list;
if (numeric_ids) return;
if (numeric_ids)
return;
if (preserve_uid) {
int len;
/* we send sequences of uid/byte-length/name */
list = uidlist;
while (list) {
int len = strlen(list->name);
for (list = uidlist; list; list = list->next) {
if (!list->name)
continue;
len = strlen(list->name);
write_int(f, list->id);
write_byte(f, len);
write_buf(f, list->name, len);
list = list->next;
}
/* terminate the uid list with a 0 uid. We explicitly exclude
0 from the list */
* 0 from the list */
write_int(f, 0);
}
if (preserve_gid) {
list = gidlist;
while (list) {
int len = strlen(list->name);
int len;
for (list = gidlist; list; list = list->next) {
if (!list->name)
continue;
len = strlen(list->name);
write_int(f, list->id);
write_byte(f, len);
write_buf(f, list->name, len);
list = list->next;
}
write_int(f, 0);
}
}
/* recv a complete uid/gid mapping from the peer and map the uid/gid
in the file list to local names */
* in the file list to local names */
void recv_uid_list(int f, struct file_list *flist)
{
int id, i;
char *name;
struct idlist *list;
if (numeric_ids) return;
if (preserve_uid) {
if (preserve_uid && !numeric_ids) {
/* read the uid list */
list = uidlist;
id = read_int(f);
while (id != 0) {
while ((id = read_int(f)) != 0) {
int len = read_byte(f);
name = new_array(char, len+1);
if (!name) out_of_memory("recv_uid_list");
if (!name)
out_of_memory("recv_uid_list");
read_sbuf(f, name, len);
if (!list) {
uidlist = add_list(id, name);
list = uidlist;
} else {
list->next = add_list(id, name);
list = list->next;
}
list->id2 = map_uid(id, name);
free(name);
id = read_int(f);
recv_add_uid(id, name); /* node keeps name's memory */
}
}
if (preserve_gid) {
/* and the gid list */
list = gidlist;
id = read_int(f);
while (id != 0) {
if (preserve_gid && !numeric_ids) {
/* read the gid list */
while ((id = read_int(f)) != 0) {
int len = read_byte(f);
name = new_array(char, len+1);
if (!name) out_of_memory("recv_uid_list");
if (!name)
out_of_memory("recv_uid_list");
read_sbuf(f, name, len);
if (!list) {
gidlist = add_list(id, name);
list = gidlist;
} else {
list->next = add_list(id, name);
list = list->next;
}
list->id2 = map_gid(id, name);
free(name);
id = read_int(f);
recv_add_gid(id, name); /* node keeps name's memory */
}
}
if (!(am_root && preserve_uid) && !preserve_gid) return;
/* now convert the uid/gid of all files in the list to the mapped
uid/gid */
for (i=0;i<flist->count;i++) {
if (am_root && preserve_uid && flist->files[i]->uid != 0) {
* uid/gid */
if (am_root && preserve_uid && !numeric_ids) {
for (i = 0; i < flist->count; i++)
flist->files[i]->uid = match_uid(flist->files[i]->uid);
}
if (preserve_gid && flist->files[i]->gid != 0) {
}
if (preserve_gid && (!am_root || !numeric_ids)) {
for (i = 0; i < flist->count; i++)
flist->files[i]->gid = match_gid(flist->files[i]->gid);
}
}
}

350
util.c
View File

@@ -1,19 +1,19 @@
/* -*- c-file-style: "linux" -*-
*
* Copyright (C) 1996-2000 by Andrew Tridgell
*
* Copyright (C) 1996-2000 by Andrew Tridgell
* 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.
@@ -22,12 +22,13 @@
/**
* @file
*
* Utilities used in rsync
* Utilities used in rsync
**/
#include "rsync.h"
extern int verbose;
extern struct exclude_list_struct server_exclude_list;
int sanitize_paths = 0;
@@ -67,7 +68,7 @@ void set_blocking(int fd)
/**
* Create a file descriptor pair - like pipe() but use socketpair if
* possible (because of blocking issues on pipes).
*
*
* Always set non-blocking.
*/
int fd_pair(int fd[2])
@@ -111,14 +112,14 @@ void print_child_argv(char **cmd)
void out_of_memory(char *str)
{
rprintf(FERROR,"ERROR: out of memory in %s\n",str);
exit_cleanup(RERR_MALLOC);
rprintf(FERROR, "ERROR: out of memory in %s\n", str);
exit_cleanup(RERR_MALLOC);
}
void overflow(char *str)
{
rprintf(FERROR,"ERROR: buffer overflow in %s\n",str);
exit_cleanup(RERR_MALLOC);
rprintf(FERROR, "ERROR: buffer overflow in %s\n", str);
exit_cleanup(RERR_MALLOC);
}
@@ -134,10 +135,10 @@ int set_modtime(char *fname, time_t modtime)
fname, (long) modtime,
asctime(localtime(&modtime)));
}
{
#ifdef HAVE_UTIMBUF
struct utimbuf tbuf;
struct utimbuf tbuf;
tbuf.actime = time(NULL);
tbuf.modtime = modtime;
return utime(fname,&tbuf);
@@ -167,13 +168,15 @@ int create_directory_path(char *fname, int base_umask)
{
char *p;
while (*fname == '/') fname++;
while (strncmp(fname,"./",2)==0) fname += 2;
while (*fname == '/')
fname++;
while (strncmp(fname, "./", 2) == 0)
fname += 2;
p = fname;
while ((p=strchr(p,'/'))) {
while ((p = strchr(p,'/')) != NULL) {
*p = 0;
do_mkdir(fname, 0777 & ~base_umask);
do_mkdir(fname, 0777 & ~base_umask);
*p = '/';
p++;
}
@@ -194,15 +197,13 @@ int create_directory_path(char *fname, int base_umask)
static int full_write(int desc, char *ptr, size_t len)
{
int total_written;
total_written = 0;
while (len > 0) {
int written = write (desc, ptr, len);
int written = write(desc, ptr, len);
if (written < 0) {
#ifdef EINTR
if (errno == EINTR)
continue;
#endif
return written;
}
total_written += written;
@@ -227,18 +228,14 @@ static int full_write(int desc, char *ptr, size_t len)
static int safe_read(int desc, char *ptr, size_t len)
{
int n_chars;
if (len == 0)
return len;
#ifdef EINTR
do {
n_chars = read(desc, ptr, len);
} while (n_chars < 0 && errno == EINTR);
#else
n_chars = read(desc, ptr, len);
#endif
return n_chars;
}
@@ -256,40 +253,50 @@ int copy_file(char *source, char *dest, mode_t mode)
ifd = do_open(source, O_RDONLY, 0);
if (ifd == -1) {
rprintf(FERROR,"open %s: %s\n",
source,strerror(errno));
full_fname(source), strerror(errno));
return -1;
}
if (robust_unlink(dest) && errno != ENOENT) {
rprintf(FERROR,"unlink %s: %s\n",
dest,strerror(errno));
full_fname(dest), strerror(errno));
return -1;
}
ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode);
if (ofd == -1) {
rprintf(FERROR,"open %s: %s\n",
dest,strerror(errno));
full_fname(dest), strerror(errno));
close(ifd);
return -1;
}
while ((len = safe_read(ifd, buf, sizeof(buf))) > 0) {
while ((len = safe_read(ifd, buf, sizeof buf)) > 0) {
if (full_write(ofd, buf, len) < 0) {
rprintf(FERROR,"write %s: %s\n",
dest,strerror(errno));
full_fname(dest), strerror(errno));
close(ifd);
close(ofd);
return -1;
}
}
close(ifd);
close(ofd);
if (len < 0) {
rprintf(FERROR,"read %s: %s\n",
source,strerror(errno));
rprintf(FERROR, "read %s: %s\n",
full_fname(source), strerror(errno));
close(ifd);
close(ofd);
return -1;
}
if (close(ifd) < 0) {
rprintf(FINFO, "close failed on %s: %s\n",
full_fname(source), strerror(errno));
}
if (close(ofd) < 0) {
rprintf(FERROR, "close failed on %s: %s\n",
full_fname(dest), strerror(errno));
return -1;
}
@@ -320,17 +327,15 @@ int robust_unlink(char *fname)
char path[MAXPATHLEN];
rc = do_unlink(fname);
if ((rc == 0) || (errno != ETXTBSY))
if (rc == 0 || errno != ETXTBSY)
return rc;
strlcpy(path, fname, MAXPATHLEN);
if ((pos = strlcpy(path, fname, MAXPATHLEN)) >= MAXPATHLEN)
pos = MAXPATHLEN - 1;
pos = strlen(path);
while((path[--pos] != '/') && (pos >= 0))
;
++pos;
strlcpy(&path[pos], ".rsync", MAXPATHLEN-pos);
pos += sizeof(".rsync")-1;
while (pos > 0 && path[pos-1] != '/')
pos--;
pos += strlcpy(path+pos, ".rsync", MAXPATHLEN-pos);
if (pos > (MAXPATHLEN-MAX_RENAMES_DIGITS-1)) {
errno = ETXTBSY;
@@ -343,7 +348,7 @@ int robust_unlink(char *fname)
sprintf(&path[pos], "%03d", counter);
if (++counter >= MAX_RENAMES)
counter = 1;
} while (((rc = access(path, 0)) == 0) && (counter != start));
} while ((rc = access(path, 0)) == 0 && counter != start);
if (verbose > 0) {
rprintf(FINFO,"renaming %s to %s because of text busy\n",
@@ -359,18 +364,33 @@ int robust_unlink(char *fname)
#endif
}
int robust_rename(char *from, char *to)
/* Returns 0 on success, -1 on most errors, and -2 if we got an error
* trying to copy the file across file systems. */
int robust_rename(char *from, char *to, int mode)
{
#ifndef ETXTBSY
return do_rename(from, to);
#else
int rc = do_rename(from, to);
if ((rc == 0) || (errno != ETXTBSY))
return rc;
if (robust_unlink(to) != 0)
return -1;
return do_rename(from, to);
int tries = 4;
while (tries--) {
if (do_rename(from, to) == 0)
return 0;
switch (errno) {
#ifdef ETXTBSY
case ETXTBSY:
if (robust_unlink(to) != 0)
return -1;
break;
#endif
case EXDEV:
if (copy_file(from, to, mode) != 0)
return -2;
do_unlink(from);
return 0;
default:
return -1;
}
}
return -1;
}
@@ -381,7 +401,7 @@ static int num_pids;
pid_t do_fork(void)
{
pid_t newpid = fork();
if (newpid != 0 && newpid != -1) {
all_pids[num_pids++] = newpid;
}
@@ -455,19 +475,18 @@ int lock_range(int fd, int offset, int len)
lock.l_start = offset;
lock.l_len = len;
lock.l_pid = 0;
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) {
if (server_exclude_list.head) {
for (s = arg; (s = strchr(s, '/')) != NULL; ) {
*s = '\0';
if (check_exclude(server_exclude_list, arg, 1)) {
if (check_exclude(&server_exclude_list, arg, 1) < 0) {
/* We must leave arg truncated! */
return 1;
}
@@ -496,7 +515,7 @@ static void glob_expand_one(char *s, char **argv, int *argc, int maxargs)
sanitize_path(s, NULL);
}
memset(&globbuf, 0, sizeof(globbuf));
memset(&globbuf, 0, sizeof globbuf);
if (!exclude_server_path(s))
glob(s, 0, NULL, &globbuf);
if (globbuf.gl_pathc == 0) {
@@ -504,13 +523,15 @@ static void glob_expand_one(char *s, char **argv, int *argc, int maxargs)
globfree(&globbuf);
return;
}
for (i=0; i<(maxargs - (*argc)) && i < (int) globbuf.gl_pathc;i++) {
if (i == 0) free(s);
argv[(*argc) + i] = strdup(globbuf.gl_pathv[i]);
if (!argv[(*argc) + i]) out_of_memory("glob_expand");
for (i = 0; i < maxargs - *argc && i < (int)globbuf.gl_pathc; i++) {
if (i == 0)
free(s);
argv[*argc + i] = strdup(globbuf.gl_pathv[i]);
if (!argv[*argc + i])
out_of_memory("glob_expand");
}
globfree(&globbuf);
(*argc) += i;
*argc += i;
#endif
}
@@ -534,14 +555,15 @@ void glob_expand(char *base1, char **argv, int *argc, int maxargs)
base_len++;
q = s;
while ((p = strstr(q,base)) && ((*argc) < maxargs)) {
while ((p = strstr(q,base)) != NULL && *argc < maxargs) {
/* split it at this point */
*p = 0;
glob_expand_one(q, argv, argc, maxargs);
q = p + base_len;
}
if (*q && (*argc < maxargs)) glob_expand_one(q, argv, argc, maxargs);
if (*q && *argc < maxargs)
glob_expand_one(q, argv, argc, maxargs);
free(s);
free(base);
@@ -559,6 +581,58 @@ void strlower(char *s)
}
}
/* Join strings p1 & p2 into "dest" with a guaranteed '/' between them. (If
* p1 ends with a '/', no extra '/' is inserted.) Returns the length of both
* strings + 1 (if '/' was inserted), regardless of whether the null-terminated
* string fits into destsize. */
size_t pathjoin(char *dest, size_t destsize, const char *p1, const char *p2)
{
size_t len = strlcpy(dest, p1, destsize);
if (len < destsize - 1) {
if (!len || dest[len-1] != '/')
dest[len++] = '/';
if (len < destsize - 1)
len += strlcpy(dest + len, p2, destsize - len);
else {
dest[len] = '\0';
len += strlen(p2);
}
}
else
len += strlen(p2) + 1; /* Assume we'd insert a '/'. */
return len;
}
/* Join any number of strings together, putting them in "dest". The return
* value is the length of all the strings, regardless of whether the null-
* terminated whole fits in destsize. Your list of string pointers must end
* with a NULL to indicate the end of the list. */
size_t stringjoin(char *dest, size_t destsize, ...)
{
va_list ap;
size_t len, ret = 0;
const char *src;
va_start(ap, destsize);
while (1) {
if (!(src = va_arg(ap, const char *)))
break;
len = strlen(src);
ret += len;
if (destsize > 1) {
if (len >= destsize)
len = destsize - 1;
memcpy(dest, src, len);
destsize -= len;
dest += len;
}
}
*dest = '\0';
va_end(ap);
return ret;
}
void clean_fname(char *name)
{
char *p;
@@ -570,7 +644,7 @@ void clean_fname(char *name)
while (modified) {
modified = 0;
if ((p=strstr(name,"/./"))) {
if ((p = strstr(name,"/./")) != NULL) {
modified = 1;
while (*p) {
p[0] = p[2];
@@ -578,7 +652,7 @@ void clean_fname(char *name)
}
}
if ((p=strstr(name,"//"))) {
if ((p = strstr(name,"//")) != NULL) {
modified = 1;
while (*p) {
p[0] = p[1];
@@ -586,14 +660,14 @@ void clean_fname(char *name)
}
}
if (strncmp(p=name,"./",2) == 0) {
if (strncmp(p = name, "./", 2) == 0) {
modified = 1;
do {
p[0] = p[2];
} while (*p++);
}
l = strlen(p=name);
l = strlen(p = name);
if (l > 1 && p[l-1] == '/') {
modified = 1;
p[l-1] = 0;
@@ -652,7 +726,7 @@ void sanitize_path(char *p, char *reldir)
* both p (and sanp if the original had a slash) should
* always be left pointing after a slash
*/
if ((*p == '.') && ((*(p+1) == '/') || (*(p+1) == '\0'))) {
if (*p == '.' && (p[1] == '/' || p[1] == '\0')) {
/* skip "." component */
while (*++p == '/') {
/* skip following slashes */
@@ -661,10 +735,9 @@ void sanitize_path(char *p, char *reldir)
continue;
}
allowdotdot = 0;
if ((*p == '.') && (*(p+1) == '.') &&
((*(p+2) == '/') || (*(p+2) == '\0'))) {
if (*p == '.' && p[1] == '.' && (p[2] == '/' || p[2] == '\0')) {
/* ".." component followed by slash or end */
if ((depth > 0) && (sanp == start)) {
if (depth > 0 && sanp == start) {
/* allow depth levels of .. at the beginning */
--depth;
allowdotdot = 1;
@@ -675,7 +748,7 @@ void sanitize_path(char *p, char *reldir)
if (sanp != start) {
/* back up sanp one level */
--sanp; /* now pointing at slash */
while ((sanp > start) && (*(sanp - 1) != '/')) {
while (sanp > start && sanp[-1] != '/') {
/* skip back up to slash */
sanp--;
}
@@ -686,7 +759,7 @@ void sanitize_path(char *p, char *reldir)
while (1) {
/* copy one component through next slash */
*sanp++ = *p++;
if ((*p == '\0') || (*(p-1) == '/')) {
if (*p == '\0' || p[-1] == '/') {
while (*p == '/') {
/* skip multiple slashes */
p++;
@@ -699,7 +772,7 @@ void sanitize_path(char *p, char *reldir)
start = sanp;
}
}
if ((sanp == start) && !allowdotdot) {
if (sanp == start && !allowdotdot) {
/* ended up with nothing, so put in "." component */
/*
* note that the !allowdotdot doesn't prevent this from
@@ -712,59 +785,100 @@ void sanitize_path(char *p, char *reldir)
*sanp = '\0';
}
/* Works much like sanitize_path(), with these differences: (1) a new buffer
* is allocated for the sanitized path rather than modifying it in-place; (2)
* a leading slash gets transformed into the rootdir value (which can be empty
* or NULL if you just want the slash to get dropped); (3) no "reldir" can be
* specified. */
char *alloc_sanitize_path(const char *path, const char *rootdir)
{
char *buf;
int rlen, plen = strlen(path);
if (*path == '/' && rootdir) {
rlen = strlen(rootdir);
if (rlen == 1)
path++;
} else
rlen = 0;
if (!(buf = new_array(char, rlen + plen + 1)))
out_of_memory("alloc_sanitize_path");
if (rlen)
memcpy(buf, rootdir, rlen);
memcpy(buf + rlen, path, plen + 1);
if (rlen > 1)
rlen++;
sanitize_path(buf + rlen, NULL);
if (rlen && buf[rlen] == '.' && buf[rlen+1] == '\0') {
if (rlen > 1)
rlen--;
buf[rlen] = '\0';
}
return buf;
}
char curr_dir[MAXPATHLEN];
unsigned int curr_dir_len;
/**
* Like chdir() but can be reversed with pop_dir() if @p save is set.
* It is also much faster as it remembers where we have been.
* Like chdir(), but it keeps track of the current directory (in the
* global "curr_dir"), and ensures that the path size doesn't overflow.
* Also cleans the path using the clean_fname() function.
**/
char *push_dir(char *dir, int save)
int push_dir(char *dir)
{
char *ret = curr_dir;
static int initialised;
unsigned int len;
if (!initialised) {
initialised = 1;
getcwd(curr_dir, sizeof(curr_dir)-1);
getcwd(curr_dir, sizeof curr_dir - 1);
curr_dir_len = strlen(curr_dir);
}
if (!dir) return NULL; /* this call was probably just to initialize */
if (!dir) /* this call was probably just to initialize */
return 0;
if (chdir(dir)) return NULL;
len = strlen(dir);
if (len == 1 && *dir == '.')
return 1;
if (save) {
ret = strdup(curr_dir);
}
if ((*dir == '/' ? len : curr_dir_len + 1 + len) >= sizeof curr_dir)
return 0;
if (chdir(dir))
return 0;
if (*dir == '/') {
strlcpy(curr_dir, dir, sizeof(curr_dir));
} else if (dir[0] != '.' || dir[1] != '\0') {
strlcat(curr_dir,"/", sizeof(curr_dir));
strlcat(curr_dir,dir, sizeof(curr_dir));
memcpy(curr_dir, dir, len + 1);
curr_dir_len = len;
} else {
curr_dir[curr_dir_len++] = '/';
memcpy(curr_dir + curr_dir_len, dir, len + 1);
curr_dir_len += len;
}
clean_fname(curr_dir);
return ret;
return 1;
}
/** Reverse a push_dir() call */
/**
* Reverse a push_dir() call. You must pass in an absolute path
* that was copied from a prior value of "curr_dir".
**/
int pop_dir(char *dir)
{
int ret;
if (chdir(dir))
return 0;
ret = chdir(dir);
if (ret) {
free(dir);
return ret;
}
curr_dir_len = strlcpy(curr_dir, dir, sizeof curr_dir);
if (curr_dir_len >= sizeof curr_dir)
curr_dir_len = sizeof curr_dir - 1;
strlcpy(curr_dir, dir, sizeof(curr_dir));
free(dir);
return 0;
return 1;
}
/**
@@ -823,7 +937,7 @@ int u_strcmp(const char *cs1, const char *cs2)
while (*s1 && *s2 && (*s1 == *s2)) {
s1++; s2++;
}
return (int)*s1 - (int)*s2;
}
@@ -864,7 +978,7 @@ int unsafe_symlink(const char *dest, const char *src)
/* find out what our safety margin is */
for (name = src; (slash = strchr(name, '/')) != 0; name = slash+1) {
if (strncmp(name, "../", 3) == 0) {
depth=0;
depth = 0;
} else if (strncmp(name, "./", 2) == 0) {
/* nothing */
} else {
@@ -902,9 +1016,9 @@ char *timestring(time_t t)
struct tm *tm = localtime(&t);
#ifdef HAVE_STRFTIME
strftime(TimeBuf,sizeof(TimeBuf)-1,"%Y/%m/%d %T",tm);
strftime(TimeBuf, sizeof TimeBuf - 1, "%Y/%m/%d %H:%M:%S", tm);
#else
strlcpy(TimeBuf, asctime(tm), sizeof(TimeBuf));
strlcpy(TimeBuf, asctime(tm), sizeof TimeBuf);
#endif
if (TimeBuf[strlen(TimeBuf)-1] == '\n') {
@@ -923,21 +1037,21 @@ char *timestring(time_t t)
**/
int msleep(int t)
{
int tdiff=0;
struct timeval tval,t1,t2;
int tdiff = 0;
struct timeval tval, t1, t2;
gettimeofday(&t1, NULL);
gettimeofday(&t2, NULL);
while (tdiff < t) {
tval.tv_sec = (t-tdiff)/1000;
tval.tv_usec = 1000*((t-tdiff)%1000);
errno = 0;
select(0,NULL,NULL, NULL, &tval);
gettimeofday(&t2, NULL);
tdiff = (t2.tv_sec - t1.tv_sec)*1000 +
tdiff = (t2.tv_sec - t1.tv_sec)*1000 +
(t2.tv_usec - t1.tv_usec)/1000;
}
@@ -983,7 +1097,7 @@ int _Insure_trap_error(int a1, int a2, int a3, int a4, int a5, int a6)
int ret;
char *cmd;
asprintf(&cmd, "/usr/X11R6/bin/xterm -display :0 -T Panic -n Panic -e /bin/sh -c 'cat /tmp/ierrs.*.%d ; gdb /proc/%d/exe %d'",
asprintf(&cmd, "/usr/X11R6/bin/xterm -display :0 -T Panic -n Panic -e /bin/sh -c 'cat /tmp/ierrs.*.%d ; gdb /proc/%d/exe %d'",
getpid(), getpid(), getpid());
if (!fn) {

View File

@@ -19,9 +19,6 @@ int wildmatch_errors = 0;
typedef char bool;
#define false 0
#define true 1
int output_iterations = 0;
static struct poptOption long_options[] = {
@@ -84,8 +81,14 @@ main(int argc, char **argv)
}
}
if ((fp = fopen("wildtest.txt", "r")) == NULL) {
fprintf(stderr, "Unable to open wildtest.txt.\n");
argv = (char**)poptGetArgs(pc);
if (!argv || argv[1]) {
fprintf(stderr, "Usage: wildtest TESTFILE\n");
exit(1);
}
if ((fp = fopen(*argv, "r")) == NULL) {
fprintf(stderr, "Unable to open %s\n", *argv);
exit(1);
}
@@ -104,8 +107,8 @@ main(int argc, char **argv)
if (*++s != ' ' && *s != '\t')
flag[i] = -1;
if (flag[i] < 0) {
fprintf(stderr, "Invalid flag syntax on line %d of wildtest.txt:%s\n",
line, buf);
fprintf(stderr, "Invalid flag syntax on line %d of %s:\n%s",
line, *argv, buf);
exit(1);
}
while (*++s == ' ' || *s == '\t') {}
@@ -116,16 +119,16 @@ main(int argc, char **argv)
string[i] = s;
while (*s && *s != quote) s++;
if (!*s) {
fprintf(stderr, "Unmatched quote on line %d of wildtest.txt:%s\n",
line, buf);
fprintf(stderr, "Unmatched quote on line %d of %s:\n%s",
line, *argv, buf);
exit(1);
}
end[i] = s;
}
else {
if (!*s || *s == '\n') {
fprintf(stderr, "Not enough strings on line %d of wildtest.txt:%s\n",
line, buf);
fprintf(stderr, "Not enough strings on line %d of %s:\n%s",
line, *argv, buf);
exit(1);
}
string[i] = s;