Compare commits

..

641 Commits

Author SHA1 Message Date
Wayne Davison
44ae628c59 Preparing for release of 3.0.0pre2 2007-10-12 00:09:19 +00:00
Wayne Davison
44a7ba4587 Tweaked a couple minor things. 2007-10-12 00:07:28 +00:00
Wayne Davison
44c4492acf Conditionalize the call to setup_iconv(). 2007-10-10 19:24:35 +00:00
Wayne Davison
609e6dda6b - Use the new *_CONTENT_DIR flag names (was *_XFER_DIR).
- Check the FLAG_IMPLIED_DIR flag to find implied dirs.
- Expect flagged implied dirs for all protocol 30 transfers.
2007-10-08 18:02:11 +00:00
Wayne Davison
3f30927214 - Mark implied dirs with FLAG_IMPLIED_DIR.
- Use the new *_CONTENT_DIR flag names (was *_XFER_DIR).
- Send implied dirs with XMIT_TOP_DIR | XMIT_NO_CONTENT_DIR.
- All protocol 30 transfers send flagged implied dirs.
2007-10-08 18:02:07 +00:00
Wayne Davison
ae11e4ee2d - Added a flag for implied dirs: FLAG_IMPLIED_DIR.
- Changed the *_XFER_DIR flags to *_CONTENT_DIR flags.
- Increment SUBPROTOCOL_VERSION.
2007-10-08 18:02:03 +00:00
Wayne Davison
b61665d5b6 Reposition the call to setup_iconv() so that it gets called only once
is a local_server copy, and so that arg-parsing code doesn't interfere
with the sending of a remote charset value.
2007-10-07 20:43:49 +00:00
Wayne Davison
38943d29d3 Improved on the list-only fix and on the other similar checks that want
to ignore implied dirs that are actually present in the file list
when inc_recurse is active and --no-implied-dirs was specified.
2007-10-07 07:18:49 +00:00
Wayne Davison
ff0284ddc4 - Simplified the code in recv_file_entry() for protocol 30.
- Simplified the flag setting in send1extra since we know that
  recurse is set.
- Make sure that FLAG_XFER_DIR is unset for a non-dot-dir when
  recurse is not set.
- The --relative code wasn't setting is_dot_dir enough.
2007-10-07 07:18:45 +00:00
Wayne Davison
3f65576881 Mention how --list-only w/o -r now abandons an old kluge. 2007-10-07 04:04:57 +00:00
Wayne Davison
3caf40356d We now send -d to the server for a list-only transfer w/o -r (rather
than sending -r with a kluged exclude).
2007-10-07 03:52:28 +00:00
Wayne Davison
26bbb6aa4b Set xfer_dirs when we set list_only. 2007-10-07 03:52:24 +00:00
Wayne Davison
bf66c2da14 Got rid of some old exclude trickery for --list-only w/o -r. 2007-10-07 03:52:20 +00:00
Wayne Davison
65f6b6b0ef Got rid of a useless list_only tweak. 2007-10-07 03:52:17 +00:00
Wayne Davison
983f647c7e Fix list-only output of dirs w/--relative but w/o --recursive. 2007-10-07 03:29:04 +00:00
Wayne Davison
14dfad3873 A couple tweaks to the AIX ACL code. 2007-10-05 20:47:18 +00:00
Wayne Davison
215465713b Make sure ICONV_OPTION is unset if we didn't find iconv_open()
and iconv.h.
2007-10-05 20:40:36 +00:00
Wayne Davison
6be5ac61bd Simplified a SMB_ACL_NEED_SORT conditional because some preprocessors
couldn't handle an #if embedded in a macro.
2007-10-05 02:45:09 +00:00
Wayne Davison
90c71caeb3 The hpux_count_obj() function should have been declared with a
void return type.
2007-10-05 02:30:39 +00:00
Wayne Davison
d46b5646c6 A few more improvements and some reshuffling. 2007-10-05 02:22:51 +00:00
Wayne Davison
da564b51a1 Preparing for release of 3.0.0pre1 2007-10-05 00:45:13 +00:00
Wayne Davison
f89617f7f2 One more tweak. 2007-10-05 00:41:38 +00:00
Wayne Davison
0f8984ed78 The latest changes. 2007-10-01 06:13:16 +00:00
Wayne Davison
306847ea67 Mention that we abort if the pid file exists. 2007-10-01 02:32:54 +00:00
Wayne Davison
d4eba300c9 The lp_load() function doesn't fudge the pszFname arg anymore. 2007-10-01 02:25:58 +00:00
Wayne Davison
dd589118d0 - Set config_file to a default filename if it is NULL.
- Changed create_pid_file() to fail if the pidfile already exists,
  which makes the daemon exit with an error.
- Output errors about a failure to open the config file or the lock
  file to (a still open) stderr.
- We now notice (and complain) if fork() fails.
2007-10-01 02:25:54 +00:00
Wayne Davison
f92e15efd5 Mention the latest way to specify multiple remote args. 2007-09-30 07:46:28 +00:00
Wayne Davison
4f3c1df6c3 Made list more complete. 2007-09-30 07:34:33 +00:00
Wayne Davison
eb8f5c74e1 Got rid of some SPACE-TAB sequencs in the indentation. 2007-09-30 07:30:48 +00:00
Wayne Davison
a960239f39 Allow additional remote args to contain an identical hostname instead
of requiring it to be empty.  This allows for the easy use of braces:
rsync -av host:file{1,2} /dest/
2007-09-30 07:14:16 +00:00
Wayne Davison
5621e5105a Moved become_daemon() into clientserver.c. 2007-09-30 06:57:12 +00:00
Wayne Davison
a1d2685b08 - Moved become_daemon() here from socket.c and made it static.
- Call lp_load() before we call become_daemon().
- Output an error to stderr if we fail to open/parse the config file.
- Added a create_pid_file() static function and call it earlier in
  the startup sequence.
2007-09-30 06:57:07 +00:00
Wayne Davison
0f6b4909db Improved --acls, --xattrs, and --fake-super. 2007-09-29 17:01:01 +00:00
Wayne Davison
b0ca7d2500 Specify a better SMB_ACL_VALID_NAME_BITS value for OS X. 2007-09-29 16:06:40 +00:00
Wayne Davison
7ed6bc53b9 Added get_xattr_acl(), set_xattr_acl(), and del_def_xattr_acl(). 2007-09-29 16:06:37 +00:00
Wayne Davison
f57ab2f718 When running with --fake-super, get/put ACLs from/to an xattr and don't
range-check the incoming values.
2007-09-29 16:06:34 +00:00
Wayne Davison
5ebb7935d2 Tweaked a variable name. 2007-09-29 04:35:26 +00:00
Wayne Davison
c50a9076e1 Added support for OS X testing using chmod +a and ls. 2007-09-29 02:26:23 +00:00
Wayne Davison
d417c51669 - Added OS X ACL support.
- Simplified some of the ge/set calling sequences.
- Got rid of SMB_ACL_PERMSET_T.
2007-09-28 21:54:11 +00:00
Wayne Davison
5b934f5133 Added OS X ACL support, using slightly tweaked sys_acl_*()
functions.
2007-09-28 21:54:07 +00:00
Wayne Davison
49ea69b3ff We enable ACL compilation on OS X by default now. 2007-09-28 21:54:01 +00:00
Wayne Davison
578219bed5 Determine the previous version number in a more reasonable fashion. 2007-09-26 17:43:57 +00:00
Wayne Davison
2e4a3d17b4 Some improvements and fixes for the upcoming release. 2007-09-26 14:57:52 +00:00
Wayne Davison
b4b24520f6 Added (conditional) include of stdint.h. 2007-09-23 22:31:14 +00:00
Wayne Davison
13710874ce Changed "statx" to "stat_x" to try to work around a build problem on AIX. 2007-09-23 22:19:55 +00:00
Wayne Davison
7341ee2dfd Fixed a crash bug in get_local_name() when the file list is empty. 2007-09-23 21:54:03 +00:00
Wayne Davison
e0cfd15bcc Fixed a glitch in the sending of mount-point dirs in inc_recurse mode. 2007-09-23 21:46:51 +00:00
Wayne Davison
5a47354882 Added a stub function for make_bak_dir(). 2007-09-23 21:05:15 +00:00
Wayne Davison
f5b532b144 Added an option to copy_file() that tells it to try to make a
backup directory if the open of the dest file fails.
2007-09-23 21:03:46 +00:00
Wayne Davison
c0dba635ba The --inplace code now properly handles creating a backup when
the --whole-file and/or --read-batch options are specified.
2007-09-23 21:03:41 +00:00
Wayne Davison
e1ac7791fe Changed make_bak_dir() to take a const char *. 2007-09-23 21:03:38 +00:00
Wayne Davison
5b3f6a2730 Use make_bak_dir() if we get ENOENT while trying to open an
inplace backup file.
2007-09-23 19:45:22 +00:00
Wayne Davison
f203266889 Made make_bak_dir() global. 2007-09-23 19:45:19 +00:00
Wayne Davison
21914d8135 Made clean_flist() only duplicate *_DIR_* flags on a dropped dir
when the kept entry is also a dir.
2007-09-23 19:45:00 +00:00
Wayne Davison
200aec7db4 Avoid a checker warning about unfreed memory. 2007-09-23 19:10:10 +00:00
Wayne Davison
a15c4b38b5 Fix a glitch in the handling of the last path element in a -R path
with a trailing slash.
2007-09-23 16:02:33 +00:00
Wayne Davison
40e383765a - Don't allow -x to drop implied directories.
- Improved the code that tries to avoid scanning the same dir
  twice in a row to not drop any relnamecache entries.
2007-09-23 15:46:11 +00:00
Wayne Davison
5441088298 Added the relnamecache structure and improved some variable names. 2007-09-23 14:35:12 +00:00
Wayne Davison
d0a6cdb62e Make sure that the dirs we are merging have the same timestamps. 2007-09-23 02:18:57 +00:00
Wayne Davison
19531e1f74 Got rid of some unneeded externs. 2007-09-23 02:03:20 +00:00
Wayne Davison
6f0805f564 Moved list-only output from flist.c to generator.c so that it works
properly even in inc_recurse mode.  Got rid of double output, weird
output order, and outputting of implied dirs w/--no-implied-dirs.
2007-09-23 02:00:53 +00:00
Wayne Davison
6191429b50 Added a missing "void" to the arg-spec of setup_iconv(). 2007-09-23 01:18:03 +00:00
Wayne Davison
89b76bac1f Added a test to make sure that merging relative items continues to
work right.
2007-09-23 00:30:40 +00:00
Wayne Davison
0758b2db30 Document the change to how --releative works. 2007-09-22 22:57:50 +00:00
Wayne Davison
74db1f1498 Always send implied dirs as dirs. 2007-09-22 22:37:52 +00:00
Wayne Davison
4f802c6637 Fixed a just-introduced glitch in directory creation with --no-implied-dirs. 2007-09-22 21:51:08 +00:00
Wayne Davison
33a04593ee We now forward the --no-implied-dirs option to the receiving side,
just in case we end up talking protocol 30 in inc_recurse mode.
2007-09-22 21:43:19 +00:00
Wayne Davison
6303f9a25f The latest --relative --no-implied-dirs code in inc_recurse mode
sends us a normal sequence of dirs, and we just skip the implied
ones.
2007-09-22 21:43:15 +00:00
Wayne Davison
3932c42373 Using relative with incremental recursion now results in a normal
sequence of directories in the hierarchy, and works properly when
merging things from multiple sources.
2007-09-22 21:43:11 +00:00
Wayne Davison
bc5df0f4e6 Fixed name of PTR_EXTRA_CNT (was PTR_EXTRA_LEN). 2007-09-22 21:43:08 +00:00
Wayne Davison
4b163f00c2 - Incremented the SUBPROTOCOL_VERSION to 9.
- Fixed name of PTR_EXTRA_CNT (was PTR_EXTRA_LEN).
- Added F_DIR_RELS_P() to support --relative in inc_recurse mode.
2007-09-22 21:43:05 +00:00
Wayne Davison
f07992739a Added ifuncs.h. 2007-09-22 18:07:44 +00:00
Wayne Davison
c605c2cdbd Tweaked opening comments. 2007-09-22 18:07:17 +00:00
Wayne Davison
1b42f628f4 Moved inline functions from rsync.h into ifuncs.h. 2007-09-22 16:52:58 +00:00
Wayne Davison
5dafe360de Moving inline functions into its own .h file. 2007-09-22 16:46:49 +00:00
Wayne Davison
6619d5fcc1 Added some stub functions for compilers not smart enough to get rid
of static inline functions that are not called.
2007-09-22 14:18:32 +00:00
Wayne Davison
b960483e99 Avoid affecting the proto.h file. 2007-09-22 14:16:48 +00:00
Wayne Davison
dd4a039515 Added some stub functions for compilers not smart enough to get rid
of static inline functions that are not called.
2007-09-18 19:53:50 +00:00
Wayne Davison
229554084d Added missing "#ifdef ICONV_OPTION" conditionals. 2007-09-18 18:46:03 +00:00
Wayne Davison
4a1edb63dd If iconv_t isn't needed, define it as an "int" so that our
proto.h file can be parsed.
2007-09-18 18:45:59 +00:00
Wayne Davison
3170b20967 Mention that a negative max-connections value disables the module. 2007-09-18 14:18:45 +00:00
Wayne Davison
d34cd639fc If max-connections is < 0, disable the module. 2007-09-18 14:14:22 +00:00
Wayne Davison
236df01b15 One final tweak. 2007-09-18 14:11:25 +00:00
Wayne Davison
21cafc50cc Some minor improvements in claim_connection(). 2007-09-18 14:09:38 +00:00
Wayne Davison
de80679b67 Switching to --no-i-r from --no-ir. 2007-09-18 14:04:46 +00:00
Wayne Davison
27999abab4 Document the changed name of --no-i-r. 2007-09-18 14:03:41 +00:00
Wayne Davison
82f37486a1 Mention the --protect-args (-s) option and how it interacts with
--iconv and --files-from.
2007-09-18 01:29:36 +00:00
Wayne Davison
7820fa949f Relocated the setting of ic_ndx. 2007-09-18 01:14:33 +00:00
Wayne Davison
2ac9793064 - Added new iconvbufs() conversion function that is now used for
our --iconv support.
- Moved the setup of the ic_ndx value to compat.c.
2007-09-18 01:11:57 +00:00
Wayne Davison
a4453606cc - Improved -s support.
- Handle setup_iconv() call in parse_arguments() so it gets set early.
2007-09-18 01:11:54 +00:00
Wayne Davison
71605b0f4d - Make use of new iconvbufs() function.
- Convert protected args when -s and --iconv are active.
- Simplified the splitting of args between normal and protected.
- Relocated setup_iconv() call so that it takes effect earlier.
2007-09-18 01:11:49 +00:00
Wayne Davison
ba525f770c - Make use of new iconvbufs() function.
- Convert remote --files-from filenames when -s and --iconv are
  active.
2007-09-18 01:11:45 +00:00
Wayne Davison
2509753fd3 Make use of new iconvbufs() function. 2007-09-18 01:11:42 +00:00
Wayne Davison
5688c74d25 - Setup the ic_ndx value here with the other FOO_ndx values.
- Don't disable inc_recurse due to --no-implied-dirs.
- Set filesfrom_convert bool.
2007-09-18 01:11:35 +00:00
Wayne Davison
2ac081ff60 - Added an xbuf type for use in the --iconv and --files-from code.
- Incremented the SUBPROTOCOL_VERSION.
2007-09-18 01:11:32 +00:00
Wayne Davison
5d3e5f641d Improved -s and support cvs's -e30.8 version idiom. 2007-09-17 06:02:09 +00:00
Wayne Davison
a0f29ed824 Make sure that the hashed hard-link numbers from different file
lists can't overlap in inc_recurse mode.
2007-09-17 01:45:44 +00:00
Wayne Davison
0b515981fc Changed print_child_argv() to take its prefix message as an arg. 2007-09-16 21:41:42 +00:00
Wayne Davison
2e8259bb0b Disable -s by default. 2007-09-16 02:42:55 +00:00
Wayne Davison
d274524317 Adding knowledge of some new options. 2007-09-15 21:10:35 +00:00
Wayne Davison
71845bd2a0 That should have been -s. 2007-09-15 21:10:18 +00:00
Wayne Davison
bdd53557a8 Force knowledge the -p option, since it gets passed specially. 2007-09-15 21:08:08 +00:00
Wayne Davison
d6ca255c21 - Fixed a bug in the passing of the --max-delete option.
- Added --no-i-d as a shorter no-implied-dirs.
- Changing to --no-i-r instead of --no-ir.
2007-09-15 20:54:31 +00:00
Wayne Davison
2dc7b91dd2 Handle inheritance of SGID bit on dirs marked with FLAG_DIR_CREATED. 2007-09-15 19:58:15 +00:00
Wayne Davison
288b12eefe We set FLAG_DIR_CREATED on a dot dir that got created by
get_local_name() rather than using the (now removed)
new_root_dir global.
2007-09-15 19:58:12 +00:00
Wayne Davison
f7d6dce6c8 - Fixed an inc_recurse problem with implied dirs not getting created
with the right attributes and getting omitted from the output.
- Got rid of the directory touch-up pass in inc_recurse mode again.
  This requires us to create any missing directories early, but we
  still report on what happened in the normal course of the transfer
  sequence.
- Use the FLAG_DIR_CREATED flag instead of (the removed)
  new_root_dir global.
2007-09-15 19:58:09 +00:00
Wayne Davison
48a481c4d0 Changed FLAG_DIR_CHANGED to FLAG_DIR_CREATED. 2007-09-15 18:43:36 +00:00
Wayne Davison
8db8eacbdd - If two duplicate directories have identical outside-the-transfer
paths, we only scan one of them in inc_recurse mode.
- When unduplicating directories in inc_recurse mode, dump the
  ealier directory if it is implied.
2007-09-15 17:29:25 +00:00
Wayne Davison
e8e9e12c3a Reverting last change for a re-think. 2007-09-15 17:00:41 +00:00
Wayne Davison
6e6daf5ac6 Fixed a problem with duplicate dirs being unduplicated in the list:
in inc_recurse mode, we must keep the last dir of the duplicates.
2007-09-15 16:32:38 +00:00
Wayne Davison
e73eed8563 Added more local-network IPs to the "hosts allow" rsyncd config
so that the FreeBSD machine in the compile farm can test.
2007-09-15 15:50:59 +00:00
Wayne Davison
da1319128a - Parse hard-link info as soon as we get it in inc_recurse mode.
- Improve the chances of the generator finding a match for a
  hard-link file in inc_recurse mode.
2007-09-15 15:40:57 +00:00
Wayne Davison
f2179fd370 The server should not wait around for an extra end-of-run message. 2007-09-15 15:36:04 +00:00
Wayne Davison
969cdffbea Prevent a server from outputting an end-of-run message about its
error-code that cannot be sent successfully.
2007-09-15 15:30:45 +00:00
Wayne Davison
3b7bcaaf34 Got rid of duplicate error when push_pathname() fails. 2007-09-15 15:27:56 +00:00
Wayne Davison
4abe379c05 Added an "ndx" arg to all the finish_hard_link() calls. 2007-09-10 06:15:28 +00:00
Wayne Davison
c980db5f08 - Simplified the flist-spanning gnum logic in match_gnums().
- Don't use hlink_flist in hard_link_check().
- Made the prev_name logic in hard_link_check() better.
- Added an "ndx" arg to the finish_hard_link() call.  Also, set the
  prev value of any prior entries to the first finished item (which
  ensures that any item that follows a re-shuffled item (which was
  waiting for a transferred file to finish) can find the FIRST+DONE
  item.
2007-09-10 06:15:25 +00:00
Wayne Davison
c35d6e3522 Added --no-protect-args and --no-s. 2007-09-09 07:58:19 +00:00
Wayne Davison
044dc29307 - Made glob_expand_one() public.
- Tweaking the calling syntax for glob_expand().
2007-09-09 07:53:22 +00:00
Wayne Davison
7a4addaa74 Added the --protect-args (-s) option, and made parse_arguments()
clear out an old popt context before starting a new one.
2007-09-09 07:53:18 +00:00
Wayne Davison
f7e5068d94 - If the user specifies a source arg with a hostspec in it in a local-
source transer, complain and exit.  This can help to find option
  problems were an arg to an option turns into a local-source arg,
  and the real remote-source arg will now get rejected rather than
  attempting to find a file with a colon in its name.
- We now support the ability to specify more than one remote arg using
  the ":FILENAME" idiom for additional remote filenames.
- If the --protect-args (-s) option was specified, we send just the
  "--server -s" options to the remote rsync when it is starting, and
  then the real args are sent over the socket.
2007-09-09 07:53:15 +00:00
Wayne Davison
67b8f3dfe7 - Renamed read_line() to be read_line_old().
- Renamed read_filesfrom_line() to read_line() and added args to allow
  the caller to control how it works.
- Added a new function, read_args(), that reads args from a file
  descriptor (using read_line()) and expands any wildcards in them.
  This function has relocated daemon code (from clientserver.c) and
  is also used by the new --protect-args (-s) option.  The new code
  also got rid of an extra strdup() that wasn't needed.
2007-09-09 07:53:12 +00:00
Wayne Davison
95a44066da Call the renamed read_line() function (was read_filesfrom_line()). 2007-09-09 07:53:08 +00:00
Wayne Davison
7909e65f83 - Made start_socket_client() and start_inband_exchange() take a variable
number of remote args.
- We now exchange a "VERSION.SUBVERSION" value in the initial @RSYNCD
  message.  This is backward compatible with pre-protocol 30 rsyncs,
  and fixes a problem where rsync daemons weren't checking if they were
  speaking a compatible pre-release protocol.
- Moved the protocol-handling code (which was in two places) into a new
  function:  exchange_protocols().
- Protocol 30 now sends/receives the daemon args using NULLs as a separator
  rather than a newline.
- Moved the arg-reading code into a new function in io.c:  read_args().
2007-09-09 07:53:05 +00:00
Wayne Davison
f74a3d813b Call the renamed read_line_old() function (was read_line()). 2007-09-09 07:53:02 +00:00
Wayne Davison
ac59386027 Used a couple "#if SUBPROTOCOL_VERSION != 0" conditionals. 2007-09-09 07:52:59 +00:00
Wayne Davison
73a649b7cb Tweaked the pretend-ssh script. 2007-09-08 20:16:28 +00:00
Wayne Davison
9b49704959 Added a remote-shell substitute for use in testing and for certain
other esoteric needs.
2007-09-08 20:03:42 +00:00
Wayne Davison
ffbffc647b Improved the argv/argc variable names that are really pointers. 2007-09-08 19:42:27 +00:00
Wayne Davison
968061bb65 Clarified something in the new --hard-links text. 2007-09-04 20:10:52 +00:00
Wayne Davison
c47e3ee1b6 Fixed two flist->files[first_hlink_ndx] references. 2007-09-04 07:13:01 +00:00
Wayne Davison
549a3efbb7 Improved a sentence. 2007-09-04 06:58:19 +00:00
Wayne Davison
accf8d12bc Added a test combining -H with -c and a hard-linked file that has only
one instance inside the copy hierarchy.  (Used to fail with protocol 29
or --no-ir.)
2007-09-04 06:57:57 +00:00
Wayne Davison
0eeb9f5481 If we turn off FLAG_HLINKED, set FLAG_HLINK_DONE so that any
file-entry values affected by HLINK_BUMP() stay put.
2007-09-04 06:53:47 +00:00
Wayne Davison
7b46e30fd4 Changed HLINK_BUMP() to look for either FLAG_HLINKED or FLAG_HLINK_DONE. 2007-09-04 06:52:52 +00:00
Wayne Davison
35c8fd761f Disabled the debug messages relating to the e_fds vars. 2007-09-03 21:51:59 +00:00
Wayne Davison
ba2d43d702 - Got rid of caveat about -H not working with incremental recursion.
- Talk about how inc_recurse affects -H.
- Mention --no-inc-recursive and --no-ir options.
2007-09-03 21:32:21 +00:00
Wayne Davison
29349024c4 Improved the handling of the file-status events received by
the generator.
2007-09-03 21:21:24 +00:00
Wayne Davison
d108e04f38 We don't disable inc_recurse due to -H anymore. 2007-09-03 21:21:21 +00:00
Wayne Davison
d4d6646aae Changes to allow hard-linking to work in inc_recurse mode. 2007-09-03 21:21:17 +00:00
Wayne Davison
cf2d26656d - Changes to allow hard-linking to work in inc_recurse mode.
- Incremented SUBPROTOCOL_VERSION to 7.
2007-09-03 21:21:12 +00:00
Wayne Davison
7918f24405 Changed some instances of \" in checkit calls to '. 2007-09-03 20:43:58 +00:00
Wayne Davison
9544261a45 Added weeding of "sending incremental file list" line to filter_outfile(). 2007-09-03 19:52:35 +00:00
Wayne Davison
354c9da60d Added hashtable.o. 2007-09-03 04:59:15 +00:00
Wayne Davison
626065702f Removed the old version of the hashtable functions and updated
the code to use the structures and functions calls.
2007-09-03 04:59:12 +00:00
Wayne Davison
9863bdbc93 - Use the new hashtable structures and functions.
- Tweaked a {read,write}_varint30() call set that didn't need to be "30".
2007-09-03 04:59:09 +00:00
Wayne Davison
83135e8f6a Updated hashtable structures. 2007-09-03 04:59:05 +00:00
Wayne Davison
369233927c The hashtable routines from hlink.c modified to have more generic names,
to support 2 sizes of key (32 and 64 bits), and to have a non-allocating
option for the find routine (returning NULL for no match).
2007-09-03 04:46:57 +00:00
Wayne Davison
7e4b6b7bc4 Use new0() function instead of new() followed by memset(). 2007-09-03 04:19:11 +00:00
Wayne Davison
a2dc4d687b Tweaked _new_array() to handle new use_calloc parameter. 2007-09-03 04:19:02 +00:00
Wayne Davison
a4431563e8 Added new0() and new_array0() to allocate and zero the memory. 2007-09-03 04:18:58 +00:00
Wayne Davison
fbd91cae0c One more tweak to latest omit-dir-times code. 2007-09-02 06:25:26 +00:00
Wayne Davison
eb7a6e09cb Added --no-omit-dir-times and --no-O. 2007-09-02 06:20:42 +00:00
Wayne Davison
9889a34bf2 Don't include the checksum_seed in the full-file MD5 checksum. 2007-09-02 06:00:30 +00:00
Wayne Davison
8e1e60e98f Bump up the SUBPROTOCOL_VERSION number. 2007-09-02 06:00:27 +00:00
Wayne Davison
f9998046a3 Made omit_dir_times a static variable in options.c by encoding
all the time-preserving semantics into preserve_times.
2007-09-01 16:57:01 +00:00
Wayne Davison
07bbf8703f Document the new --append and --append-verify options. 2007-09-01 16:38:09 +00:00
Wayne Davison
77502cbade Downgrade the new --append option to --append-verify for protocols < 30. 2007-09-01 16:38:04 +00:00
Wayne Davison
936fa865e1 Handle the new --append and --append-verify options. 2007-09-01 16:38:00 +00:00
Wayne Davison
2f188c8d96 Tweaked a comment. 2007-09-01 00:59:44 +00:00
Wayne Davison
83f5394810 Make the verbose message about the file-list expansion clearer in
what is being expanded.
2007-08-29 23:10:16 +00:00
Wayne Davison
24d677fc16 Don't omit the -4/-6 options if no IPv6 support was compiled into
rsync.  Just make them a no-op.
2007-08-22 00:36:56 +00:00
Wayne Davison
65a22a5ff7 In pool_free_old(), one code path was not clearing a "next" pointer,
so the code could try to free an extent twice in certain circumstances.
2007-08-21 05:04:02 +00:00
Wayne Davison
a0f70237f5 Fix pool_create() to honor the POOL_INTERN flag.
(Thanks to Brion Vibber.)
2007-08-21 04:54:30 +00:00
Wayne Davison
4eff3051a0 Fixed a null-pointer dereference pointed out by Olivier Thauvin. 2007-08-16 01:22:46 +00:00
Wayne Davison
e208631a5b Improved the arg-checking of a daemon command. 2007-08-11 16:53:31 +00:00
Wayne Davison
b553a3dd20 Document the RSYNC_CONNECT_PROG environment variable. 2007-08-11 16:51:48 +00:00
Wayne Davison
e5f1a96ff8 Added support for a %H escape in the value of the RSYNC_CONNECT_PROG
environment variable.
2007-08-11 16:20:56 +00:00
Wayne Davison
eb7e7b2499 Get rid of the comment that --xattrs implies --perms and the
outdated text that said it was a non-standard option.
2007-08-04 22:19:49 +00:00
Wayne Davison
3caafdfd2f Make the --xattrs option not imply --perms. 2007-08-04 22:19:43 +00:00
Wayne Davison
26ac181223 Let's go with "delta transfer algorithm" (thanks, Matt). 2007-08-04 19:09:26 +00:00
Wayne Davison
7fa60281bf Avoid a crash if pop_local_filters() has some pointer gaps. 2007-08-04 19:09:21 +00:00
Wayne Davison
73f2fa8189 - Call the rsync algorithm differential rather than incremental.
- Don't refer to --files-from in the talk of incremental recursion,
  since it might make people think that --files-from disables
  incremental recursion for any recursively scanned directories.
2007-08-04 17:47:08 +00:00
Wayne Davison
75f162e46f - Use the new XMIT_NON_XFER_DIR flag.
- Make sure that non-inc-recurse mode sets FLAG_XFER_DIR on all
  the non-implied directories.
- Don't set FLAG_XFER_DIR on non-directories.
2007-08-04 17:47:02 +00:00
Wayne Davison
1d2ca00703 - Added XMIT_NON_XFER_DIR flag.
- Incremented the SUBPROTOCOL_VERSION number.
2007-08-04 17:46:59 +00:00
Wayne Davison
4d91a5f8f4 Only honor XFLAGS_HLINKED on a non-directory. 2007-08-04 16:10:37 +00:00
Wayne Davison
61cb031ca4 Changed flags variable in send_file_entry() to xflags. 2007-08-04 16:08:16 +00:00
Wayne Davison
ff0c27c926 Files with the same size should also be skipped by --append. 2007-08-01 22:47:36 +00:00
Wayne Davison
d1d0a7051f Don't output a negative time-remaining value if the file has grown. 2007-08-01 22:35:54 +00:00
Wayne Davison
444f9f7b04 Fixed the port-parsing in an rsync:// path; e.g., this now
works properly:  rsync://backup@otherbox/module/a:123:b
2007-08-01 22:25:02 +00:00
Wayne Davison
411c04f06f If readdir() gives us an empty name, reject it. 2007-08-01 22:18:46 +00:00
Wayne Davison
5d935dce63 If --no-ir is specified, pass it to the server. 2007-07-24 04:09:46 +00:00
Wayne Davison
b88f6fe7e5 Let's try using egrep instead of grep since grep on Solaris
systems was failing to work right.
2007-07-15 06:37:17 +00:00
Wayne Davison
e6109f496c Updated the --max-delete docs. 2007-07-15 06:01:27 +00:00
Wayne Davison
836ce36a4f Mention the improved --max-delete behavior. 2007-07-15 05:51:05 +00:00
Wayne Davison
35da2ec35a We don't need a compatibility check for --max-delete anymore. 2007-07-15 05:43:05 +00:00
Wayne Davison
7b9598b2d5 We now take a negative value specified to --max-delete as being
synonymous with --max-delete=0.  We also pass a request for 0
deletions to the server as --max-delete=-1.  This ensures that we
can send a backward-compatible option to old and new versions alike.
2007-07-15 05:42:30 +00:00
Wayne Davison
4a4622bbe5 Improve the description of --update with respect to symlinks and
special files.
2007-07-14 22:24:03 +00:00
Wayne Davison
c9ec460807 Make extra-verbose output of touch_up_dirs() only mention the dirs. 2007-07-14 21:58:36 +00:00
Wayne Davison
79cd0c7fa4 Using --relative with --no-implied-dirs turns off incremental recursion.
(A temporary measure until some bugs can be fixed.)
2007-07-14 21:49:11 +00:00
Wayne Davison
de8c8b28c0 - When --omit-implied-dirs is specified and the creation of a directory
fails, we must make sure that the item we're skipping has a name that
  is still inside the missing hierarchy by using a prefix matching func.
- We now handle the failure to remove a file to create a dir the same
  way as a failed mkdir() (skipping the failed dir's contents).
2007-07-14 21:25:51 +00:00
Wayne Davison
569e6f432b - Made f_name() and f_name_cmp() take const pointers.
- Added f_name_has_prefix().
2007-07-14 21:21:15 +00:00
Wayne Davison
0d585188f9 Make sure that any "dont compress" patterns that have wildcards in a
suffix match stay in the wildcard-matching list.
2007-07-14 19:36:52 +00:00
Wayne Davison
34ca58d440 The "dont compress" daemon option points to the --skip-compress option
for the default set of non-compressed file suffixes.
2007-07-14 19:32:10 +00:00
Wayne Davison
9c528e2935 Mention the latest changes. 2007-07-14 19:29:04 +00:00
Wayne Davison
2b967218eb Document --skip-compress. 2007-07-14 19:24:44 +00:00
Wayne Davison
6e058b4b60 - Added support for the new --skip-compress option.
- Optimized the matching of non-compressing file suffixes.
2007-07-14 19:24:35 +00:00
Wayne Davison
b1e436ec17 Parse the --skip-compress=LIST option and sent it to the sending side. 2007-07-14 19:24:32 +00:00
Wayne Davison
4319cc56d8 Added more suffixes to the default "dont compress" value. 2007-07-14 19:24:27 +00:00
Wayne Davison
952ae75138 Make sure that --dry-run with --del doesn't output extraneous info
when the dest directory does not exist.
2007-07-14 04:47:42 +00:00
Wayne Davison
4d745d3cf5 The delete-during code needs to skip directories that don't exist
yet in --dry-run mode to avoid outputting bogus delete details.
2007-07-14 04:20:13 +00:00
Wayne Davison
8798be8e63 Mention license change. 2007-07-14 04:06:33 +00:00
Wayne Davison
42b06481c3 Made some descriptions concerning modification times clearer. 2007-07-12 14:43:26 +00:00
Wayne Davison
dbe287b701 Needed to use ndx_end in decrement_flist_in_progress(). 2007-07-12 14:04:11 +00:00
Wayne Davison
8e3b627d07 Mention how --ignore-existing can be useful for restarting a copy
that uses --link-dest.
2007-07-10 14:49:35 +00:00
Wayne Davison
809724d7e2 - Use "filename", not "file name".
- Say "regular file" instead of "file" when itemizing a list of
  non-directory types.
- Try to avoid "file" in its generic sense, as it is hard to figure
  out when it includes dirs and when it doesn't.
2007-07-10 14:21:59 +00:00
Wayne Davison
8e41b68e8f Tweaking the license text a bit more. 2007-07-10 13:55:49 +00:00
Wayne Davison
dc77edf218 Martin gave his approval to use GPLv3 with this code. 2007-07-09 01:24:01 +00:00
Wayne Davison
65ba6af61b - Do directory touch-ups at the end, even in inc-recurse mode.
- Use the latest F_DIR_*() defines (whose names were tweaked).
2007-07-08 20:53:42 +00:00
Wayne Davison
83d5e90054 - Use the new DEV_EXTRA_CNT and DIRNODE_EXTRA_CNT defines.
- Use the latest F_DIR_*() defines (whose names were tweaked).
2007-07-08 20:53:38 +00:00
Wayne Davison
e434f0ebfe Use the latest F_DIR_*() defines (whose names were tweaked). 2007-07-08 20:53:35 +00:00
Wayne Davison
a08979d564 - Define DEV_EXTRA_CNT and DIRNODE_EXTRA_CNT.
- Define and use ACL_BUMP(), fixing a clash between -A and -x in a
  directory's data.
- Tweaked the F_DIR_*() defines to have more consistent names.
- Don't make F_SUM() return a char pointer that is const.
2007-07-08 20:53:31 +00:00
Wayne Davison
252af65bb4 Changed the spots that referred to the filter_level as filter_flags
to make the naming consistent.
2007-07-08 06:30:28 +00:00
Wayne Davison
d048c2f225 Added a test for --prune-empty-dirs. 2007-07-08 06:25:57 +00:00
Wayne Davison
9b9d5f89b3 Got rid of the output differences for protocol 30 since it is now
the same as earlier protocols.
2007-07-08 06:25:54 +00:00
Wayne Davison
e5bf3b5855 - Incremental recursion mode does not process the dirs while scanning a
file list's contents.  Instead, it handles a parent dir prior to each
  extra file list.  This makes the dir-processing order the same in
  protocol 30 as it is in earlier protocols.
- Moved the permission-fudging code for dirs into recv_generator() to
  make the new protocol-30 dir-handling logic easier.
2007-07-08 06:25:51 +00:00
Wayne Davison
6755a7d742 If we get an ndx that is 1 entry prior to an incremental flist's
start, it refers to the file list's parent dir.
2007-07-08 06:25:47 +00:00
Wayne Davison
5459e693a3 - The sending side now sets the parent_ndx value in each file list.
- Leave a 1-entry gap between incremental file lists so that we can use
  that index value to refer to the parent directory of each file list.
- Set and use the new ndx_end value in the file list.  The incremental
  recursion mode omits dirs in this value (except in the first list)
  since the generator will be using the new "gap" ndx value to process
  each parent dir.
2007-07-08 06:25:42 +00:00
Wayne Davison
24108eb854 - Increased the SUBPROTOCOL_VERSION to 4 due to the new dir-ndx logic.
- Added ndx_end value to struct file_list.
2007-07-08 06:25:36 +00:00
Wayne Davison
4635fb9995 Avoid the prune-empty-dir code when cleaning a file list created
by get_dirlist().
2007-07-07 20:43:14 +00:00
Wayne Davison
9decb4d2ef Changed "count" to "used" in struct file_list since there can
be empty items that make the count inaccurate (and the name
somewhat deceiving).
2007-07-07 20:22:05 +00:00
Wayne Davison
b3b326016a The length check in make_file() doesn't need to subtract pathname_len
anymore, as the sender code never concatenates the F_PATHNAME() value
with the dirname+basename string these days.
2007-07-07 16:01:59 +00:00
Wayne Davison
4bde45f60e Make the comment even better. 2007-07-07 15:37:56 +00:00
Wayne Davison
4fd842f98d Switching to GPL 3. 2007-07-07 05:33:14 +00:00
Wayne Davison
f92f5b166e Tweaked a comment to remove a (really old) rsync version reference. 2007-07-07 05:25:50 +00:00
Wayne Davison
9b25ef35bd Switch the checking of preserve_[ug]id var to checking [ug]id_ndx var
when the code is about to use the [ug]id_ndx value as an index (since
this saves a memory reference).
2007-07-02 22:11:23 +00:00
Wayne Davison
7c73536c25 Use module_dir instead of lp_path(). 2007-07-02 22:06:48 +00:00
Wayne Davison
33cbd577ad If a module's path is not absolute, make it absolute. 2007-07-02 22:02:14 +00:00
Wayne Davison
524eaa8245 We omit copying any user-space rsync.%FOO attributes unless the
user specified -X twice.
2007-07-02 21:35:14 +00:00
Wayne Davison
9742b386b3 Make option variables a little clearer by using separate FOO_ndx
values to index into the file-list extra-attribute array instead
of abusing the preserve_FOO variables.
2007-07-02 21:29:49 +00:00
Wayne Davison
8b498b9f1a Decided against the last change. 2007-06-06 15:43:34 +00:00
Wayne Davison
c04af69701 Allow a NULL address to be passed to pool_free_old() to indicate that
it should free all old mem and reset to an empty state.
2007-06-06 15:38:31 +00:00
Wayne Davison
f87fb190b3 Check for the setacl command for Tru64 (which doesn't have setfacl). 2007-06-02 16:44:23 +00:00
Wayne Davison
a21e72c3e6 Attempting to make the mask test compatible with Solaris 8. 2007-06-02 16:30:04 +00:00
Wayne Davison
1c4ffe64db Mention the pool_alloc changes. 2007-05-29 04:23:50 +00:00
Wayne Davison
abdcb21a7a Unified the file-list pool used in incremental recursion mode so that
we use less memory, especially in small transfers.  As file lists are
discarded, we use the new pool_boundary() and pool_free_old() functions
to discard pool extents that are no longer needed.
2007-05-29 04:19:47 +00:00
Wayne Davison
f5ba7bfbb6 - Changed FILE_EXTENT to NORMAL_EXTENT and HLINK_EXTENT to SMALL_EXTENT.
- Added a pool_boundary variable to struct file_list.
2007-05-29 04:19:44 +00:00
Wayne Davison
676e604135 Added pool_free_old() and pool_boundary() functions to add a way to
free all wholly affected extents older than a particular point in time.
2007-05-29 04:19:41 +00:00
Wayne Davison
3fac8ca8d1 Tweaked a variable and a label to make them less confusing. 2007-05-29 02:47:23 +00:00
Wayne Davison
33766a8daa Improvements to increase clarity, fix misstatements, add missing
punctuation, and fix some typos.
2007-05-29 02:46:44 +00:00
Wayne Davison
e3d27df444 - Fixed a bug where a pool_free() on the most-recently allocated pool
item was trying to make that memory available to the pool, but it
  failed to adjust the right variable.
- Fixed a bug in pool_free() where the return of the entire live
  extent back to unallocated status did not obey POOL_CLEAR.
- Use the new() and new_array() functions instead of malloc().
- Changed the sqew variable to skew.
- Some other minor formatting tweaks.
2007-05-29 00:52:08 +00:00
Wayne Davison
6aa27a7ce5 - Do less seeking when writing a sparse file.
- Don't rewrite the last byte of a file in sparse mode when the
  file didn't end with a null char.
2007-05-26 21:46:22 +00:00
Wayne Davison
47cffb77de Handle EINTR in a couple places where we handle the --file-from I/O. 2007-05-26 21:44:19 +00:00
Wayne Davison
565a340b0a Changed verbosity back from -vvvv to -vv. 2007-05-25 14:32:08 +00:00
Wayne Davison
f45b64d8dd Improved the sort comment. 2007-05-25 14:29:35 +00:00
Wayne Davison
56ce72c447 Improved a comment. 2007-05-25 14:23:05 +00:00
Wayne Davison
898fab2577 Got rid of superfluous acl_clear_perms() call that Antti Tapaninen
pointed out.
2007-05-25 14:16:57 +00:00
Wayne Davison
0e5dd89866 Mention latest improvements. 2007-05-24 23:11:33 +00:00
Wayne Davison
79028af116 Changed dup-detection code to keep the first item in the user's args.
This is more in keeping with the way cp works, and also makes the dir-
joining code (in inc_recurse mode) easier.
2007-05-24 23:08:39 +00:00
Wayne Davison
a572e12675 - Added fsort() and fsort_tmp() that implement a mergesort routine
that ensures that any identical items in the file-list stay in the
  same order as they had in the input.  It will also obey the --qsort
  option (which causes it to punt the sort to the qsort() routine).
- Changed the various places that sort the file-list to call fsort().
2007-05-24 02:50:41 +00:00
Wayne Davison
c8e8394615 If someone forces the use of qsort() via --qsort, disable incremental
recursion (at least for now).
2007-05-24 02:50:38 +00:00
Wayne Davison
8487f9cf29 - Added the --qsort option.
- Added several new --no-FOO options.
2007-05-24 02:50:35 +00:00
Wayne Davison
d750be6ad8 Make sure we don't try to output a NULL pointer in a verbose message. 2007-05-23 00:48:27 +00:00
Wayne Davison
0bb8616535 - Output a -vvv(erbose) message in the touch_up_dirs() loop.
- Made the keep-alive counter in touch_up_dirs() work better.
- Use !(N & 0xFF) instead of !(N % 200).
2007-05-23 00:42:38 +00:00
Wayne Davison
1faa1a6da9 Output a -vvv(erbose) message when receiving an incremental file list. 2007-05-23 00:42:32 +00:00
Wayne Davison
b5ae4e25c2 Added a comment to the do_chmod() to mark it as a discouraged function. 2007-05-22 05:59:02 +00:00
Wayne Davison
3d0a159d96 Added a comment to a shared iterator to avoid a warning from IBM's checker. 2007-05-22 05:58:59 +00:00
Wayne Davison
8ea07c0030 - Changed the dir_flist code on the sending side to derive its sorted
data from the sorted parent flist.  This ensures that any entries
  marked with FLAG_DUPLICATE are in the same order in the dir_flist
  (where the flags get checked) as they are in the parent flist
  (where the flags get set).
- Made the flist_expand() function static.
- Added a growth count arg to flist_expand().
- Made make_file() set a pool variable instead of tweaking flist.
- Improved the error message when a dir-number is out of bounds.
2007-05-22 05:50:47 +00:00
Wayne Davison
59fd2a5e7d Improved the error message when a dir-number is out of bounds. 2007-05-22 05:50:41 +00:00
Wayne Davison
ae87c43452 One more output_flist() call that should verify if my analysis
of the Solaris 10 host's merge-test failure is correct or not.
2007-05-22 03:58:18 +00:00
Wayne Davison
f1599b9ef2 Be more verbose so that we can debug what is going wrong on solaris. 2007-05-22 00:00:51 +00:00
Wayne Davison
ee83e1bd4d Improved the index values that output_flist() outputs when we're being
extra verbose:  they now have the list's ndx_start value added in.
2007-05-22 00:00:07 +00:00
Wayne Davison
7455467c17 One more try at silencing some checker warnings. 2007-05-21 23:45:26 +00:00
Wayne Davison
19395697b9 Let's see if we can silence some more code-checker warnings. 2007-05-21 18:39:05 +00:00
Wayne Davison
7787579ad4 Added some "FALL THROUGH" comments in the main switch. 2007-05-21 10:20:18 +00:00
Wayne Davison
58a37ed34a Get rid of compiler warning about iconv()'s second parameter. 2007-05-21 03:56:06 +00:00
Wayne Davison
fe8d61e5d5 Fixed a thinko in the calling of recv_add_gid(). 2007-05-21 03:20:39 +00:00
Wayne Davison
87b0cc726b Got rid of the temporary "set -x" that was added for debugging. 2007-05-21 03:09:25 +00:00
Wayne Davison
4504b2259f The match_gid() function needed to affect the *flags_ptr value
when re-using the last-found match.
2007-05-21 03:08:55 +00:00
Wayne Davison
cf1b4969b9 The recv_file_entry() function needed to remember the gid flags so that
it can reuse them when the gid stays the same.
2007-05-21 03:08:01 +00:00
Wayne Davison
434e77193c Set -x option to diagnose what is going wrong on FreeBSD. 2007-05-21 02:31:20 +00:00
Wayne Davison
858d45f160 Cast some F_OWNER()/F_GROUP() values to make sure that we don't get
a signed/unsigned compiler warning on some systems.
2007-05-21 02:17:48 +00:00
Wayne Davison
63186ec077 Fixed a problem in a couple OS's sys_acl_get_access_bits() functions. 2007-05-21 02:09:45 +00:00
Wayne Davison
dfcb386569 Make sure that the scratch dirs have rwx permissions before we try
a recursive rm.
2007-05-21 02:06:51 +00:00
Wayne Davison
d15f2ff0cf Tweaked a sentence in the --size-only section. 2007-05-21 01:06:16 +00:00
Wayne Davison
c395acd804 Create a symlink back to the source dir in the scratchdir of a test. 2007-05-21 01:05:36 +00:00
Wayne Davison
030820d5dc - Unified the formerly separate user & group name-lists into a single
name-list.  On POSIX systems, this list will be sorted with the user
  names first, so the code will work essentially the same way it did
  before for the currently supported OSes.  However, the code will now
  more easily support non-POSIX ACL setups such as (hopefully) the one
  used in OS X.
- Increased the (potentially) available access-bit storage for name
  elements from 3 to 31 bits.  For non-name elements, the access bits
  now have the potential to store 7 bits instead of 3.  (All the
  current POSIX implementations still error-check their values at 3
  bits, but this will allow adding non-POSIX ACL setups more easily.)
- The protocol that transmits the ACL information was changed to send
  names in a single list, and to use {read,write}_varint() functions
  instead of {read,write}_byte().  This supports sending access-bit
  values up to 32-bits (minus any bits reserved for xmit flags).
- The construction of the internal access-bit value was moved into the
  lib/sysacls.c code, so that it could be handled in an appropriate
  manner for each OS.

(Aside: the code still does not support transmitting incompatible ACL
information between systems, but I envision improving --fake-super to
store the ACL information that is received as xattr information, and
this would allow a system that supports extended attributes to backup
a source system that had an incompatible ACL method.)
2007-05-21 01:04:40 +00:00
Wayne Davison
043ef55b22 - Define what the valid access bits are for a name element and a
non-name element.
- Set a define when the OS needs the name-list sorted.
- Got rid of the permset-related defines.
- Got rid of some function prototypes that rsync doesn't need.
- Got rid of the defines for the do-nothing ACL code.
2007-05-21 01:04:37 +00:00
Wayne Davison
a30dcbc0a8 - Added a function to get/set all the access-bit values with a single
call.  This allows the per-OS compatibility code to construct the
  value with however many bits are supported by each OS.
- Removed several functions that rsync doesn't (and won't) need.
- Got rid of the do-nothing ACL code (the ACL code in rsync should be
  disabled on a system that we can't support).
2007-05-21 01:04:34 +00:00
Wayne Davison
02f0227e87 Changed SUBPROTOCOL_VERSION from 2 to 3 because of the ACL protocol changes. 2007-05-21 01:04:31 +00:00
Wayne Davison
142a5e7b8b Moved GID_NONE define from rsync.h to uidlist.c. 2007-05-20 07:40:07 +00:00
Wayne Davison
fdfc67406c - Added more users and some groups to one of the files we're copying. 2007-05-20 07:10:48 +00:00
Wayne Davison
fb7b9ddcb1 - Use F_OWNER() and F_GROUP() instead of F_UID() and F_GID(). 2007-05-20 07:10:45 +00:00
Wayne Davison
4ade505c7e - Use F_OWNER() and F_GROUP() instead of F_UID() and F_GID().
- Use the new FLAG_SKIP_GROUP define.
2007-05-20 07:10:41 +00:00
Wayne Davison
1564cd5a87 - Use F_OWNER() and F_GROUP() instead of F_UID() and F_GID().
- Made recv_file_entry() name the xmit-flags variable "xflags" to
  prevent confusion with the internal flags value we're creating.
- Added an arg to the calls of recv_group_name() and match_gid().
- Use the improved function names: send_id_list() and recv_id_list().
- Improved the display of the GID values in output_flist().
2007-05-20 07:10:37 +00:00
Wayne Davison
33233b4900 - Fixed a bug in the match_racl_ids() function's iteration.
- Fixed a bug with preserving a group ID in an ACL when running as
  a non-super user that the user is not a member of.
2007-05-20 07:10:34 +00:00
Wayne Davison
d6b422a61c - Changed id & id2 from int to id_t in the struct iflist.
- Added a uint16 flags var to struct iflist.
- We now mark a group with FLAG_SKIP_GROUP if the receiving user
  can't set a group rather than turning it into GID_NONE.  This
  allows us to keep the real group ID mapping, which is needed by
  the ACL code.
2007-05-20 07:10:31 +00:00
Wayne Davison
ff2001b91b - Added FLAG_SKIP_GROUP define.
- Removed F_UID() and F_GID() defines.
2007-05-20 07:10:28 +00:00
Wayne Davison
d858b27400 A couple more minor tweaks. 2007-05-08 17:04:05 +00:00
Wayne Davison
1874f7e2e1 Improved the documentation on the "quick check" algorithm and the
--size-only option.
2007-05-08 17:01:24 +00:00
Wayne Davison
377d22ab9f If the server is exiting with an error, delay our exit just a little
in order to give the client side a better chance of reading any error
message we just sent.
2007-05-06 19:44:26 +00:00
Wayne Davison
4f3797c7e2 Clumped some option-sending together that only happens on the sending side. 2007-05-05 18:34:37 +00:00
Wayne Davison
6b5a8f80fc Try a better way to deduce if the xattr functions we need are there. 2007-04-30 02:58:14 +00:00
Wayne Davison
bf10faa9dc Added a "sleep 1" to make certain failures more reproducible. 2007-04-29 15:01:57 +00:00
Wayne Davison
548ca46fec Use the --super option for the non-fake test, just in case a system
can chown without appearing to be root (uid 0).
2007-04-28 23:47:16 +00:00
Wayne Davison
e8c64ffdc7 If the lgetxattr() function isn't found, disable xattr support. 2007-04-28 18:40:23 +00:00
Wayne Davison
0eb05245f1 Authorize 10.0.1.2 for one of the BSD test-farm systems. 2007-04-28 17:22:53 +00:00
Wayne Davison
0156c7842d Improved the --iconv description. 2007-04-27 14:09:22 +00:00
Wayne Davison
1acb8f5119 Added the $(CHECK_SYMLINKS) var to installcheck target. 2007-04-27 13:52:07 +00:00
Wayne Davison
76e754a0fd Fixed the buildability of the file without ICONV_OPTION enabled. 2007-04-27 00:19:21 +00:00
Wayne Davison
e7f905accb Fixed the comment about --iconv. 2007-04-27 00:19:02 +00:00
Wayne Davison
a9a8bc962c Got rid of the --no-ir kluge in this test. 2007-04-26 23:15:51 +00:00
Wayne Davison
a6e7b97868 - Fixed the merging of duplicated directory hierarchies in incremental
recursion mode.
- Fixed some problems with --iconv in incremental recursion mode.
2007-04-26 23:15:47 +00:00
Wayne Davison
1befb74b13 Refer to the right sorted/unsorted file list array in touch_up_dirs(). 2007-04-26 23:15:43 +00:00
Wayne Davison
8f3335a18c The server now needs the F_NDX() data for --iconv with incremental
recursion.
2007-04-26 23:15:39 +00:00
Wayne Davison
505c0579f7 Added FLAG_DUPLICATE for the sender to mark a duplicate flist entry
(which is better on the sending side than clearing the duplicate's
data).
2007-04-26 23:15:36 +00:00
Wayne Davison
a430691df1 Prevent a hang in incremental-recursion mode when the receiver encounters
an error updating the file:  the receiver now sends MSG_NO_SEND to the
generator so that it knows when all outstanding work is completed.
2007-04-26 23:06:38 +00:00
Wayne Davison
332cf6df7c The --iconv option has now made it to the trunk. 2007-04-26 05:53:13 +00:00
Wayne Davison
3f7afe7ec1 Changed a "mkdir -p" into a makedir. 2007-04-26 05:32:38 +00:00
Wayne Davison
8fc4033ef0 Changed F_ROOTDIR() to F_PATHNAME(). 2007-04-26 00:23:52 +00:00
Wayne Davison
ef35abb2b7 - Renamed flist_dir to pathname to avoid confusion with dir_flist var.
- Renamed push_flist_dir() to push_pathname().
- Set a pool var in recv_file_ent() instead of playing games with flist.
- Simplified the top_flags computation in send_file_list().
2007-04-26 00:23:48 +00:00
Wayne Davison
0b68d6b6f4 Create symlinks for fake tests. 2007-04-24 19:33:12 +00:00
Wayne Davison
f1271537a4 Put the files down in a subdir so that we test backup's dir-
creating functionality (which had a bug until recently).
2007-04-24 19:03:54 +00:00
Wayne Davison
b13505da1d Need to call unmake_file() instead of free() on a file_struct. 2007-04-24 18:43:31 +00:00
Wayne Davison
7ea6ea98c8 Use a single makepath call with multiple args. 2007-04-24 18:21:08 +00:00
Wayne Davison
d1798a2fda Allow makepath to take multiple args. 2007-04-24 18:19:25 +00:00
Wayne Davison
e911ff75d6 Specify an arg sequence that was recently failing to work. 2007-04-24 18:18:57 +00:00
Wayne Davison
49f7162e7d Use a slightly different rsync calling syntax. 2007-04-24 18:18:29 +00:00
Wayne Davison
3bb88b4388 Fixed a directory push problem with the user specified an arg
with a subdir followed by an arg with no subdirs.
2007-04-24 17:53:54 +00:00
Wayne Davison
b3fbe3ce35 The chown script now has a --fake-super mode if the script name has
"fake" in it.  Added a symlink named chown-fake.test.
2007-04-24 17:22:01 +00:00
Wayne Davison
9557eabaa7 Made the devices.test script do a real device test when called
normally, or a fake-device test when called with "fake" in the
script name.  Added a devices-fake.test symlink.
2007-04-24 17:06:09 +00:00
Wayne Davison
acac1f5c6f Conditionalize xattr code for systems without xattr support. 2007-04-24 16:54:38 +00:00
Wayne Davison
3427355422 A little more popt tweaking. 2007-04-24 16:11:02 +00:00
Wayne Davison
cbf626fd62 Fixed build problem for tls for those using the included popt. 2007-04-24 16:06:29 +00:00
Wayne Davison
1c702303eb Moved the header info from smb_acls.h into lib/sysacls.h. 2007-04-24 08:11:02 +00:00
Wayne Davison
9a234269ed Improved the usage message. 2007-04-24 08:00:49 +00:00
Wayne Davison
db9c9e2766 Added arg-parsing to tls.c. 2007-04-24 07:52:45 +00:00
Wayne Davison
9439c0cb5a Adding the --fake-super option. 2007-04-24 07:32:44 +00:00
Wayne Davison
2ed790f354 Improved the SUBPROTOCOL_VERSION code a little, and bumped the value
to 2.
2007-04-23 19:54:07 +00:00
Wayne Davison
486f8cd1ab Changed the prerelease-protocol support to use an idiom that will not
slow down the initial version handshake between the two sides.
2007-04-23 19:03:29 +00:00
Wayne Davison
875a13b42c No need to reset quiet, since we tell parse_arguments() that it
should prevent quiet from getting set.
2007-04-23 18:40:00 +00:00
Wayne Davison
719522b9bd Tweaked --version in a few minor ways, including the mentioning of
the SUBPROTOCOL_VERSION if it is non-zero.
2007-04-21 19:46:19 +00:00
Wayne Davison
753849fdbc Batch files need to be written with the new subprotocol value
for protocol 30.
2007-04-21 19:32:46 +00:00
Wayne Davison
bb25779de7 Mention how many bits our local timestamps support. 2007-04-21 19:31:54 +00:00
Wayne Davison
348d54d6d1 Mention the latest changes that have been made. 2007-04-21 19:27:04 +00:00
Wayne Davison
4471d9e570 Added a way to exchange a protocol's sub-protocol value. This will be
0 when a protocol goes final, and non-zero for an intermediary CVS
version of a protocol that is in flux.  If we find that we're talking
to a CVS version with a different sub-protocol #, we automatically
drop back to the prior protocol that the sides have in common.
2007-04-21 18:40:42 +00:00
Wayne Davison
19d4cac996 We now allow verbose messages to be sent when forwarding incremental-recursion
file-list data from the receiver to the generator.
2007-04-20 22:40:01 +00:00
Wayne Davison
e4c877cf70 Added a message queue for the receiver->generator messages to handle the case
where the message pipe is being used to forward the file-list data.
2007-04-20 22:39:58 +00:00
Wayne Davison
f14b3ef430 Verify that the modtime value is not being truncated, and complain if it is. 2007-04-20 22:39:55 +00:00
Wayne Davison
f3c93b1761 Check the size of a time_t. 2007-04-20 21:39:08 +00:00
Wayne Davison
a72ba0cfac Call the new {read,write}_varlong30() names for the long-int
functions that are protocol sensitive.
2007-04-20 08:17:06 +00:00
Wayne Davison
ba59bd68fc - Call the new {read,write}_varlong30() names for the long-int
functions that are protocol sensitive.
- Changed the sending of the time value in protocol 30 to support
  64-bit values without bloating positive 32-bit values.
2007-04-20 08:17:03 +00:00
Wayne Davison
1c60d21947 Got rid of the NVAL*() defines. 2007-04-20 08:16:59 +00:00
Wayne Davison
473feecff3 Added {read,write}_varlong30() inline functions to use the
right long-int function based on protocol version.
2007-04-20 08:16:56 +00:00
Wayne Davison
351e23ad8e - Changed the {read,write}_longint() functions into separate
{read,write}_varlong() and {read,write}_longint() functions:
  the former handles variable-length transmissions, and the
  latter is backward-compatible with older rsync versions.
- Improved the {read,write}_var{int,long}() functions to be
  simpler and to use a different byte order.
- The {read_write}_varlong() functions also allow the caller
  to specify the minimum number of bytes to send.  This allows
  time values to be sent efficiently with a 4-byte minimum,
  while length values continue to be sent with a (more optimal
  for them) 3-byte minimum.
2007-04-20 08:16:53 +00:00
Wayne Davison
f31514adb7 Changed the *_abbbrevint() functions to *_varint(). 2007-04-20 02:17:58 +00:00
Wayne Davison
2fcc265c2f Got rid of protocol-29 check. 2007-04-18 03:30:53 +00:00
Wayne Davison
b58e40332f If ssh access is not enabled, use a shell function to test that
we can copy using a spawned rsync process.
2007-04-18 03:23:26 +00:00
Wayne Davison
a217c45359 Got rid of ACL's uid/gid iterators in favor of a single function
that converts the uids & gids in a loop.
2007-04-18 02:33:02 +00:00
Wayne Davison
764782662d Can eliminate the testtmp.* ignore rule now. 2007-04-14 07:11:32 +00:00
Wayne Davison
4b24f4a2b5 Changed scratchbase from using a "testtmp." name prefix to using a
"testtmp/" name prefix (i.e. using a subdir).  This allows me to create
a testtmp as a symlink to a different file system to assist with testing
ACLs and xattrs.
2007-04-14 07:10:52 +00:00
Wayne Davison
c64ff141b8 Improved the description of the --checksum option. 2007-04-12 02:44:41 +00:00
Wayne Davison
1b896f8d1e The check for GCC <= 2 was in the wrong part of an #ifdef sequence. 2007-04-12 02:37:31 +00:00
Wayne Davison
01894cf01f Allow a local-server copy to use -X and -A even if a --protocol-version
is forced, which makes some testing idioms easier.
2007-04-07 19:22:20 +00:00
Wayne Davison
16edf86595 The improved --xattrs option is landing on the trunk. 2007-04-07 17:22:25 +00:00
Wayne Davison
1c53e5171c Tweaked an error message and a comment. 2007-04-07 17:22:09 +00:00
Wayne Davison
63d83e9477 Improved push_dir() error reporting. 2007-03-25 17:01:48 +00:00
Wayne Davison
5463453489 The print now uses a more straight-forward map() instead of a join(). 2007-03-21 13:51:54 +00:00
Wayne Davison
108133689d Use relative directories, and note that the merge code is only
working because it is not yet using --inc-recursion.
2007-03-18 20:41:51 +00:00
Wayne Davison
46ad63b7cf Added a test of a multi-file copy from a nested directory using a
relative source path.
2007-03-18 20:40:01 +00:00
Wayne Davison
dbb20f6bc0 One more tweak. 2007-03-18 20:05:24 +00:00
Wayne Davison
25c2a6ac0e Fixed a multi-file, no-dir, relative copy, such as:
rsync -av lib/*.c /var/tmp/lib
2007-03-18 17:35:39 +00:00
Wayne Davison
161fba6903 Put the checksum seed at the end of the checksum2 buffer in md5 mode. 2007-03-18 06:28:51 +00:00
Wayne Davison
55edf18c42 Made a char* arg const. 2007-03-18 06:20:07 +00:00
Wayne Davison
a0456b9c46 Protocol 30 now uses MD5 checksums instead of MD4. 2007-03-18 06:00:53 +00:00
Wayne Davison
1a515b494b In option descriptions, the short form of --copy-dirlinks is -k, not -K. 2007-03-15 23:17:26 +00:00
Wayne Davison
33cd9ad54b I managed to duplicate the hang, so hopefully it's fixed now.
Let's restore the full test suite and find out.
2007-03-14 00:22:05 +00:00
Wayne Davison
896f046f79 Fixed more potential hang cases for incremental recursion. 2007-03-14 00:20:44 +00:00
Wayne Davison
b9d5eea5c6 Next step: allow protocol 30 to be used, but disallow the use
of incremental recursion.  If this still avoids the hanging, I
will need to try to track down how inc_recurse can deadlock.
2007-03-14 00:02:39 +00:00
Wayne Davison
5275029d11 Added an explicit option that will disallow the use of
incremental recursive mode (and an option to negate that).
2007-03-14 00:00:01 +00:00
Wayne Davison
271aeaa49e Next step: see if the hang returns with a partial restoration of
protocol 30.
2007-03-12 18:05:03 +00:00
Wayne Davison
91763a9c2f It looks like some of the compile-farm hosts are hanging on this test,
so let's try some remote-diagnostics (let's try protocol 29 first).
2007-03-12 04:56:15 +00:00
Wayne Davison
18438f0bac Changed the sending of device major/minor numbers in protocol 30 to
take fewer protocol bytes and use one less bit in the XMIT_* flags.
2007-03-12 04:33:30 +00:00
Wayne Davison
057f649fc9 When a hard-linked device is duplicating the data from the prior
device, we need to allocate 2 extra option slots for the device
numbers.
2007-03-11 22:02:26 +00:00
Wayne Davison
88467ec444 Don't enable ACLs on darwin until we figure out how they work. 2007-03-11 14:25:00 +00:00
Wayne Davison
1b897d50a9 Leave out two unneeded sys*_fd() functions due to their using
a function & struct that is not available in the rsync code.
2007-03-11 07:31:17 +00:00
Wayne Davison
d4a013edb7 We now compile on systems where ENOTSUP is not defined. 2007-03-11 07:21:07 +00:00
Wayne Davison
545584cb9a Leave SUPPORT_ACLS undefined instead of giving it a 0 value. 2007-03-11 07:13:11 +00:00
Wayne Davison
e5abce8e0d Silence a compiler warning about a printf() %d mismatch. 2007-03-11 06:50:48 +00:00
Wayne Davison
3060ca8d42 Temporarily skip this test as it is taking too long on the
compile farm at the moment.
2007-03-11 06:27:59 +00:00
Wayne Davison
ab14d01a0e Use the abbrevint30 routines in a few more places. 2007-03-11 05:59:46 +00:00
Wayne Davison
987838fd2c Make configure continue if ACL support is not found and the user
didn't explicitly ask for ACLs.
2007-03-11 05:54:21 +00:00
Wayne Davison
6d4e718f5f Moved the new static internal functions from rsync.h to io.h. 2007-03-11 05:43:55 +00:00
Wayne Davison
1c3344a105 The ACL support has arrived! This version has a brand new protocol
that makes it incompatible with all prior versions.  A patch will be
provided to allow talking with older (patched) rsync versions.
2007-03-11 00:13:34 +00:00
Wayne Davison
085e2fd588 Changed the code that cleans up the old nightly releases from
time-based to count-based (keeping the newest 10 items).
2007-03-08 02:00:48 +00:00
Wayne Davison
f41152d393 Decided that we don't really want the rule that preserves the
backup-suffix files to be perishable.
2007-03-05 17:08:00 +00:00
Wayne Davison
d0c59b0e88 A local server needs to process the auto-exclude rules since we don't
send the excludes over the socket for a local copy.
2007-03-04 14:56:22 +00:00
Wayne Davison
f49c837651 Mention the slight change to the auto-filter rules that are created
for the --backup option and the --partial-dir option.
2007-03-03 01:14:08 +00:00
Wayne Davison
c12895089c Moved a couple auto-filter rules from options.c into compat.c so
that we are sure to only apply the perishable filter modifier when
the receiving side is new enough to understand it.
2007-03-03 01:06:45 +00:00
Wayne Davison
27122338dc Make the auto-generated protect filters use the perishable flag so
that they don't stop a vanished directory from being removed.
2007-03-02 21:14:01 +00:00
Wayne Davison
d762dfe94b Mention a couple more changes. 2007-02-17 17:05:22 +00:00
Wayne Davison
c4750c2a07 Make sure that a newly-created destination directory gets the same
rules applied to it as other newly-created directories when --perms
wasn't specified.
2007-02-17 17:00:40 +00:00
Wayne Davison
3831f06319 - Moved the second send_extr_file_list() call to a better spot.
- Moved the FILECNT_LOOKAHEAD define into rsync.h.
2007-02-16 02:47:12 +00:00
Wayne Davison
be91bd81b8 Improved the incremental sending of file lists in two ways: (1)
when the sender gets an index of a file to send, we make sure to
send enough future file-list data relative to the new cur_flist
value before we send the data for the file transfer (ensuring that
the generator gets the data in a more timely manner), and (2) the
generator flushes the output socket after each file-list object
has completed its scan so that the sender knows in a more timely
manner that more list data is needed.
2007-02-16 02:35:31 +00:00
Wayne Davison
2a40b503c0 Make sure that the am_server variable is non-zero after parsing the
options we received over the socket.  (Thanks, Matt!)
2007-02-16 01:20:29 +00:00
Wayne Davison
ba2133d6ad Further modifications to the copyright comment section. 2007-02-04 14:54:58 +00:00
Wayne Davison
4f47fec04d Added a license comment to the top of the file. 2007-02-03 22:46:57 +00:00
Wayne Davison
ab3d6c6025 The "ndx" variable now holds the unique, over-the-wire value, not
a value that is relative to the cur_flist object.  This makes the
variable consistent with how the sender and the receiver use it.
2007-02-03 05:13:17 +00:00
Wayne Davison
121bfb2b4d The ndx arg passed to increment_active_files() is now the unique,
over-the-wire value, making it consistent with the ndx arg that
is passed to decrement_active_files().
2007-02-03 05:13:14 +00:00
Wayne Davison
100018b7cd Mention the year 2007 in the copyright declarations. 2007-01-31 21:46:49 +00:00
Wayne Davison
1ff66d4c68 Changed the main file-scan loop to not check for redo items when
in incremental recurse mode -- it is enough to check for them
when changing from one file-list to another.
2007-01-31 21:45:42 +00:00
Wayne Davison
87a34ce56a The code can now set cur_flist to NULL sooner than it used to, so the
flist_for_ndx() routine needs to work when cur_flist is NULL.
2007-01-30 03:57:55 +00:00
Wayne Davison
04c722d5e0 - Renamed done_cnt -> msgdone_cnt.
- Changed increment_active_files() to call check_for_finished_files()
  and to avoid calling both io_flush() and read_msg_fd() in the same
  iteration of a loop (since the former may have called the latter).
2007-01-30 03:57:52 +00:00
Wayne Davison
7730114b30 Moved the code that checks for finished file-lists, for finished "redo"
sends, and finished hard-links into check_for_finished_files(), a new
function that takes the place of check_for_finished_hlinks().  This
lets us signal the sender more rapidly when a file-list is done (which
ensures that it sends us more work to do in a timely manner), and also
avoids two potential deadlocks in the old code.
2007-01-30 03:57:48 +00:00
Wayne Davison
7a2fa0c2d3 Changed how send_extra_file_list() checks if we have enough future work. 2007-01-30 03:57:45 +00:00
Wayne Davison
4eeaa16253 Improved a sentence. 2007-01-30 03:37:47 +00:00
Wayne Davison
8dca155fca Some improvements from Matt. 2007-01-28 06:39:52 +00:00
Wayne Davison
2a5df86299 - Fixed a potential hang bug in wait_for_receiver() that could occur
if the io_flush() call happened to read the last message from the
  receiver, causing the read_msg_fd() call to deadlock.
- Fixed an error-looping problem when the server-side receiver failed
  to send a message down the error-msg pipe:  we no longer try to send
  a new error about this new failure down the same failing pipe.
- Make sure that we stop any deferring of forwarded messages in the
  generator when we are exiting with an error.
2007-01-27 16:30:33 +00:00
Wayne Davison
3ea6e0e7a1 Changed the variable "incremental" to "inc_recurse". 2007-01-27 14:56:09 +00:00
Wayne Davison
051ad69634 Improved the talk of --hard-link improvements. 2007-01-27 14:53:10 +00:00
Wayne Davison
744e63fb2a More extern tweaking. 2007-01-27 14:37:53 +00:00
Wayne Davison
cc7b86bf9b The last MSG_DONE from the receiver to the generator is now followed
by the stats.total_read value so that the generator can set its value
to that of the receiver.  This makes log_exit() log the right value
when we're on the server side.
2007-01-27 14:34:15 +00:00
Wayne Davison
8c18ebe81d Got rid of unused externs. 2007-01-27 14:26:19 +00:00
Wayne Davison
33689f4803 Added an extra paragraph to the --link-dest option to make it more
explicit that it is best used with an empty destination hierarchy.
2007-01-23 15:34:43 +00:00
Wayne Davison
424d369179 Paul's patch to silence some 64-bit compiler warnings. 2007-01-23 15:24:36 +00:00
Wayne Davison
d0221f1d2b Fixed handling of "redo" items in protocol 30. 2007-01-21 14:51:52 +00:00
Wayne Davison
3be97bf931 - Make sure that we can't write via io_flush() when msg_fd_in is
temporarily set to -1.
- Got rid of the msg2genr message cache.
2007-01-20 22:10:14 +00:00
Wayne Davison
4afab31607 We need to call msg2sndr_flush() in read_msg_fd() now. 2007-01-20 20:19:24 +00:00
Wayne Davison
be21e29c35 Make sure defer_forwarding_messages is set when msg_fd_in gets
set to -1.
2007-01-20 19:56:03 +00:00
Wayne Davison
c5b6e57a13 Fixed some typos Matt found. 2007-01-20 08:42:53 +00:00
Wayne Davison
ca947dea3e Moved the code that adds each file's length to stats.total_size
so that the delete code doesn't change the value.
2007-01-10 01:49:35 +00:00
Wayne Davison
2aea85ab54 Removed a couple items (one complete, one that we don't need). 2007-01-09 20:03:34 +00:00
Wayne Davison
05a41409b1 Mention that --prune-empty-dirs forces a non-incremental recursive scan. 2006-12-29 14:17:26 +00:00
Wayne Davison
7a28d18448 If prune_empty_dirs is set, don't set incremental. 2006-12-29 14:17:21 +00:00
Wayne Davison
1e05b590c4 Fixed a typo and improved a sentence. 2006-12-29 01:22:51 +00:00
Wayne Davison
ce5fddc3ed Added a sleep so that the --delete-delay action will always tweak
the directory time, and reveal any lack of dir-time touch-up.
2006-12-29 00:56:25 +00:00
Wayne Davison
fd3f5af2aa - Put directory retouching code into a separate function that
is now called for all our touch-up needs.
- Fixed a problem with --delete-delay interfering with the
  directory-time touch-up in incremental mode.
2006-12-29 00:55:28 +00:00
Wayne Davison
dde5b77226 - My use of readfd_unbuffered() in read_msg_fd() really needed to be
readfd() so that the buffer is never partially filled.
- Make sure that msg2genr_flush() does not flush any messages while
  the flist-forwarding is active.
- Changed io_flush() to honor its flush_it_all arg again.
2006-12-29 00:12:42 +00:00
Wayne Davison
f845ef7dec An incremental-recursion transfer can't switch from delete-delay to
delete-after.
2006-12-28 19:02:01 +00:00
Wayne Davison
9ae7a2cddb Use write_ndx() and read_ndx(). 2006-12-28 18:49:13 +00:00
Wayne Davison
8a65e0ce00 Added write_ndx() and read_ndx(), functions that allow us to transmit
fewer bytes when exchanging the file-list index values.
2006-12-28 18:49:08 +00:00
Wayne Davison
98b1689dcb Output a file-list message when verbose and using incremental recursion
mode.
2006-12-28 18:43:20 +00:00
Wayne Davison
012d1a01f5 Mention incremental recursion and change to --delete. 2006-12-28 16:40:24 +00:00
Wayne Davison
d9f46544a3 Document the incremental recursion algorithm and the change in the
--delete default.
2006-12-28 16:37:01 +00:00
Wayne Davison
42c6b13901 Restored the calling of send_file_entry() back to send_file_name()
(since the reason I had separated it no longer exists).
2006-12-28 15:43:30 +00:00
Wayne Davison
f1482c3391 Assign the owner and group using F_OWNER() and F_GROUP(). 2006-12-28 09:42:48 +00:00
Wayne Davison
5bb7348509 - Define F_OWNER() and F_GROUP() to be used for assigning the UID and GID.
- F_UID() is now defined to return a uid_t value.
- F_GID() is now defined to return a gid_t value.
2006-12-28 09:42:44 +00:00
Wayne Davison
4c9d5fef07 Repositioned a misplaced assignment. 2006-12-28 08:57:25 +00:00
Wayne Davison
5607803376 - Added a sleep to make sure that the preservation of the mtime on
implied directories is working.
2006-12-28 07:54:47 +00:00
Wayne Davison
76e0a49efe Handle slight differences in the output of protocol 30's incremental mode. 2006-12-28 07:54:44 +00:00
Wayne Davison
76a1013cc6 Use --delete-delay instead of --delete-after. 2006-12-28 07:54:41 +00:00
Wayne Davison
496c809f8c - Made match_uid(), match_gid(), recv_user_name(), and recv_group_name()
public functions.
- Made add_uid() and add_gid() return the name or NULL.
2006-12-28 07:54:37 +00:00
Wayne Davison
3ac830b9f9 A few minor tweaks to handle the newest variable names. 2006-12-28 07:54:34 +00:00
Wayne Davison
f3d6d4800b Handle the new incremental-recursion mode. 2006-12-28 07:54:31 +00:00
Wayne Davison
8ef246e0b5 - Handle the new incremental-recursion mode.
- Changed some function names to make them more consistent.
2006-12-28 07:54:27 +00:00
Wayne Davison
c7e6f84f89 New functions, variables, and file-list code to support the new
incremental-recursion mode.
2006-12-28 07:54:23 +00:00
Wayne Davison
fe04532ad2 New support function: change_local_filter_dir(). 2006-12-28 07:54:19 +00:00
Wayne Davison
e4b619b46d - Choose --delete-before or --delete-during depending on protocol version.
- Set incremental-recursion mode, if possible.
- Protocol 30 gets generator->sender messages enabled.
2006-12-28 07:54:16 +00:00
Wayne Davison
9ec3828b03 Some new defines for incremental-recursion mode. 2006-12-28 07:54:13 +00:00
Wayne Davison
e0e3203156 - Changes to handle new default of --delete-during for --delete.
- Allow -H to be repeated.
2006-12-28 07:54:10 +00:00
Wayne Davison
edb977215b Only append_mode > 0 now indicates option is enabled. 2006-12-28 07:54:07 +00:00
Wayne Davison
18233a170e Only sparse_files > 0 now indicates option is enabled. 2006-12-28 07:54:04 +00:00
Wayne Davison
283887d777 Neaten up use of uid_t/gid_t variable types. 2006-12-28 07:08:13 +00:00
Wayne Davison
c2f0e4d965 Don't include MATCHFLG_PERISHABLE in CVS-exclude handling unless
we're talking protocol 30 or above.
2006-12-28 06:27:22 +00:00
Wayne Davison
8576397c3e Fix the building of mkrounding$(EXEEXT) when building outside the
source directory (provided by Art Haas).
2006-12-27 21:40:16 +00:00
Wayne Davison
c09af06d0c Made the int_byte_cnt[] array 75% smaller. 2006-12-27 17:43:51 +00:00
Wayne Davison
ded73ed90f Ignore all conftest* items, as Matt suggested. 2006-12-27 17:36:57 +00:00
Wayne Davison
f335eb1f83 Fix usage message. 2006-12-26 05:56:38 +00:00
Wayne Davison
7afa34fd27 Test --only-write-batch option. 2006-12-26 05:29:05 +00:00
Wayne Davison
1f56188f8c Can just test ignore_errors w/o lp_ignore_errors(module_id) now. 2006-12-25 17:49:23 +00:00
Wayne Davison
3162ea6f67 Set ignore_errors variable based on lp_ignore_errors(module_id). 2006-12-25 17:49:19 +00:00
Wayne Davison
327c559aff Improved the new --pasword-file error message. 2006-12-24 06:13:08 +00:00
Wayne Davison
99effefc81 Fixed a thinko in the last news item. 2006-12-24 05:47:21 +00:00
Wayne Davison
e8dad39518 Mention checking of --password-file's use. 2006-12-24 01:30:44 +00:00
Wayne Davison
09a54c399c Make the --password-file option's summary even better. 2006-12-24 01:30:24 +00:00
Wayne Davison
9586e59370 Improved the docs for the --password-file option. 2006-12-24 00:58:30 +00:00
Wayne Davison
ce455b03e7 Improved the summary of the --password-file option. 2006-12-24 00:58:24 +00:00
Wayne Davison
a39da29ac5 If the user specified --password-file without using daemon mode,
complain and die.
2006-12-24 00:58:21 +00:00
Wayne Davison
794a0b6c25 Make use of the SHORT_SUM_LENGTH define. 2006-12-23 23:57:16 +00:00
Wayne Davison
1b81f797a2 Fixed a problem with the output of %f for non-daemon rsyncs. 2006-12-23 20:48:29 +00:00
Wayne Davison
889ae39d7a Mention the %f fix. 2006-12-23 20:46:33 +00:00
Wayne Davison
5f4e991c70 Fixed the item numbers in the regex comment. 2006-12-20 00:50:17 +00:00
Wayne Davison
c96f6eb584 Call SIGACTION() instead of signal(). 2006-12-18 07:24:24 +00:00
Wayne Davison
e10664c5e8 Moved the write_stream_flags() call from io.c into main.c so that
it gets called before the transfer starts (thus ensuring that it
can write out un-tweaked values of preserver_[ug]id vars).
2006-12-18 06:56:30 +00:00
Wayne Davison
99a957d3f4 Renamed flist_extra_cnt to file_extra_cnt. 2006-12-18 06:56:26 +00:00
Wayne Davison
658a63694b Got rid of the "tweaked" versions of the uid and gid vars. 2006-12-18 06:56:23 +00:00
Wayne Davison
30e50494bb Tweaked the output a little. 2006-12-18 06:41:00 +00:00
Wayne Davison
719985cb9c A few more minor tweaks. 2006-12-17 04:42:33 +00:00
Wayne Davison
2d2414f39e - We now define int16 and uint16.
- Make use of the [u]int{16,32,64}_t types, if they're around.
2006-12-17 02:05:11 +00:00
Wayne Davison
edb4ba5fdb We now check for these: int16_t, uint16_t, int32_t, uint32_t, and int64_t. 2006-12-17 01:59:03 +00:00
Wayne Davison
007996b40d Got rid of the code that sorted based on struct idev objects since
we always use a hardlinked group-number now.
2006-12-17 00:40:39 +00:00
Wayne Davison
dbd9ea3e5a Use F_ROOTDIR() in place of dir.root. 2006-12-17 00:40:36 +00:00
Wayne Davison
2ef0340517 Use F_DEPTH() in place of dir.depth. 2006-12-17 00:40:33 +00:00
Wayne Davison
9d737ecb7a Got rid of the hlink_pool in favor of using the new hashtable code
on the receiving side.  This allows us to always use a 32-bit number
to identify the hardlink clusters, even on a system where pointers
are 64-bits.  Also made changes to handle the use of F_ROOTDIR() and
F_DEPTH() instead of the old union that wasted space on the
receiving side when pointers are 64-bits.
2006-12-17 00:40:28 +00:00
Wayne Davison
bd6edd3fa2 - Got rid of "struct idev".
- Use just the 32-bit numbers in the file_extras union.
- Re-ordered the items in the file_struct to avoid padding
  on systems with 64-bit pointers.
- Got rid of the "dir" union in the file_struct, making the
  two items into "extras": F_DEPTH() for the receiving side,
  and F_ROOTDIR() for the sending side.
- Added PTR_EXTRA_LEN define.
- Got rid of F_HL_IDEV() define.
2006-12-17 00:40:24 +00:00
Wayne Davison
6eee13cf58 Moved the flist_extra_cnt stuff from options.c to compat.c so that
the values will be computed separately for the sender and the
receiver.
2006-12-17 00:40:21 +00:00
Wayne Davison
9602b5cfbd - Ensure that mkrouding gets rebuilt when rsync.h changes.
- Added an easy way to run the tests using protocol 29.
2006-12-17 00:40:18 +00:00
Wayne Davison
48ffc11e9c Make the error messages a little clearer. 2006-12-16 23:14:59 +00:00
Wayne Davison
5a3e9ff608 Output some info about the size of our structures. 2006-12-16 21:11:58 +00:00
Wayne Davison
aac5cab80b Changed the static file_struct var to match the changes in rsync.h. 2006-12-16 19:24:17 +00:00
Wayne Davison
a3e18c763a Use the new rounding.h file to optionally round up the count of
extra values we put at the start of the file_struct.  Also, deal
with the extras variable no longer being in the file_struct.
2006-12-16 19:24:14 +00:00
Wayne Davison
403dbc1377 Build & run mkrounding to make the rounding.h file used by flist.c.
Also, clean up the new items.
2006-12-16 19:24:11 +00:00
Wayne Davison
5b30412c68 Moved the file_extra union out of the file_struct. 2006-12-16 19:24:08 +00:00
Wayne Davison
d5833800a8 New file to figure out if a system has any rounding needs when
prepending extra values at the start of the file_struct.
2006-12-16 19:24:05 +00:00
Wayne Davison
8d3a785fa5 Added mkrounding and rounding.h. 2006-12-16 19:24:02 +00:00
Wayne Davison
3a5a7de6c9 Mention hard-link memory savings and byte-transfer savings. 2006-12-16 07:39:53 +00:00
Wayne Davison
c58c1dc446 Added a basename var to file_struct at the end, making it clearer
where the basename exists without actually changing how the data
is organized.
2006-12-16 07:18:41 +00:00
Wayne Davison
eefe189e1d Changed the test for the 2.6.8 bug to preserve owner and group. 2006-12-16 02:18:44 +00:00
Wayne Davison
f05c801194 Moved the calls to init_hard_links() into flist.c. 2006-12-15 22:31:16 +00:00
Wayne Davison
c905bf37f6 Added a simple hashtable routine for hashing st_dev and st_ino info
on the sending side, and the support routines for the receiving side
that handle using a "group number" for each hard-link cluster rather
than having to manage a pool of dev+inode data. (For protocol 30)
2006-12-15 22:31:13 +00:00
Wayne Davison
8cae71ebc3 For protocol 30, the sender uses the new idev_node() hashfile
routine to keep track of which item is the first one in a particular
hard-link cluster.  It then abbreviates the sending of any follow-on
items in the cluster, reducing transfer bytes.  It also omits the
sending of any dev+inode data to the receiver, saving even more xfer
bytes (since the receiver can associate the entries based on the the
group's index number that is sent when abbreviating an entry).
2006-12-15 22:31:10 +00:00
Wayne Davison
14d776ff0c - The XMIT_SAME_DEV define is now pre-protocol-30 specific.
- Added XMIT_HLINK_FIRST define.
- Added struct idev_node.
- Added F_HL_GNUM() for protocol 30 (used in place of F_HL_IDEV()).
2006-12-15 22:31:07 +00:00
Wayne Davison
c7565dad84 Renamed XMIT_HAS_IDEV_DATA to XMIT_HLINKED. 2006-12-14 22:38:21 +00:00
Wayne Davison
b7cfb9e2c0 Renamed the F_*HLINK* macros to make their purpose clearer. 2006-12-13 15:36:15 +00:00
Wayne Davison
0d152437df Tweaked the option-passing code's delete logic to make it cleaner. 2006-12-13 14:52:59 +00:00
Wayne Davison
6aef83c97d Cast FILE_STRUCT_LEN & EXTRA_LEN to int for rprintf(). 2006-12-12 20:42:06 +00:00
Wayne Davison
225aeca346 Use new BITS_EQUAL() define. 2006-12-12 20:17:05 +00:00
Wayne Davison
0a62f5f382 Added BITS_EQUAL() define. 2006-12-12 20:17:02 +00:00
Wayne Davison
234844915e Removed last reference to "struct hlist". 2006-12-12 15:01:57 +00:00
Wayne Davison
263d3bfb40 Neaten some function formatting. 2006-12-12 14:58:10 +00:00
Wayne Davison
bf466c0f82 Provide alternate F_LENGTH() define for systems with no 64-bit type. 2006-12-12 14:55:21 +00:00
Wayne Davison
8b58407586 Mention fix for -vv --stats. 2006-12-10 21:56:37 +00:00
Wayne Davison
64119c792d Added MSG_CLIENT to the acceptable messages the generator can
get from the receiver.
2006-12-10 14:55:44 +00:00
Wayne Davison
8388e011ae Added MSG_CLIENT to the msgcode enum. 2006-12-10 14:54:08 +00:00
Wayne Davison
0fddbd8a09 A minor format tweak. 2006-12-09 17:35:36 +00:00
Wayne Davison
badb8c24b9 Handle the new output from the hard-link code, including a fix
for a long-standing bug combinding -H with --compare-dest.
2006-12-09 00:24:11 +00:00
Wayne Davison
bfd3137246 - Added FLAG_HLINK_DONE.
- Added BITS_SET() and BITS_SETnUNSET() defines.
- Got rid of unused HL_* defines.
- Got rid of no-longer-needed struct hlist.
- Changed F_HL_LIST() to F_HL_PREV().
- Added F_NOT_HLINK_FIRST() and F_NOT_HLINK_LAST().
- Got rid of WITH_HLINK and WITHOUT_HLINK.
- Got rid of the hlink_pool in the file list.
2006-12-09 00:24:08 +00:00
Wayne Davison
6de0d06259 Got rid of the pool-destroy call since this is not around anymore. 2006-12-09 00:24:05 +00:00
Wayne Davison
89d730a098 Call the new hard-link init functions. 2006-12-09 00:24:01 +00:00
Wayne Davison
18979194cf - Use the revamped hard-link functions.
- Turned maybe_ATTRS_REPORT var into a global for use by hlink.c.
2006-12-09 00:23:58 +00:00
Wayne Davison
aadc84d359 - Revamped the hard-link algorithm to save memory.
- Improved the function names.
- Improved a few variable names.
- Got rid of the "is a hard link" message in favor of the normal status
  messages for files (e.g. --itemize-changes indicates hard-links).
- Fixed a long-standing bug when combining -H with --compare-dest.
- Made sure that code compiles when hard-linking is not available.
2006-12-09 00:23:55 +00:00
Wayne Davison
9d155ecd12 Changed the hlink_pool variable to be a global since only the main
file list ever has a pool for hard-linking.
2006-12-09 00:23:51 +00:00
Wayne Davison
60af946576 Explicitly cast the length values down to an uint32 so that some
compilers don't complain about the value getting smaller.
2006-12-08 21:02:11 +00:00
Wayne Davison
ca0e8296bc Get rid of some signed/unsigned-comparison compiler warnings. 2006-12-08 20:58:51 +00:00
Wayne Davison
c4a28da3ad Use --delete-delay instead of --delete-after. 2006-12-08 20:47:09 +00:00
Wayne Davison
20319fd9ed - The --delete-delay code now does its own output buffering. This
allows us to delay opening a temp file to hold the list of deletions
  until we overflow the buffer (and thus, it's not usually needed).
- Fall back to doing a --delete-after pass if the --delete-delay
  code has a temp-file-writing failure.
2006-12-08 20:42:45 +00:00
Wayne Davison
01d29d7b02 Fixed --delete-delay by making the fprintf() output an unsigned short
for the mode.
2006-12-08 15:10:12 +00:00
Wayne Davison
1183260426 Added missing initialization of new solo_file variable. 2006-12-07 06:22:22 +00:00
Wayne Davison
07613def0a Some minor format tweaks. 2006-12-07 03:31:44 +00:00
Wayne Davison
c2a608d9f1 - Use renamed hard-link defines: F_HL_IDEV() and F_HL_LIST(). 2006-12-07 03:31:41 +00:00
Wayne Davison
49b86442ff - Set "solo_file" bool and use that for improved clarity.
- Use the new device defines: F_RDEV_P(), DEV_MAJOR(), and DEV_MINOR().
2006-12-07 03:31:38 +00:00
Wayne Davison
4785cd43d1 - Use the new device defines: F_RDEV_P(), DEV_MAJOR(), and DEV_MINOR().
- Use renamed F_HL_IDEV() define.
2006-12-07 03:31:34 +00:00
Wayne Davison
e238c9977d Use the new device defines: F_RDEV_P(), DEV_MAJOR(), and DEV_MINOR(). 2006-12-07 03:31:31 +00:00
Wayne Davison
b37b7c9949 - Added a signed number to the flist_extras union.
- Renamed F_IDEV() to F_HL_IDEV() and F_HLIST() to F_HL_LIST().
- Changed device defines to be: F_RDEV_P(), DEV_MAJOR(), and DEV_MINOR().
2006-12-07 03:31:28 +00:00
Wayne Davison
f7d7fb381d Improved the format of the debug output for mknod(). 2006-12-07 02:37:42 +00:00
Wayne Davison
3481bdf493 Mention waitpid() fix (which helps pre-xfer exec). 2006-12-06 17:27:47 +00:00
Wayne Davison
d365e22967 The wait_process() call now handles EINTR. 2006-12-06 17:21:59 +00:00
Wayne Davison
d02363609a If the pre-xfer exec failed with -1, output the strerror()
from the waitpid() call.
2006-12-06 16:56:19 +00:00
Wayne Davison
1e1ca25343 #ifdef calls to hard-link functions. 2006-12-06 01:32:17 +00:00
Wayne Davison
a2ebbffca7 - Make some char* pointers const.
- Tweaked a couple variable names.
- Changed the #ifdefs to not define any hard-link functions
  when hard-linking is disabled.
2006-12-06 01:26:11 +00:00
Wayne Davison
0395130c06 Changed i -> ndx in several variables. 2006-12-06 00:55:33 +00:00
Wayne Davison
b8c167e804 F_SUM() needed to use HLINK_BUMP(). 2006-12-06 00:52:34 +00:00
Wayne Davison
17026f2741 Handle the FLAG_LENGTH64 flag in unmake_file(). 2006-12-05 17:45:29 +00:00
Wayne Davison
112d728f48 Use the latest F_*() accessors. 2006-12-05 15:59:58 +00:00
Wayne Davison
96293cf991 Saved 9 more bytes per file in a typical transfer by making the length
32 bits by default, by removing the basename pointer, and by making the
mode value a unsigned short.
2006-12-05 15:59:53 +00:00
Wayne Davison
f0fbf1d670 Changed flist_extra_ndx into flist_extra_cnt. 2006-12-05 15:59:49 +00:00
Wayne Davison
7a821d518b Tweaked some externs. 2006-12-05 15:59:46 +00:00
Wayne Davison
663b2857eb Use new send_msg_int() function. 2006-12-04 02:07:37 +00:00
Wayne Davison
155d9206a4 Added send_msg_int() function. 2006-12-04 02:07:30 +00:00
Wayne Davison
6b2a3d5de6 Moved an extern. 2006-12-03 07:58:12 +00:00
Wayne Davison
82ad07c418 - Typical tranfers now save 12-20 bytes per file because several vars
were moved out of file_struct into an optional member-var setup.
- Renamed and reorganized the FLAG_* defines.
- Use NDX_DONE instead of a literal -1 when sending/checking the
  end-of-phase index value.
2006-12-03 06:44:16 +00:00
Wayne Davison
d144e43bb3 Restored write_ndx_and_attrs() and made it public. 2006-12-02 16:17:11 +00:00
Wayne Davison
d2aee174e6 Moved write_ndx_and_attrs() to sender.c and made it public. 2006-12-02 16:16:54 +00:00
Wayne Davison
20f0d0f9b9 Moved write_ndx_and_attrs() too. 2006-12-02 16:13:02 +00:00
Wayne Davison
b675ba6f79 Added a couple externs. 2006-12-02 16:11:33 +00:00
Wayne Davison
d1c178dd53 Moved read_item_attrs() from sender.c to rsync.c since the function
is used by both the sender and the receiver.
2006-12-02 16:08:59 +00:00
Wayne Davison
d619ff1376 Change the format/order of the capabilities --version outputs. 2006-12-01 18:29:18 +00:00
Wayne Davison
db0f7613e1 Got rid of an incorrect comment. 2006-11-28 19:34:01 +00:00
Wayne Davison
45d8bfe09e Added some more "const" prefixes to some "char *" vars. 2006-11-28 19:31:41 +00:00
Wayne Davison
d521e1c2a1 - Use write_shortint() to send the 2 bytes in an extended flag.
- Improved a comment.
2006-11-24 20:21:13 +00:00
Wayne Davison
4ea4acf17b - Added checking of SIZEOF_INT64 to the new code in read_longint().
- Improved the SIZEOF_INT64 checking code in write_longint().
2006-11-24 18:35:00 +00:00
Wayne Davison
3a993aa4bf - Changed {read,write}_shortint() to use unsigned short.
- Added explicit char-casting to new long-int code.
2006-11-24 17:28:57 +00:00
Wayne Davison
c7871d9892 Document the latest changes. 2006-11-24 08:46:21 +00:00
Wayne Davison
482f48cca9 - Fixed a bug when sending a negative 64-bit number (which may not
be needed, but it at least works right now).
- Improved the transmission of 32-bit negative numbers on systems
  where the 32-bit type is larger than 32 bits.
- Changed the sending of 64-bit numbers for protocol 30:  we send
  them in MSB-first order with the number of bytes used in the
  transmission encoded into the earliest bits.  This lets us save
  transmitted bytes for both small and large numbers.  The new
  method sends from 3 to 9 bytes, the old sent either 4 or 12.
2006-11-24 08:38:44 +00:00
Wayne Davison
36e6594dce Added some defines for sending variable-sized MSB-first numbers. 2006-11-24 08:22:23 +00:00
Wayne Davison
e17883827b Silenced a compiler warning. 2006-11-23 04:16:48 +00:00
Wayne Davison
37a4386d2c Fix a unused-variable compiler warning. 2006-11-23 03:28:58 +00:00
Wayne Davison
fd0a130c14 Document the new --delete-delay option. 2006-11-22 20:52:51 +00:00
Wayne Davison
5e77efaf41 - Implement new --delete-delay option.
- Tweaked a variable name in delete_item().
2006-11-22 20:51:03 +00:00
Wayne Davison
b0cacef14b Added parsing for --delete-delay. 2006-11-22 20:49:23 +00:00
Wayne Davison
b20830b338 Made get_tmpname() non-static. 2006-11-22 20:48:04 +00:00
Wayne Davison
c63625d41a Switch over to testing --remove-source-files, not *-sent-*. 2006-11-22 16:34:25 +00:00
Wayne Davison
7de7b49f6c Don't define NORETURN for older gcc versions. 2006-11-21 22:29:33 +00:00
Wayne Davison
d0d0e41fd2 Mention latest changes. 2006-11-21 19:08:59 +00:00
Wayne Davison
2a28dd32fd The exclude code wasn't sending the MATCHFLG_NEGATE (!) char to the
other side.
2006-11-21 17:46:54 +00:00
Wayne Davison
65e83e097c Don't set an "rc" var that we aren't going to use. 2006-11-21 08:37:28 +00:00
Wayne Davison
4f37559232 Avoid a compiler warning about setting "len" without using it. 2006-11-21 08:37:06 +00:00
Wayne Davison
604dbf6d94 Make the file_list stats value an int64. 2006-11-21 08:36:48 +00:00
Wayne Davison
53593085cf - Use an explicit cast when a value gets stored in a smaller var.
- The msgtype var should have been an enum.
2006-11-21 08:36:31 +00:00
Wayne Davison
eb0144d79b Output the size of the file list using human_num(). 2006-11-21 08:36:15 +00:00
Wayne Davison
54b0dfa0f7 Explicitly cast the tag value in read_msg_fd() to an enum. 2006-11-21 08:36:06 +00:00
Wayne Davison
264042760b Use an explicit cast when a value gets stored in a smaller var. 2006-11-21 08:35:58 +00:00
Wayne Davison
1e999f9f1b The call to do_chmod() needed to be conditional. 2006-11-21 08:35:22 +00:00
Wayne Davison
f9b66bc464 Fixed a problem with the new iconv const check. 2006-11-20 19:12:35 +00:00
Wayne Davison
60d465dbdd Use the new ICONV_CONST definition. 2006-11-20 18:17:48 +00:00
Wayne Davison
3ebdd3c7fc Added a test to figure out if iconv() takes a const char **. 2006-11-20 18:17:17 +00:00
Wayne Davison
f0fa8c6df2 Moved the options_rejected label to avoid a compiler warning on
some systems.
2006-11-19 04:39:35 +00:00
Wayne Davison
9d33e6f7cf Use rwrite() to output the err_msg string. 2006-11-19 04:37:52 +00:00
Wayne Davison
4a19c3b254 Added "const" to appropriate char pointers. 2006-11-19 00:23:21 +00:00
Wayne Davison
4743f0f41b Some bf(...) tweaks. 2006-11-14 07:56:05 +00:00
Wayne Davison
0abe148fd9 - Use double quotes for a quoted string.
- Some bf(...) tweaks.
2006-11-14 07:55:47 +00:00
Wayne Davison
39411fa876 Added: also tweak single-/double-quotes and em-dashes. 2006-11-14 07:54:26 +00:00
Wayne Davison
662fd70b54 Changed name of tweak_manpage script. 2006-11-14 07:48:56 +00:00
Wayne Davison
cd87e2f59a Turned the char * vars flist_dir and lastdir into const char * vars. 2006-11-13 00:27:10 +00:00
Wayne Davison
2c70847654 Turned the char * args to push_dir() and pop_dir() into const char *. 2006-11-13 00:27:04 +00:00
Wayne Davison
eaf895e6ef Turned the char *dir.root var in struct file_struct into a const char *. 2006-11-13 00:27:00 +00:00
Wayne Davison
149a78e33f Ignore a time-setting error on a symlink (which is only attempted
on a system with lutimes() anyway).
2006-11-12 21:18:26 +00:00
Wayne Davison
88897638a9 Tweaked a couple comments. 2006-11-11 17:09:32 +00:00
Wayne Davison
c575f8ce87 Document the new p (perishable) filter modifier. 2006-11-11 17:01:58 +00:00
Wayne Davison
5303941021 If ignore_perishable is set, increment a count of all excluded
items found by make_file().
2006-11-11 16:44:22 +00:00
Wayne Davison
c0f1e57b51 Added the MATCHFLAG_PERISHABLE flag. 2006-11-11 16:43:13 +00:00
Wayne Davison
ccdb23bb90 - Added the 'p' (perishable) flag to the filter rules, as suggested
by Matt.
- If ignore_perishable is set, we ignore all perishable rules.
- Mark all default-cvsignore rules as perishable (e.g. excludes such
  as *.o CVS .svn/ will not prevent a directory from being deleted).
2006-11-11 16:39:57 +00:00
Wayne Davison
146c2c368c - Restored some of Matt's suggested logic that I left out, as it
is needed to get --dry-run to output appropriately.
- Got rid of DR_PINNED from the enum delret.
- Set a flag when we're deleting outside the transfer hierarchy and
  initialize a counter that flist.c will use to count excluded files.
2006-11-11 16:39:02 +00:00
Wayne Davison
60cc01a6c6 When make_file() gets a stat() error on a file, the check-for-
exclusion-before-reporting-an-error code allows a dir-specific
rule to match the unknown file, not just a non-dir rule.
2006-11-11 15:34:31 +00:00
Wayne Davison
f5761a342b - Make delete_dir_contents() use less stack by recursing directly
to itself, and then calling delete_item() w/o DEL_RECURSE.
- Fixed the return value handling of delete_dir_contents().
2006-11-11 14:45:00 +00:00
Wayne Davison
caf8299e2e Tweaked an exit_cleanup() value. 2006-11-11 08:01:40 +00:00
Wayne Davison
c6fadc0ee1 My adaptation of Matt's cleanup of the delete_item() code.
The new code splits out part of the directory deletion into
its own function, delete_dir_contents(), and it outputs more
warnings when something could not be deleted.
2006-11-11 07:03:57 +00:00
Wayne Davison
2dc3db2a3e Docment that --max-delete=0 now works. 2006-11-11 05:09:22 +00:00
Wayne Davison
771d0add8f Die if we sent --max-delete=0 to a receiving side that is too old. 2006-11-11 05:09:17 +00:00
Wayne Davison
e5e85283a9 Allow --max-delete=0 (zero used to be ignored). 2006-11-11 05:09:14 +00:00
Wayne Davison
21068d8e87 Increased the PROTOCOL_VERSION to 30. 2006-11-11 05:09:10 +00:00
Wayne Davison
4d2ea5a838 Mention another internal change. 2006-11-10 15:39:03 +00:00
Wayne Davison
9ba53f26a3 Test --del too. 2006-11-10 15:36:15 +00:00
Wayne Davison
3aeedbfd11 Fixed the hard-linking of symlinks test (we need to use a symlink
to a non-existent file for the test to work right).
2006-11-10 07:49:02 +00:00
Wayne Davison
989b0b8802 Changed how we deal with the alternate-dest directory because
some systems change the time on a directory that gets moved.
2006-11-10 07:37:51 +00:00
Wayne Davison
b2e4811db2 Changed two more references to "st" to "real_st" in the dir-handling
code.
2006-11-10 07:17:20 +00:00
Wayne Davison
b467495cd0 - Fixed a problem where the real stat struct for a newly-created
root-of-transfer directory could get overwritten by the check
  for basis dirs.
- Fixed a potential problem where the stat struct for a new dir
  could get passed uninitialized to delete_in_dir().
2006-11-10 07:13:21 +00:00
Wayne Davison
3b8ed84245 If the OS can't hard-link a symlink, tweak the expected output
when using --link-dest.
2006-11-10 06:27:35 +00:00
Wayne Davison
3a72cc2929 Mention latest bug fixes. 2006-11-10 05:07:08 +00:00
Wayne Davison
c202424a03 Changed to reflect new (more correct) output of what updating is
happening.
2006-11-10 05:07:05 +00:00
Wayne Davison
083f75ee42 Improved to test --link-dest (when hard-linking of devices works). 2006-11-10 05:07:02 +00:00
Wayne Davison
45760f5f05 Allow all itemize types to change all-dots (no changes) into spaces. 2006-11-10 05:06:59 +00:00
Wayne Davison
116a4769c1 - Improved try_dests_non() so that it works with all non-regular
files (including dirs).
- Changed the directory-creating code to call try_dests_non() when a
  --*-dest option is used.
- Revamped the device/special-files code to have the same logic as
  the symlink code, making it both simpler and more correct.
- All the above makes us output changes for all items consistently
  when a --*-dest option is used.
- Fixed an output bug in try_dests_reg() and try_dests_non() when
  -ii is enabled (we use to fail to output unchanged files).
2006-11-10 05:06:56 +00:00
Wayne Davison
1e4f5f6342 Added flag ITEM_MATCHED. 2006-11-10 05:06:53 +00:00
Wayne Davison
a19d285ae3 Changed strcat() calls to strlcat(). 2006-11-10 03:34:51 +00:00
Wayne Davison
564782ba95 Disable POPT_WCHAR_HACK for now. 2006-11-09 02:55:32 +00:00
Wayne Davison
2dc7b8bd0e Got rid of type-casting into isFOO() and toFOO() functions by
using static inline functions that take a signed char pointer.
2006-11-09 02:39:29 +00:00
Wayne Davison
e0930845ce Improved the vmefail() code. 2006-11-09 02:37:38 +00:00
Wayne Davison
cf81788366 Fixed a problem with the xstrdup() change. 2006-11-09 02:36:03 +00:00
Wayne Davison
89a0e3a927 Get rid of the last strcpy() call by using an static inline function. 2006-11-09 02:34:17 +00:00
Wayne Davison
a8facdc090 Use a new isSpace() inline function to call isspace() safely
when using a signed character pointer.
2006-11-09 02:14:38 +00:00
Wayne Davison
c5e29261f3 Need to include lib/snprintf.o when building wildtest. 2006-11-09 01:58:28 +00:00
Wayne Davison
1acb2e15b4 Changed _ABS to be defined as MY_ABS. 2006-11-09 01:55:17 +00:00
Wayne Davison
06898c80d9 Got rid of code to twiddle _ABS. 2006-11-09 01:54:59 +00:00
Wayne Davison
684576ff45 Moved definition of DBL_EPSILON. 2006-11-09 01:51:57 +00:00
Wayne Davison
574a24a2ec Try a full prototype for alloca() for those systems that need it. 2006-11-09 01:34:36 +00:00
Wayne Davison
9775d6ab66 - Define snprintf() when needed.
- Improved the compatibility of the standard includes.
2006-11-09 01:26:27 +00:00
Wayne Davison
2b916250d8 The Mac version of GCC can now handle __attribute__ . 2006-11-09 01:07:35 +00:00
Wayne Davison
2955529bb4 Rolling over the NEWS file for the next version. 2006-11-09 01:06:30 +00:00
Wayne Davison
d094b5eb3c Change the version for new CVS work. 2006-11-09 00:59:58 +00:00
Wayne Davison
bc93ee842f - Upgraded popt to version 1.10.2.
- Modified all sprintf() and strcpy() calls to use snprintf()
  and strlcpy().
2006-11-09 00:57:55 +00:00
119 changed files with 16602 additions and 4984 deletions

View File

@@ -6,8 +6,7 @@ config.cache
config.h
config.log
config.status
conftest.c
conftest.log
conftest*
dox
getgroups
gmon.out
@@ -16,10 +15,11 @@ shconfig
testdir
tests-dont-exist
testtmp
testtmp.*
tls
trimslash
t_unsafe
wildtest
getfsdev
.rsync-filter
mkrounding
rounding.h

848
COPYING
View File

@@ -1,285 +1,626 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
TERMS AND CONDITIONS
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
0. Definitions.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
"This License" refers to version 3 of the GNU General Public License.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
A "covered work" means either the unmodified Program or a work based
on the Program.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
1. Source Code.
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
The Corresponding Source for a work in source code form is that
same work.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
13. Use with the GNU Affero General Public License.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
14. Revised Versions of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
NO WARRANTY
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
15. Disclaimer of Warranty.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
@@ -287,15 +628,15 @@ free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
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
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
@@ -304,37 +645,30 @@ the "copyright" line and a pointer to where the full notice is found.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
along with this program. If not, see <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.

View File

@@ -26,27 +26,29 @@ VERSION=@VERSION@
.SUFFIXES:
.SUFFIXES: .c .o
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 lib/pool_alloc.o @LIBOBJS@
HEADERS=byteorder.h config.h errcode.h proto.h rsync.h ifuncs.h lib/pool_alloc.h
LIBOBJ=lib/wildmatch.o lib/compat.o lib/snprintf.o lib/mdfour.o lib/md5.o \
lib/permstring.o lib/pool_alloc.o lib/sysacls.o lib/sysxattrs.o @LIBOBJS@
ZLIBOBJ=zlib/deflate.o zlib/inffast.o zlib/inflate.o zlib/inftrees.o \
zlib/trees.o zlib/zutil.o zlib/adler32.o zlib/compress.o zlib/crc32.o
OBJS1=rsync.o generator.o receiver.o cleanup.o sender.o exclude.o util.o \
main.o checksum.o match.o syscall.o log.o backup.o
OBJS2=options.o flist.o io.o compat.o hlink.o token.o uidlist.o socket.o \
fileio.o batch.o clientname.o chmod.o
OBJS1=flist.o rsync.o generator.o receiver.o cleanup.o sender.o exclude.o \
util.o main.o checksum.o match.o syscall.o log.o backup.o
OBJS2=options.o io.o compat.o hlink.o token.o uidlist.o socket.o hashtable.o \
fileio.o batch.o clientname.o chmod.o acls.o xattrs.o
OBJS3=progress.o pipe.o
DAEMON_OBJ = params.o loadparm.o clientserver.o access.o connection.o authenticate.o
popt_OBJS=popt/findme.o popt/popt.o popt/poptconfig.o \
popt/popthelp.o popt/poptparse.o
OBJS=$(OBJS1) $(OBJS2) $(OBJS3) $(DAEMON_OBJ) $(LIBOBJ) $(ZLIBOBJ) @BUILD_POPT@
TLS_OBJ = tls.o syscall.o lib/compat.o lib/snprintf.o lib/permstring.o
TLS_OBJ = tls.o syscall.o lib/compat.o lib/snprintf.o lib/permstring.o lib/sysxattrs.o @BUILD_POPT@
# Programs we must have to run the test cases
CHECK_PROGS = rsync$(EXEEXT) tls$(EXEEXT) getgroups$(EXEEXT) getfsdev$(EXEEXT) \
trimslash$(EXEEXT) t_unsafe$(EXEEXT) wildtest$(EXEEXT)
CHECK_SYMLINKS = testsuite/chown-fake.test testsuite/devices-fake.test
# Objects for CHECK_PROGS to clean
CHECK_OBJS=getgroups.o getfsdev.o t_stub.o t_unsafe.o trimslash.o wildtest.o
@@ -74,6 +76,16 @@ rsync$(EXEEXT): $(OBJS)
$(OBJS): $(HEADERS)
flist.o: rounding.h
rounding.h: mkrounding$(EXEEXT)
./mkrounding$(EXEEXT) >rounding.h
mkrounding$(EXEEXT): mkrounding.c rsync.h
@sed '1,/^struct file_struct/d; /^}/,$$d' <$(srcdir)/rsync.h >mkrounding.h
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ -I. $(srcdir)/mkrounding.c
@rm mkrounding.h
tls$(EXEEXT): $(TLS_OBJ)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(TLS_OBJ) $(LIBS)
@@ -101,7 +113,8 @@ proto:
cd $(srcdir) && $(MAKE) -f prepare-source.mak proto.h
clean: cleantests
rm -f *~ $(OBJS) $(TLS_OBJ) $(CHECK_PROGS) $(CHECK_OBJS)
rm -f *~ $(OBJS) $(TLS_OBJ) $(CHECK_PROGS) $(CHECK_OBJS) $(CHECK_SYMLINKS) \
mkrounding mkrounding.h rounding.h
cleantests:
rm -rf ./testtmp*
@@ -131,7 +144,6 @@ finddead:
test: check
# There seems to be no standard way to specify some variables as
# exported from a Makefile apart from listing them like this.
@@ -142,18 +154,27 @@ test: check
# catch Bash-isms earlier even if we're running on GNU. Of course, we
# might lose in the future where POSIX diverges from old sh.
check: all $(CHECK_PROGS)
check: all $(CHECK_PROGS) $(CHECK_SYMLINKS)
rsync_bin=`pwd`/rsync$(EXEEXT) $(srcdir)/runtests.sh
check29: all $(CHECK_PROGS) $(CHECK_SYMLINKS)
rsync_bin=`pwd`/rsync$(EXEEXT) $(srcdir)/runtests.sh --protocol=29
wildtest.o: wildtest.c lib/wildmatch.c rsync.h
wildtest$(EXEEXT): wildtest.o lib/compat.o
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ wildtest.o lib/compat.o @BUILD_POPT@ $(LIBS)
wildtest$(EXEEXT): wildtest.o lib/compat.o lib/snprintf.o @BUILD_POPT@
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ wildtest.o lib/compat.o lib/snprintf.o @BUILD_POPT@ $(LIBS)
testsuite/chown-fake.test:
ln -s chown.test $(srcdir)/testsuite/chown-fake.test
testsuite/devices-fake.test:
ln -s devices.test $(srcdir)/testsuite/devices-fake.test
# This does *not* depend on building or installing: you can use it to
# check a version installed from a binary or some other source tree,
# if you want.
installcheck: $(CHECK_PROGS)
installcheck: $(CHECK_PROGS) $(CHECK_SYMLINKS)
POSIXLY_CORRECT=1 TOOLDIR=`pwd` rsync_bin="$(bindir)/rsync$(EXEEXT)" srcdir="$(srcdir)" $(srcdir)/runtests.sh
# TODO: Add 'dist' target; need to know which files will be included

316
NEWS
View File

@@ -1,158 +1,232 @@
NEWS for rsync 2.6.9 (6 Nov 2006)
Protocol: 29 (unchanged)
Changes since 2.6.8:
NEWS for rsync 3.0.0 (UNRELEASED)
Protocol: 30 (changed)
Changes since 2.6.9:
NOTABLE CHANGES IN BEHAVIOR:
- The handling of implied directories when using --relative has changed to
send them as directories (e.g. no implied dir is ever sent as a symlink).
This avoids unexpected behavior and should not adversely affect most
people. If you're one of those rare people who relied upon having an
implied dir be duplicated as a symlink, you should specify the transfer
of the symlink and the transfer of the referent directory as separate
args. (See also --keep-dirlinks and --no-implied-dirs.)
- Requesting a remote file list without specifying -r (--recursive) now
sends the -d (--dirs) option to the remote rsync rather than sending -r
along with an extra exclude of /*/*. If the remote rsync does not
understand the -d option (i.e. it is 2.6.3 or older), you will need to
either turn off -d (--no-d), or specify -r --exclude='/*/*' manually.
BUG FIXES:
- If rsync is interrupted via a handled signal (such as SIGINT), it will
once again clean-up its temp file from the destination dir.
- Fixed the output of -ii when combined with one of the --*-dest options:
it now itemizes all the items, not just the changed ones.
- Fixed an overzealous sanitizing bug in the handling of the --link-dest,
--copy-dest, and --compare-dest options to a daemon without chroot: if
the copy's destination dir is deeper than the top of the module's path,
these options now accept a safe number of parent-dir (../) references
(since these options are relative to the destination dir). The old code
incorrectly chopped off all "../" prefixes for these options, no matter
how deep the destination directory was in the module's hierarchy.
- Made the output of all file types consistent when using a --*-dest
option. Prior versions used to output too many creation events for
matching items.
- Fixed a bug where a deferred info/error/log message could get sent
directly to the sender instead of being handled by rwrite() in the
generator. This fixes an "unexpected tag 3" fatal error, and should
also fix a potential problem where a deferred info/error message from
the receiver might bypass the log file and get sent only to the client
process. (These problems could only affect an rsync daemon that was
receiving files.)
- The code that waits for a child pid now handles being interrupted by a
signal. This fixes a problem with the pre-xfer exec function not being
able to get the exit status from the script.
- Fixed a bug when --inplace was combined with a --*-dest option and we
update a file's data using an alternate basis file. The code now
notices that it needs to copy the matching data from the basis file
instead of (wrongly) assuming that it was already present in the file.
- A negated filter rule (with a '!' modifier) no longer loses the negation
when sending the filter rules to the remote rsync.
- Fixed a bug where using --dry-run with a --*-dest option with a path
relative to a directory that does not yet exist: the affected option
gets its proper path value so that the output of the dry-run is right.
- Fixed a problem with the --out-format (aka --log-format) option %f: it
would output superfluous directory information for a non-daemon rsync.
- Fixed a bug in the %f logfile escape when receiving files: the
destination path is now included in the output (e.g. you can now tell
when a user specifies a subdir inside a module).
- Fixed a problem with -vv (double --verbose) and --stats when "pushing"
files (which includes local copies). Version 2.6.9 would complete the
copy, but exit with an error when the receiver output its memory stats.
- If the receiving side fails to create a directory, it will now skip
trying to update everything that is inside that directory.
- If --password-file is used on a non-daemon transfer, rsync now complains
and exits. This should help users figure out that they can't use this
option to control a remote shell's password prompt.
- If --link-dest is specified with --checksum but without --times, rsync
will now allow a hard-link to be created to a matching link-dest file
even when the file's modify-time doesn't match the server's file.
- Make sure that directory permissions of a newly-created destination
directory are handled right when --perms is left off.
- The daemon now calls more timezone-using functions prior to doing a
chroot. This should help some C libraries to generate proper timestamps
from inside a chrooted daemon (and to not try to access /etc/timezone
over and over again).
- The itemized output of a newly-created destination directory is now
output as a creation event, not a change event.
- Fixed a bug in the handling of an absolute --partial-dir=ABS_PATH option:
it now deletes an alternate basis file from the partial-dir that was used
to successfully update a destination file.
- Improved --hard-link so that more corner cases are handled correctly
when combined with options such as --link-dest and/or --ignore-existing.
- Fixed a bug in the handling of --delete-excluded when using a per-dir
merge file: the merge file is now honored on the receiving side, and
only its unqualified include/exclude commands are ignored (just as is
done for global include/excludes).
- The --append option no longer updates a file that has the same size.
- Fixed a recent bug where --delete was not working when transferring from
the root (/) of the filesystem with --relative enabled.
- Fixed a bug when combining --backup and --backup-dir with --inplace:
any missing backup directories are now created.
- Fixed a recent bug where an --exclude='*' could affect the root (/) of
the filesystem with --relative enabled.
- Fixed a bug when using --backup and --inplace with --whole-file or
--read-batch: backup files are actually created now.
- When --inplace creates a file, it is now created with owner read/write
permissions (0600) instead of no permissions at all. This avoids a
problem continuing a transfer that was interrupted (since --inplace
will not update a file that has no write permissions).
- Starting up an extra copy of an rsync daemon does not delete the pidfile
for the running daemon -- if the pidfile exists, the extra program will
exit with an error.
- If either --remove-source-files or --remove-sent-files is enabled and we
are unable to remove the source file, rsync now outputs an error.
- The daemon pidfile is checked and created sooner in the startup sequence.
- Fixed a bug in the daemon's "incoming chmod" rule: newly-created
directories no longer get the 'F' (file) rules applied to them.
- Fixed an infinite loop bug when a filter rule was rejected due to being
overly long.
- When the server receives a --partial-dir option from the client, it no
longer runs the client-side code that adds an assumed filter rule (since
the client will be sending us the rules in the usual manner, and they
may have chosen to override the auto-added rule).
- If a daemon module's "path" value is not an absolute pathname, the code
now makes it absolute internally (making it work properly).
ENHANCEMENTS:
- Added the --log-file=FILE and --log-file-format=FORMAT options. These
can be used to tell any rsync to output what it is doing to a log file.
They work with a client rsync, a non-daemon server rsync (see the man
page for instructions), and also allows the overriding of rsyncd.conf
settings when starting a daemon.
- A new incremental-recursion algorithm is now used when rsync is talking
to another 3.x version. This starts the transfer going more quickly
(before all the files have been found), and requires much less memory.
See the --recursive option in the manpage for some restrictions.
- The --log-format option was renamed to be --out-format to avoid confusing
it with affecting the log-file output. (The old option remains as an
alias for the new to preserve backward compatibility.)
- Lowered memory use in the non-incremental-recursion algorithm for typical
option values (usually saving from 21-29 bytes per file).
- Made "log file" and "syslog facility" settable on a per-module basis in
the daemon's config file.
- The default --delete algorithm is now --delete-during when talking to a
3.x rsync. This is a faster scan than using --delete-before (which is
the default when talking to older rsync versions), and is compatible with
the new incremental recursion mode.
- Added the --remove-source-files option as a replacement for the (now
deprecated) --remove-sent-files option. This new option removes all
non-dirs from the source directories, even if the file was already
up-to-date. This fixes a problem where interrupting an rsync that
was using --remove-sent-files and restarting it could leave behind
a file that the earlier rsync synchronized, but didn't get to remove.
(The deprecated --remove-sent-files is still understood for now, and
still behaves in the same way as before.)
- Rsync now allows multiple remote-source args to be specified rather than
having to rely on a special space-splitting side-effect of the remote-
shell. Additional remote args must specify the same host or have an
empty hostname, as seen here: :file1 ::module/file2. This means that
local use of brace expansion now works: rsync -av host:path/{f1,f2} .
- Added the option --no-motd to suppress the message-of-the-day output
from a daemon when doing a copy. (See the manpage for a caveat.)
- Added the --protect-args (-s) option, that tells rsync to send most of
the command-line args at the start of the transfer rather than as args
to the remote-shell command. This protects them from space-splitting,
and only interprets basic wildcard special shell characters (*?[).
- Added a new environment variable to the pre-/post-xfer exec commands (in
the daemon's config file): RSYNC_PID. This value will be the same in
both the pre- and post-xfer commands, so it can be used if the pre-xfer
command wants to cache some arg/request info for the post-xfer command.
- Added the --delete-delay option, which is a more efficient way to delete
files at the end of the transfer without needing a separate delete pass.
- Added the --acls (-A) option to preserve Access Control Lists. This is
an improved version of the prior patch that was available, and it even
supports OS X ACLs. (If you need to have backward compatibility with
old, patched versions of rsync, apply the acls.diff file from the patches
dir.)
- Added the --xattrs (-X) option to preserver extended attributes. This is
an improved version of the prior patch that was available. (If you need
to have backward compatibility with old, patched versions of rsync, apply
the xattrs.diff file from the patches dir.)
- Added the --fake-super option that allows a non-super user to preserve
all attributes of a file by using a special extended-attribute idiom.
There is also an analogous "fake super" option for an rsync daemon.
- Added the --iconv option, which allows rsync to convert filenames from
one character-set to another during the transfer. The default is to make
this feature available as long as your system has iconv_open(). If
compilation fails, specify --disable-iconv to configure, and then
rebuild. If you want rsync to perform character-set conversions by
default, you can specify --enable-iconv=CONVERT_STRING with the default
value for the --iconv option that you wish to use. For example,
"--enable-iconv=." is a good choice. See the rsync manpage for an
explanation of the --iconv option's settings.
- Added the --skip-compress=LIST option to override the default list of
file suffixes that will not be compressed when using --compress.
- The daemon's default for "dont compress" was extended to include:
*.7z *.mp[34] *.mov *.avi *.ogg *.jpg *.jpeg
The matching routine was also optimized to run more quickly.
- The --max-delete option now outputs a warning if it skipped any file
deletions, including a count of how many deletions were skipped. (Older
versions just silently stopped deleting things.)
- You may specify --max-delete=0 to a 3.0.0 client to request that it warn
about extraneous files without deleting anything. If you're not sure
what version the client is, you can use the less-obvious --max-delete=-1,
as both old and new versions will treat that as the same request (though
older versions don't warn).
- The --hard-link option now uses less memory on both the sending and
receiving side for all protocol versions. For protocol 30, the use of a
hashtable on the sending side allows us to more efficiently convey to the
receiver what files are linked together. This reduces the amount of data
sent over the socket by a considerable margin (rather than adding more
data), and limits the in-memory storage of the device+inode information
to just the sending side for the new protocol 30, or to the receiving
side when speaking an older protocol (note that older rsync versions kept
the device+inode information on both sides).
- The filter rules now support a perishable ("p") modifier that marks rules
that should not have an effect in a directory that is being deleted. e.g.
-f '-p .svn/' would only affect "live" .svn directories.
- If we get an error setting the time on a symlink, we don't complain about
it anymore (since some operating systems don't support that, and it's not
that important).
- Protocol 30 now uses MD5 checksums instead of MD4.
- Changed the --append option to not checksum the existing data in the
destination file, which speeds up file appending.
- Added the --append-verify option, which works like the older --append
option (verifying the existing data in the destination file). For
compatibility with older rsync versions, any use of --append that is
talking protocol 29 or older will revert to the --append-verify method.
- Documented and extended the support for the RSYNC_CONNECT_PROG variable
that can be used to enhance the client side of a daemon connection.
- Improved the dashes and double-quotes in the nroff manpage output.
- We now support a lot more --no-OPTION override options.
INTERNAL:
- Did a code audit using IBM's code-checker program and made several
changes, including: replacing most of the strcpy() and sprintf()
calls with strlcpy(), snprintf(), and memcpy(), adding a 0-value to
an enum that had been intermingling a literal 0 with the defined enum
values, silencing some uninitialized memory checks, marking some
functions with a "noreturn" attribute, and changing an "if" that
could never succeed on some platforms into a pre-processor directive
that conditionally compiles the code.
- The file-list sorting algorithm now uses a sort that keeps any same-
named items in the same order as they were specified. This allows
rsync to always ensure that the first of the duplicates is the one
that will be included in the copy. The new sort was also faster
than the glibc version of qsort() and mergesort() in my testing.
- Fixed a potential bug in f_name_cmp() when both the args are a
top-level "." dir (which doesn't happen in normal operations).
- Rsync now supports the transfer of 64-bit timestamps (time_t values).
- Changed exit_cleanup() so that it can never return instead of exit.
The old code might return if it found the exit_cleanup() function
was being called recursively. The new code is segmented so that
any recursive calls move on to the next step of the exit-processing.
- Fixed a build problem with older (2.x) versions of gcc.
- The macro WIFEXITED(stat) will now be defined if the OS didn't already
define it.
- Added some isType() functions that make dealing with signed characters
easier without forcing variables via casts.
- Changed strcat/strcpy/sprintf function calls to use safer versions.
- Upgraded the included popt version to 1.10.2 and improved its use of
string-handling functions.
- Added missing prototypes for compatibility functions from the lib dir.
- Configure determines if iconv() has a const arg, allowing us to avoid a
compiler warning.
- Made the sending of some numbers more efficient for protocol 30.
- Make sure that a daemon process doesn't mind if the client was weird and
omitted the --server option.
- Improved the use of "const" on pointers.
- Improved J.W.'s pool_alloc routines to add a way of freeing older
sections of a pool's memory.
DEVELOPER RELATED:
- The acls.diff and xattrs.diff patches have received a bunch of work to
make them much closer to being acceptable in the main distribution.
The xattrs patch also has some preliminary Mac OS X compatibility code
that allows Macs and non-macs to exchange extended attributes.
- Rsync is now licensed under the GPLv3 or later.
- A new diff in the patches dir, fake-root.diff, allows rsync to
maintain a backup hierarchy with full owner, group, and device info
without actually running as root. It does this using a special
extended attribute, so it depends on xattrs.diff (which depends on
acls.diff).
- When running the tests, we now put our per-test temp dirs into a sub-
directory named testtmp (which is created, if missing). This allows
someone to symlink the testtmp directory to another filesystem (which is
useful if the build dir's filesystem does not support ACLs and xattrs,
and another file system does).
- The rsync.yo and rsyncd.conf.yo files have been updated to work
better with the latest yodl 2.x releases.
- Updated config.guess and config.sub to their 2006-02-23 version.
- Updated various files to include the latest FSF address and to have
consistent opening comments.
- Rsync now has a way of handling protocol-version changes during the
development of a new protocol version. This causes any out-of-sync
versions to speak an older protocol rather than fail in a cryptic manner.
This addition makes it safe to deploy a pre-release version that may
interact with the public. This new exchange of sub-version info does not
interfere with the {MIN,MAX}_PROTOCOL_VERSION checking algorithm (which
does not have enough range to allow the main protocol number to be
incremented for every minor tweak in that happens during development).

167
OLDNEWS
View File

@@ -1,3 +1,165 @@
NEWS for rsync 2.6.9 (6 Nov 2006)
Protocol: 29 (unchanged)
Changes since 2.6.8:
BUG FIXES:
- If rsync is interrupted via a handled signal (such as SIGINT), it will
once again clean-up its temp file from the destination dir.
- Fixed an overzealous sanitizing bug in the handling of the --link-dest,
--copy-dest, and --compare-dest options to a daemon without chroot: if
the copy's destination dir is deeper than the top of the module's path,
these options now accept a safe number of parent-dir (../) references
(since these options are relative to the destination dir). The old code
incorrectly chopped off all "../" prefixes for these options, no matter
how deep the destination directory was in the module's hierarchy.
- Fixed a bug where a deferred info/error/log message could get sent
directly to the sender instead of being handled by rwrite() in the
generator. This fixes an "unexpected tag 3" fatal error, and should
also fix a potential problem where a deferred info/error message from
the receiver might bypass the log file and get sent only to the client
process. (These problems could only affect an rsync daemon that was
receiving files.)
- Fixed a bug when --inplace was combined with a --*-dest option and we
update a file's data using an alternate basis file. The code now
notices that it needs to copy the matching data from the basis file
instead of (wrongly) assuming that it was already present in the file.
- Fixed a bug where using --dry-run with a --*-dest option with a path
relative to a directory that does not yet exist: the affected option
gets its proper path value so that the output of the dry-run is right.
- Fixed a bug in the %f logfile escape when receiving files: the
destination path is now included in the output (e.g. you can now tell
when a user specifies a subdir inside a module).
- If the receiving side fails to create a directory, it will now skip
trying to update everything that is inside that directory.
- If --link-dest is specified with --checksum but without --times, rsync
will now allow a hard-link to be created to a matching link-dest file
even when the file's modify-time doesn't match the server's file.
- The daemon now calls more timezone-using functions prior to doing a
chroot. This should help some C libraries to generate proper timestamps
from inside a chrooted daemon (and to not try to access /etc/timezone
over and over again).
- Fixed a bug in the handling of an absolute --partial-dir=ABS_PATH option:
it now deletes an alternate basis file from the partial-dir that was used
to successfully update a destination file.
- Fixed a bug in the handling of --delete-excluded when using a per-dir
merge file: the merge file is now honored on the receiving side, and
only its unqualified include/exclude commands are ignored (just as is
done for global include/excludes).
- Fixed a recent bug where --delete was not working when transferring from
the root (/) of the filesystem with --relative enabled.
- Fixed a recent bug where an --exclude='*' could affect the root (/) of
the filesystem with --relative enabled.
- When --inplace creates a file, it is now created with owner read/write
permissions (0600) instead of no permissions at all. This avoids a
problem continuing a transfer that was interrupted (since --inplace
will not update a file that has no write permissions).
- If either --remove-source-files or --remove-sent-files is enabled and we
are unable to remove the source file, rsync now outputs an error.
- Fixed a bug in the daemon's "incoming chmod" rule: newly-created
directories no longer get the 'F' (file) rules applied to them.
- Fixed an infinite loop bug when a filter rule was rejected due to being
overly long.
- When the server receives a --partial-dir option from the client, it no
longer runs the client-side code that adds an assumed filter rule (since
the client will be sending us the rules in the usual manner, and they
may have chosen to override the auto-added rule).
ENHANCEMENTS:
- Added the --log-file=FILE and --log-file-format=FORMAT options. These
can be used to tell any rsync to output what it is doing to a log file.
They work with a client rsync, a non-daemon server rsync (see the man
page for instructions), and also allows the overriding of rsyncd.conf
settings when starting a daemon.
- The --log-format option was renamed to be --out-format to avoid confusing
it with affecting the log-file output. (The old option remains as an
alias for the new to preserve backward compatibility.)
- Made "log file" and "syslog facility" settable on a per-module basis in
the daemon's config file.
- Added the --remove-source-files option as a replacement for the (now
deprecated) --remove-sent-files option. This new option removes all
non-dirs from the source directories, even if the file was already
up-to-date. This fixes a problem where interrupting an rsync that
was using --remove-sent-files and restarting it could leave behind
a file that the earlier rsync synchronized, but didn't get to remove.
(The deprecated --remove-sent-files is still understood for now, and
still behaves in the same way as before.)
- Added the option --no-motd to suppress the message-of-the-day output
from a daemon when doing a copy. (See the manpage for a caveat.)
- Added a new environment variable to the pre-/post-xfer exec commands (in
the daemon's config file): RSYNC_PID. This value will be the same in
both the pre- and post-xfer commands, so it can be used as a unique ID
if the pre-xfer command wants to cache some arg/request info for the
post-xfer command.
INTERNAL:
- Did a code audit using IBM's code-checker program and made several
changes, including: replacing most of the strcpy() and sprintf()
calls with strlcpy(), snprintf(), and memcpy(), adding a 0-value to
an enum that had been intermingling a literal 0 with the defined enum
values, silencing some uninitialized memory checks, marking some
functions with a "noreturn" attribute, and changing an "if" that
could never succeed on some platforms into a pre-processor directive
that conditionally compiles the code.
- Fixed a potential bug in f_name_cmp() when both the args are a
top-level "." dir (which doesn't happen in normal operations).
- Changed exit_cleanup() so that it can never return instead of exit.
The old code might return if it found the exit_cleanup() function
was being called recursively. The new code is segmented so that
any recursive calls move on to the next step of the exit-processing.
- The macro WIFEXITED(stat) will now be defined if the OS didn't already
define it.
DEVELOPER RELATED:
- The acls.diff and xattrs.diff patches have received a bunch of work to
make them much closer to being acceptable in the main distribution.
The xattrs patch also has some preliminary Mac OS X and FreeBSD
compatibility code that various system types to exchange extended
file-attributes.
- A new diff in the patches dir, fake-root.diff, allows rsync to
maintain a backup hierarchy with full owner, group, and device info
without actually running as root. It does this using a special
extended attribute, so it depends on xattrs.diff (which depends on
acls.diff).
- The rsync.yo and rsyncd.conf.yo files have been updated to work
better with the latest yodl 2.x releases.
- Updated config.guess and config.sub to their 2006-07-02 versions.
- Updated various files to include the latest FSF address and to have
consistent opening comments.
NEWS for rsync 2.6.8 (22 Apr 2006)
Protocol: 29 (unchanged)
Changes since 2.6.7:
@@ -144,8 +306,8 @@ Changes since 2.6.6:
- Fixed the matching of the dont-compress items (e.g. *.gz) against files
that have a path component containing a slash.
- If code reading a filter/exclude file an EINTR error, rsync now clears
the error flag on the file handle so it can keep on reading.
- If the code reading a filter/exclude file gets an EINTR error, rsync now
clears the error flag on the file handle so it can keep on reading.
- If --relative is active, the sending side cleans up trailing "/" or "/."
suffixes to avoid triggering a bug in older rsync versions. Also, we now
@@ -2082,6 +2244,7 @@ Changes since 2.4.6:
Partial Protocol History
RELEASE DATE VER. DATE OF COMMIT* PROTOCOL
?? ??? 2007 3.0.0 11 Nov 2006 30
06 Nov 2006 2.6.9 29
22 Apr 2006 2.6.8 29
11 Mar 2006 2.6.7 29

10
README
View File

@@ -51,13 +51,13 @@ case.
Once built put a copy of rsync in your search path on the local and
remote systems (or use "make install"). That's it!
RSYNC SERVERS
RSYNC DAEMONS
-------------
rsync can also talk to "rsync servers" which can provide anonymous or
rsync can also talk to "rsync daemons" which can provide anonymous or
authenticated rsync. See the rsyncd.conf(5) man page for details on how
to setup a rsync server. See the rsync(1) man page for info on how to
connect to a rsync server.
to setup an rsync daemon. See the rsync(1) man page for info on how to
connect to an rsync daemon.
MAILING LIST
@@ -69,7 +69,7 @@ versions on this list.
To join the mailing list see the web page at http://lists.samba.org/
To send mail to everyone on the list send it to rsync@samba.org
To send mail to everyone on the list send it to rsync@lists.samba.org
BUG REPORTS

26
TODO
View File

@@ -365,21 +365,6 @@ Use generic zlib 2002/02/25
-- --
TDB 2002/03/12
Rather than storing the file list in memory, store it in a TDB.
This *might* make memory usage lower while building the file list.
Hashtable lookup will mean files are not transmitted in order,
though... hm.
This would neatly eliminate one of the major post-fork shared data
structures.
-- --
Splint 2002/03/12
Build rsync with SPLINT to try to find security holes. Add
@@ -392,17 +377,6 @@ Splint 2002/03/12
PERFORMANCE ----------------------------------------------------------
Traverse just one directory at a time
Traverse just one directory at a time. Tridge says it's possible.
At the moment rsync reads the whole file list into memory at the
start, which makes us use a lot of memory and also not pipeline
network access as much as we could.
-- --
Allow skipping MD4 file_sum 2002/04/08
If we're doing a local transfer, or using -W, then perhaps don't

View File

@@ -2,11 +2,11 @@
* Routines to authenticate access to a daemon (hosts allow/deny).
*
* Copyright (C) 1998 Andrew Tridgell
* Copyright (C) 2004, 2005 Wayne Davison
* Copyright (C) 2004-2007 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
@@ -15,8 +15,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
* with this program; if not, visit the http://fsf.org website.
*/
#include "rsync.h"

1079
acls.c Normal file
View File

File diff suppressed because it is too large Load Diff

View File

@@ -2,11 +2,11 @@
* Support rsync daemon authentication.
*
* Copyright (C) 1998-2000 Andrew Tridgell
* Copyright (C) 2002, 2004, 2005, 2006 Wayne Davison
* Copyright (C) 2002-2007 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
@@ -15,8 +15,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
* with this program; if not, visit the http://fsf.org website.
*/
#include "rsync.h"
@@ -27,11 +26,11 @@ extern char *password_file;
encode a buffer using base64 - simple and slow algorithm. null terminates
the result.
***************************************************************************/
void base64_encode(char *buf, int len, char *out, int pad)
void base64_encode(const char *buf, int len, char *out, int pad)
{
char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
int bit_offset, byte_offset, idx, i;
unsigned char *d = (unsigned char *)buf;
const uchar *d = (const uchar *)buf;
int bytes = (len*8 + 5)/6;
for (i = 0; i < bytes; i++) {
@@ -55,15 +54,16 @@ void base64_encode(char *buf, int len, char *out, int pad)
}
/* Generate a challenge buffer and return it base64-encoded. */
static void gen_challenge(char *addr, char *challenge)
static void gen_challenge(const char *addr, char *challenge)
{
char input[32];
char md4_out[MD4_SUM_LENGTH];
char digest[MAX_DIGEST_LEN];
struct timeval tv;
int len;
memset(input, 0, sizeof input);
strlcpy((char *)input, addr, 17);
strlcpy(input, addr, 17);
sys_gettimeofday(&tv);
SIVAL(input, 16, tv.tv_sec);
SIVAL(input, 20, tv.tv_usec);
@@ -71,20 +71,21 @@ static void gen_challenge(char *addr, char *challenge)
sum_init(0);
sum_update(input, sizeof input);
sum_end(md4_out);
len = sum_end(digest);
base64_encode(md4_out, MD4_SUM_LENGTH, challenge, 0);
base64_encode(digest, len, challenge, 0);
}
/* Return the secret for a user from the secret file, null terminated.
* Maximum length is len (not counting the null). */
static int get_secret(int module, char *user, char *secret, int len)
static int get_secret(int module, const char *user, char *secret, int len)
{
char *fname = lp_secrets_file(module);
const char *fname = lp_secrets_file(module);
STRUCT_STAT st;
int fd, ok = 1;
char ch, *p;
const char *p;
char ch, *s;
if (!fname || !*fname)
return 0;
@@ -136,27 +137,27 @@ static int get_secret(int module, char *user, char *secret, int len)
}
/* Slurp the secret into the "secret" buffer. */
p = secret;
s = secret;
while (len > 0) {
if (read(fd, p, 1) != 1 || *p == '\n')
if (read(fd, s, 1) != 1 || *s == '\n')
break;
if (*p == '\r')
if (*s == '\r')
continue;
p++;
s++;
len--;
}
*p = '\0';
*s = '\0';
close(fd);
return 1;
}
static char *getpassf(char *filename)
static const char *getpassf(const char *filename)
{
STRUCT_STAT st;
char buffer[512], *p;
int fd, n, ok = 1;
char *envpw = getenv("RSYNC_PASSWORD");
const char *envpw = getenv("RSYNC_PASSWORD");
if (!filename)
return NULL;
@@ -203,16 +204,17 @@ static char *getpassf(char *filename)
/* Generate an MD4 hash created from the combination of the password
* and the challenge string and return it base64-encoded. */
static void generate_hash(char *in, char *challenge, char *out)
static void generate_hash(const char *in, const char *challenge, char *out)
{
char buf[MD4_SUM_LENGTH];
char buf[MAX_DIGEST_LEN];
int len;
sum_init(0);
sum_update(in, strlen(in));
sum_update(challenge, strlen(challenge));
sum_end(buf);
len = sum_end(buf);
base64_encode(buf, MD4_SUM_LENGTH, out, 0);
base64_encode(buf, len, out, 0);
}
/* Possibly negotiate authentication with the client. Use "leader" to
@@ -221,14 +223,14 @@ static void generate_hash(char *in, char *challenge, char *out)
* Return NULL if authentication failed. Return "" if anonymous access.
* Otherwise return username.
*/
char *auth_server(int f_in, int f_out, int module, char *host, char *addr,
char *leader)
char *auth_server(int f_in, int f_out, int module, const char *host,
const char *addr, const char *leader)
{
char *users = lp_auth_users(module);
char challenge[MD4_SUM_LENGTH*2];
char challenge[MAX_DIGEST_LEN*2];
char line[BIGPATHBUFLEN];
char secret[512];
char pass2[MD4_SUM_LENGTH*2];
char pass2[MAX_DIGEST_LEN*2];
char *tok, *pass;
/* if no auth list then allow anyone in! */
@@ -239,7 +241,7 @@ char *auth_server(int f_in, int f_out, int module, char *host, char *addr,
io_printf(f_out, "%s%s\n", leader, challenge);
if (!read_line(f_in, line, sizeof line - 1)
if (!read_line_old(f_in, line, sizeof line)
|| (pass = strchr(line, ' ')) == NULL) {
rprintf(FLOG, "auth failed on module %s from %s (%s): "
"invalid challenge response\n",
@@ -286,11 +288,10 @@ char *auth_server(int f_in, int f_out, int module, char *host, char *addr,
return strdup(line);
}
void auth_client(int fd, char *user, char *challenge)
void auth_client(int fd, const char *user, const char *challenge)
{
char *pass;
char pass2[MD4_SUM_LENGTH*2];
const char *pass;
char pass2[MAX_DIGEST_LEN*2];
if (!user || !*user)
user = "nobody";

160
backup.c
View File

@@ -2,11 +2,11 @@
* Backup handling code.
*
* Copyright (C) 1999 Andrew Tridgell
* Copyright (C) 2003, 2004, 2005, 2006 Wayne Davison
* Copyright (C) 2003-2007 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
@@ -15,27 +15,27 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
* with this program; if not, visit the http://fsf.org website.
*/
#include "rsync.h"
extern int verbose;
extern int am_root;
extern int preserve_acls;
extern int preserve_xattrs;
extern int preserve_devices;
extern int preserve_specials;
extern int preserve_links;
extern int safe_symlinks;
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;
extern int am_root;
extern int preserve_devices;
extern int preserve_specials;
extern int preserve_links;
extern int safe_symlinks;
/* make a complete pathname for backup file */
char *get_backup_name(char *fname)
char *get_backup_name(const char *fname)
{
if (backup_dir) {
if (stringjoin(backup_dir_buf + backup_dir_len, backup_dir_remainder,
@@ -52,10 +52,10 @@ char *get_backup_name(char *fname)
}
/* simple backup creates a backup with a suffix in the same directory */
static int make_simple_backup(char *fname)
static int make_simple_backup(const char *fname)
{
int rename_errno;
char *fnamebak = get_backup_name(fname);
const char *fnamebak = get_backup_name(fname);
if (!fnamebak)
return 0;
@@ -92,31 +92,37 @@ static int make_simple_backup(char *fname)
Create a directory given an absolute path, perms based upon another directory
path
****************************************************************************/
static int make_bak_dir(char *fullpath)
int make_bak_dir(const char *fullpath)
{
STRUCT_STAT st;
char *rel = fullpath + backup_dir_len;
char *end = rel + strlen(rel);
char *p = end;
char fbuf[MAXPATHLEN], *rel, *end, *p;
struct file_struct *file;
int len = backup_dir_len;
stat_x sx;
while (strncmp(fullpath, "./", 2) == 0)
while (*fullpath == '.' && fullpath[1] == '/') {
fullpath += 2;
len -= 2;
}
if (strlcpy(fbuf, fullpath, sizeof fbuf) >= sizeof fbuf)
return -1;
rel = fbuf + len;
end = p = rel + strlen(rel);
/* Try to find an existing dir, starting from the deepest dir. */
while (1) {
if (--p == fullpath) {
p += strlen(p);
goto failure;
}
if (--p == fbuf)
return -1;
if (*p == '/') {
*p = '\0';
if (mkdir_defmode(fullpath) == 0)
if (mkdir_defmode(fbuf) == 0)
break;
if (errno != ENOENT) {
rsyserr(FERROR, errno,
"make_bak_dir mkdir %s failed",
full_fname(fullpath));
goto failure;
full_fname(fbuf));
return -1;
}
}
}
@@ -126,37 +132,53 @@ static int make_bak_dir(char *fullpath)
if (p >= rel) {
/* Try to transfer the directory settings of the
* actual dir that the files are coming from. */
if (do_stat(rel, &st) < 0) {
if (x_stat(rel, &sx.st, NULL) < 0) {
rsyserr(FERROR, errno,
"make_bak_dir stat %s failed",
full_fname(rel));
} else {
do_lchown(fullpath, st.st_uid, st.st_gid);
do_chmod(fullpath, st.st_mode);
#ifdef SUPPORT_ACLS
sx.acc_acl = sx.def_acl = NULL;
#endif
#ifdef SUPPORT_XATTRS
sx.xattr = NULL;
#endif
if (!(file = make_file(rel, NULL, NULL, 0, NO_FILTERS)))
continue;
#ifdef SUPPORT_ACLS
if (preserve_acls && !S_ISLNK(file->mode)) {
get_acl(rel, &sx);
cache_acl(file, &sx);
free_acl(&sx);
}
#endif
#ifdef SUPPORT_XATTRS
if (preserve_xattrs) {
get_xattr(rel, &sx);
cache_xattr(file, &sx);
free_xattr(&sx);
}
#endif
set_file_attrs(fbuf, file, NULL, NULL, 0);
unmake_file(file);
}
}
*p = '/';
p += strlen(p);
if (p == end)
break;
if (mkdir_defmode(fullpath) < 0) {
if (mkdir_defmode(fbuf) < 0) {
rsyserr(FERROR, errno, "make_bak_dir mkdir %s failed",
full_fname(fullpath));
goto failure;
full_fname(fbuf));
return -1;
}
}
return 0;
failure:
while (p != end) {
*p = '/';
p += strlen(p);
}
return -1;
return 0;
}
/* robustly move a file, creating new directory structures if necessary */
static int robust_move(char *src, char *dst)
static int robust_move(const char *src, char *dst)
{
if (robust_rename(src, dst, NULL, 0755) < 0
&& (errno != ENOENT || make_bak_dir(dst) < 0
@@ -168,31 +190,56 @@ static int robust_move(char *src, char *dst)
/* 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 keep_backup(const char *fname)
{
STRUCT_STAT st;
stat_x sx;
struct file_struct *file;
char *buf;
int kept = 0;
int ret_code;
/* return if no file to keep */
if (do_lstat(fname, &st) < 0)
if (x_lstat(fname, &sx.st, NULL) < 0)
return 1;
#ifdef SUPPORT_ACLS
sx.acc_acl = sx.def_acl = NULL;
#endif
#ifdef SUPPORT_XATTRS
sx.xattr = NULL;
#endif
if (!(file = make_file(fname, NULL, NULL, 0, NO_FILTERS)))
return 1; /* the file could have disappeared */
if (!(buf = get_backup_name(fname)))
if (!(buf = get_backup_name(fname))) {
unmake_file(file);
return 0;
}
#ifdef SUPPORT_ACLS
if (preserve_acls && !S_ISLNK(file->mode)) {
get_acl(fname, &sx);
cache_acl(file, &sx);
free_acl(&sx);
}
#endif
#ifdef SUPPORT_XATTRS
if (preserve_xattrs) {
get_xattr(fname, &sx);
cache_xattr(file, &sx);
free_xattr(&sx);
}
#endif
/* Check to see if this is a device file, or link */
if ((am_root && preserve_devices && IS_DEVICE(file->mode))
|| (preserve_specials && IS_SPECIAL(file->mode))) {
uint32 *devp = F_RDEV_P(file);
dev_t rdev = MAKEDEV(DEV_MAJOR(devp), DEV_MINOR(devp));
do_unlink(buf);
if (do_mknod(buf, file->mode, file->u.rdev) < 0
if (do_mknod(buf, file->mode, rdev) < 0
&& (errno != ENOENT || make_bak_dir(buf) < 0
|| do_mknod(buf, file->mode, file->u.rdev) < 0)) {
|| do_mknod(buf, file->mode, rdev) < 0)) {
rsyserr(FERROR, errno, "mknod %s failed",
full_fname(buf));
} else if (verbose > 2) {
@@ -222,20 +269,20 @@ static int keep_backup(char *fname)
#ifdef SUPPORT_LINKS
if (!kept && preserve_links && S_ISLNK(file->mode)) {
if (safe_symlinks && unsafe_symlink(file->u.link, buf)) {
const char *sl = F_SYMLINK(file);
if (safe_symlinks && unsafe_symlink(sl, buf)) {
if (verbose) {
rprintf(FINFO, "ignoring unsafe symlink %s -> %s\n",
full_fname(buf), file->u.link);
full_fname(buf), sl);
}
kept = 1;
} else {
do_unlink(buf);
if (do_symlink(file->u.link, buf) < 0
if (do_symlink(sl, buf) < 0
&& (errno != ENOENT || make_bak_dir(buf) < 0
|| do_symlink(file->u.link, buf) < 0)) {
|| do_symlink(sl, buf) < 0)) {
rsyserr(FERROR, errno, "link %s -> \"%s\"",
full_fname(buf),
file->u.link);
full_fname(buf), sl);
}
do_unlink(fname);
kept = 1;
@@ -246,6 +293,7 @@ static int keep_backup(char *fname)
if (!kept && !S_ISREG(file->mode)) {
rprintf(FINFO, "make_bak: skipping non-regular file %s\n",
fname);
unmake_file(file);
return 1;
}
@@ -254,14 +302,14 @@ static int keep_backup(char *fname)
if (robust_move(fname, buf) != 0) {
rsyserr(FERROR, errno, "keep_backup failed: %s -> \"%s\"",
full_fname(fname), buf);
} else if (st.st_nlink > 1) {
} else if (sx.st.st_nlink > 1) {
/* If someone has hard-linked the file into the backup
* dir, rename() might return success but do nothing! */
robust_unlink(fname); /* Just in case... */
}
}
set_file_attrs(buf, file, NULL, 0);
free(file);
set_file_attrs(buf, file, NULL, fname, 0);
unmake_file(file);
if (verbose > 1) {
rprintf(FINFO, "backed up %s to %s\n",
@@ -272,7 +320,7 @@ static int keep_backup(char *fname)
/* main backup switch routine */
int make_backup(char *fname)
int make_backup(const char *fname)
{
if (backup_dir)
return keep_backup(fname);

View File

@@ -3,11 +3,11 @@
*
* Copyright (C) 1999 Weiss
* Copyright (C) 2004 Chris Shoemaker
* Copyright (C) 2004, 2005, 2006 Wayne Davison
* Copyright (C) 2004-2007 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
@@ -16,8 +16,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
* with this program; if not, visit the http://fsf.org website.
*/
#include "rsync.h"

View File

@@ -2,10 +2,11 @@
* Simple byteorder handling.
*
* Copyright (C) 1992-1995 Andrew Tridgell
* Copyright (C) 2007 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
@@ -14,14 +15,13 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
* with this program; if not, visit the http://fsf.org website.
*/
#undef CAREFUL_ALIGNMENT
/* we know that the x86 can handle misalignment and has the "right"
byteorder */
/* We know that the x86 can handle misalignment and has the same
* byte order (LSB-first) as the 32-bit numbers we transmit. */
#ifdef __i386__
#define CAREFUL_ALIGNMENT 0
#endif
@@ -31,13 +31,12 @@
#endif
#define CVAL(buf,pos) (((unsigned char *)(buf))[pos])
#define PVAL(buf,pos) ((unsigned)CVAL(buf,pos))
#define UVAL(buf,pos) ((uint32)CVAL(buf,pos))
#define SCVAL(buf,pos,val) (CVAL(buf,pos) = (val))
#if CAREFUL_ALIGNMENT
#define SVAL(buf,pos) (PVAL(buf,pos)|PVAL(buf,(pos)+1)<<8)
#define IVAL(buf,pos) (SVAL(buf,pos)|SVAL(buf,(pos)+2)<<16)
#define PVAL(buf,pos) (UVAL(buf,pos)|UVAL(buf,(pos)+1)<<8)
#define IVAL(buf,pos) (PVAL(buf,pos)|PVAL(buf,(pos)+2)<<16)
#define SSVALX(buf,pos,val) (CVAL(buf,pos)=(val)&0xFF,CVAL(buf,pos+1)=(val)>>8)
#define SIVALX(buf,pos,val) (SSVALX(buf,pos,val&0xFFFF),SSVALX(buf,pos+2,val>>16))
#define SIVAL(buf,pos,val) SIVALX((buf),(pos),((uint32)(val)))
@@ -51,5 +50,3 @@
#define IVAL(buf,pos) (*(uint32 *)((char *)(buf) + (pos)))
#define SIVAL(buf,pos,val) IVAL(buf,pos)=((uint32)(val))
#endif

View File

@@ -1,11 +1,11 @@
/*
* End-of-run cleanup helper code used by cleanup.c.
*
* Copyright (C) 2006 Wayne Davison
* Copyright (C) 2006-2007 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
@@ -14,8 +14,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
* with this program; if not, visit the http://fsf.org website.
*/
/* This is included by cleanup.c multiple times, once for every segement in

View File

@@ -3,11 +3,11 @@
*
* Copyright (C) 1996 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2004, 2005 Wayne Davison
* Copyright (C) 2004-2007 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
@@ -16,19 +16,16 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
* with this program; if not, visit the http://fsf.org website.
*/
#include "rsync.h"
int csum_length=2; /* initial value */
#define CSUM_CHUNK 64
extern int checksum_seed;
extern int protocol_version;
int csum_length = SHORT_SUM_LENGTH; /* initial value */
/*
a simple 32 bit checksum that can be upadted from either end
(inspired by Mark Adler's Adler-32 checksum)
@@ -54,54 +51,64 @@ uint32 get_checksum1(char *buf1, int32 len)
void get_checksum2(char *buf, int32 len, char *sum)
{
int32 i;
static char *buf1;
static int32 len1;
struct mdfour m;
md_context m;
if (len > len1) {
if (buf1)
free(buf1);
buf1 = new_array(char, len+4);
len1 = len;
if (!buf1)
out_of_memory("get_checksum2");
if (protocol_version >= 30) {
uchar seedbuf[4];
md5_begin(&m);
md5_update(&m, (uchar *)buf, len);
if (checksum_seed) {
SIVAL(seedbuf, 0, checksum_seed);
md5_update(&m, seedbuf, 4);
}
md5_result(&m, (uchar *)sum);
} else {
int32 i;
static char *buf1;
static int32 len1;
mdfour_begin(&m);
if (len > len1) {
if (buf1)
free(buf1);
buf1 = new_array(char, len+4);
len1 = len;
if (!buf1)
out_of_memory("get_checksum2");
}
memcpy(buf1, buf, len);
if (checksum_seed) {
SIVAL(buf1,len,checksum_seed);
len += 4;
}
for (i = 0; i + CSUM_CHUNK <= len; i += CSUM_CHUNK)
mdfour_update(&m, (uchar *)(buf1+i), CSUM_CHUNK);
/*
* Prior to version 27 an incorrect MD4 checksum was computed
* by failing to call mdfour_tail() for block sizes that
* are multiples of 64. This is fixed by calling mdfour_update()
* even when there are no more bytes.
*/
if (len - i > 0 || protocol_version >= 27)
mdfour_update(&m, (uchar *)(buf1+i), len-i);
mdfour_result(&m, (uchar *)sum);
}
mdfour_begin(&m);
memcpy(buf1,buf,len);
if (checksum_seed) {
SIVAL(buf1,len,checksum_seed);
len += 4;
}
for(i = 0; i + CSUM_CHUNK <= len; i += CSUM_CHUNK) {
mdfour_update(&m, (uchar *)(buf1+i), CSUM_CHUNK);
}
/*
* Prior to version 27 an incorrect MD4 checksum was computed
* by failing to call mdfour_tail() for block sizes that
* are multiples of 64. This is fixed by calling mdfour_update()
* even when there are no more bytes.
*/
if (len - i > 0 || protocol_version >= 27) {
mdfour_update(&m, (uchar *)(buf1+i), (len-i));
}
mdfour_result(&m, (uchar *)sum);
}
void file_checksum(char *fname,char *sum,OFF_T size)
void file_checksum(char *fname, char *sum, OFF_T size)
{
OFF_T i;
struct map_struct *buf;
OFF_T i, len = size;
md_context m;
int32 remainder;
int fd;
OFF_T len = size;
struct mdfour m;
memset(sum,0,MD4_SUM_LENGTH);
memset(sum, 0, MAX_DIGEST_LEN);
fd = do_open(fname, O_RDONLY, 0);
if (fd == -1)
@@ -109,38 +116,57 @@ void file_checksum(char *fname,char *sum,OFF_T size)
buf = map_file(fd, size, MAX_MAP_SIZE, CSUM_CHUNK);
mdfour_begin(&m);
if (protocol_version >= 30) {
md5_begin(&m);
for(i = 0; i + CSUM_CHUNK <= len; i += CSUM_CHUNK) {
mdfour_update(&m, (uchar *)map_ptr(buf, i, CSUM_CHUNK),
CSUM_CHUNK);
for (i = 0; i + CSUM_CHUNK <= len; i += CSUM_CHUNK) {
md5_update(&m, (uchar *)map_ptr(buf, i, CSUM_CHUNK),
CSUM_CHUNK);
}
remainder = (int32)(len - i);
if (remainder > 0)
md5_update(&m, (uchar *)map_ptr(buf, i, remainder), remainder);
md5_result(&m, (uchar *)sum);
} else {
mdfour_begin(&m);
for (i = 0; i + CSUM_CHUNK <= len; i += CSUM_CHUNK) {
mdfour_update(&m, (uchar *)map_ptr(buf, i, CSUM_CHUNK),
CSUM_CHUNK);
}
/* Prior to version 27 an incorrect MD4 checksum was computed
* by failing to call mdfour_tail() for block sizes that
* are multiples of 64. This is fixed by calling mdfour_update()
* even when there are no more bytes. */
remainder = (int32)(len - i);
if (remainder > 0 || protocol_version >= 27)
mdfour_update(&m, (uchar *)map_ptr(buf, i, remainder), remainder);
mdfour_result(&m, (uchar *)sum);
}
/* Prior to version 27 an incorrect MD4 checksum was computed
* by failing to call mdfour_tail() for block sizes that
* are multiples of 64. This is fixed by calling mdfour_update()
* even when there are no more bytes. */
if (len - i > 0 || protocol_version >= 27)
mdfour_update(&m, (uchar *)map_ptr(buf, i, len-i), len-i);
mdfour_result(&m, (uchar *)sum);
close(fd);
unmap_file(buf);
}
static int32 sumresidue;
static char sumrbuf[CSUM_CHUNK];
static struct mdfour md;
static md_context md;
void sum_init(int seed)
{
char s[4];
mdfour_begin(&md);
sumresidue = 0;
SIVAL(s, 0, seed);
sum_update(s, 4);
if (protocol_version >= 30)
md5_begin(&md);
else {
mdfour_begin(&md);
sumresidue = 0;
SIVAL(s, 0, seed);
sum_update(s, 4);
}
}
/**
@@ -151,18 +177,23 @@ void sum_init(int seed)
* @todo Perhaps get rid of md and just pass in the address each time.
* Very slightly clearer and slower.
**/
void sum_update(char *p, int32 len)
void sum_update(const char *p, int32 len)
{
if (protocol_version >= 30) {
md5_update(&md, (uchar *)p, len);
return;
}
if (len + sumresidue < CSUM_CHUNK) {
memcpy(sumrbuf + sumresidue, p, len);
memcpy(md.buffer + sumresidue, p, len);
sumresidue += len;
return;
}
if (sumresidue) {
int32 i = CSUM_CHUNK - sumresidue;
memcpy(sumrbuf + sumresidue, p, i);
mdfour_update(&md, (uchar *)sumrbuf, CSUM_CHUNK);
memcpy(md.buffer + sumresidue, p, i);
mdfour_update(&md, (uchar *)md.buffer, CSUM_CHUNK);
len -= i;
p += i;
}
@@ -175,13 +206,20 @@ void sum_update(char *p, int32 len)
sumresidue = len;
if (sumresidue)
memcpy(sumrbuf, p, sumresidue);
memcpy(md.buffer, p, sumresidue);
}
void sum_end(char *sum)
int sum_end(char *sum)
{
if (protocol_version >= 30) {
md5_result(&md, (uchar *)sum);
return MD5_DIGEST_LEN;
}
if (sumresidue || protocol_version >= 27)
mdfour_update(&md, (uchar *)sumrbuf, sumresidue);
mdfour_update(&md, (uchar *)md.buffer, sumresidue);
mdfour_result(&md, (uchar *)sum);
return MD4_DIGEST_LEN;
}

13
chmod.c
View File

@@ -2,11 +2,11 @@
* Implement the core of the --chmod option.
*
* Copyright (C) 2002 Scott Howard
* Copyright (C) 2005, 2006 Wayne Davison
* Copyright (C) 2005-2007 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
@@ -15,8 +15,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
* with this program; if not, visit the http://fsf.org website.
*/
#include "rsync.h"
@@ -105,12 +104,12 @@ struct chmod_mode_struct *parse_chmod(const char *modestr,
case 'D':
if (flags & FLAG_FILES_ONLY)
state = STATE_ERROR;
flags |= FLAG_DIRS_ONLY;
flags |= FLAG_DIRS_ONLY;
break;
case 'F':
if (flags & FLAG_DIRS_ONLY)
state = STATE_ERROR;
flags |= FLAG_FILES_ONLY;
flags |= FLAG_FILES_ONLY;
break;
case 'u':
where |= 0100;
@@ -151,7 +150,7 @@ struct chmod_mode_struct *parse_chmod(const char *modestr,
what |= 2;
break;
case 'X':
flags |= FLAG_X_KEEP;
flags |= FLAG_X_KEEP;
/* FALL THROUGH */
case 'x':
what |= 1;

View File

@@ -4,11 +4,11 @@
* Copyright (C) 1996-2000 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2002 Martin Pool
* Copyright (C) 2003, 2004, 2005, 2006 Wayne Davison
* Copyright (C) 2003-2007 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
@@ -17,8 +17,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
* with this program; if not, visit the http://fsf.org website.
*/
#include "rsync.h"
@@ -104,6 +103,11 @@ NORETURN void _exit_cleanup(int code, const char *file, int line)
if (exit_code) /* Preserve first error code when recursing. */
code = exit_code;
/* If this is the exit at the end of the run, the server side
* should not attempt to output a message (see log.c). */
if (am_server && code == 0)
am_server = 2;
/* Some of our actions might cause a recursive call back here, so we
* keep track of where we are in the cleanup and never repeat a step. */
switch (cleanup_step) {
@@ -143,7 +147,7 @@ NORETURN void _exit_cleanup(int code, const char *file, int line)
flush_write_file(cleanup_fd_w);
close(cleanup_fd_w);
}
finish_transfer(cleanup_new_fname, fname, NULL,
finish_transfer(cleanup_new_fname, fname, NULL, NULL,
cleanup_file, 0, !partial_dir);
}
@@ -190,6 +194,8 @@ NORETURN void _exit_cleanup(int code, const char *file, int line)
/* FALLTHROUGH */
#include "case_N.h"
if (am_server && code)
msleep(100);
close_all();
/* FALLTHROUGH */

View File

@@ -3,11 +3,11 @@
*
* Copyright (C) 1992-2001 Andrew Tridgell <tridge@samba.org>
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
* Copyright (C) 2002, 2003, 2004 Wayne Davison
* Copyright (C) 2002-2007 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
@@ -16,8 +16,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
* with this program; if not, visit the http://fsf.org website.
*/
/*

View File

@@ -3,11 +3,11 @@
*
* Copyright (C) 1998-2001 Andrew Tridgell <tridge@samba.org>
* Copyright (C) 2001-2002 Martin Pool <mbp@samba.org>
* Copyright (C) 2002, 2003, 2004, 2005, 2006 Wayne Davison
* Copyright (C) 2002-2007 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
@@ -16,14 +16,13 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
* with this program; if not, visit the http://fsf.org website.
*/
#include "rsync.h"
#include "ifuncs.h"
extern int verbose;
extern int quiet;
extern int output_motd;
extern int list_only;
extern int am_sender;
@@ -31,6 +30,7 @@ extern int am_server;
extern int am_daemon;
extern int am_root;
extern int rsync_port;
extern int ignore_errors;
extern int kluge_around_eof;
extern int daemon_over_rsh;
extern int sanitize_paths;
@@ -51,15 +51,20 @@ extern char *files_from;
extern char *tmpdir;
extern struct chmod_mode_struct *chmod_modes;
extern struct filter_list_struct server_filter_list;
extern char curr_dir[];
char *auth_user;
int read_only = 0;
int module_id = -1;
struct chmod_mode_struct *daemon_chmod_modes;
/* Length of lp_path() string when in daemon mode & not chrooted, else 0. */
/* module_dirlen is the length of the module_dir string when in daemon
* mode, not chrooted, and the path is not "/"; otherwise 0. */
char *module_dir = NULL;
unsigned int module_dirlen = 0;
static int rl_nulls = 0;
#ifdef HAVE_SIGACTION
static struct sigaction sigact;
#endif
@@ -78,7 +83,8 @@ static struct sigaction sigact;
* @return -1 for error in startup, or the result of client_run().
* Either way, it eventually gets passed to exit_cleanup().
**/
int start_socket_client(char *host, char *path, int argc, char *argv[])
int start_socket_client(char *host, int remote_argc, char *remote_argv[],
int argc, char *argv[])
{
int fd, ret;
char *p, *user = NULL;
@@ -86,7 +92,7 @@ int start_socket_client(char *host, char *path, int argc, char *argv[])
/* This is redundant with code in start_inband_exchange(), but this
* short-circuits a problem in the client before we open a socket,
* and the extra check won't hurt. */
if (*path == '/') {
if (**remote_argv == '/') {
rprintf(FERROR,
"ERROR: The remote path must start with a module name not a /\n");
return -1;
@@ -105,19 +111,92 @@ int start_socket_client(char *host, char *path, int argc, char *argv[])
set_socket_options(fd, sockopts);
ret = start_inband_exchange(user, path, fd, fd, argc);
ret = start_inband_exchange(fd, fd, user, remote_argc, remote_argv);
return ret ? ret : client_run(fd, fd, -1, argc, argv);
}
int start_inband_exchange(char *user, char *path, int f_in, int f_out,
int argc)
static int exchange_protocols(int f_in, int f_out, char *buf, size_t bufsiz, int am_client)
{
int remote_sub = -1;
#if SUBPROTOCOL_VERSION != 0
int our_sub = protocol_version < PROTOCOL_VERSION ? 0 : SUBPROTOCOL_VERSION;
#else
int our_sub = 0;
#endif
char *motd;
io_printf(f_out, "@RSYNCD: %d.%d\n", protocol_version, our_sub);
if (!am_client) {
motd = lp_motd_file();
if (motd && *motd) {
FILE *f = fopen(motd,"r");
while (f && !feof(f)) {
int len = fread(buf, 1, bufsiz - 1, f);
if (len > 0)
write_buf(f_out, buf, len);
}
if (f)
fclose(f);
write_sbuf(f_out, "\n");
}
}
/* This strips the \n. */
if (!read_line_old(f_in, buf, bufsiz)) {
if (am_client)
rprintf(FERROR, "rsync: did not see server greeting\n");
return -1;
}
if (sscanf(buf, "@RSYNCD: %d.%d", &remote_protocol, &remote_sub) < 1) {
if (am_client)
rprintf(FERROR, "rsync: server sent \"%s\" rather than greeting\n", buf);
else
io_printf(f_out, "@ERROR: protocol startup error\n");
return -1;
}
if (remote_sub < 0) {
if (remote_protocol == 30) {
if (am_client)
rprintf(FERROR, "rsync: server is speaking an incompatible beta of protocol 30\n");
else
io_printf(f_out, "@ERROR: your client is speaking an incompatible beta of protocol 30\n");
return -1;
}
remote_sub = 0;
}
if (protocol_version > remote_protocol) {
protocol_version = remote_protocol;
if (remote_sub)
protocol_version--;
} else if (protocol_version == remote_protocol) {
if (remote_sub != our_sub)
protocol_version--;
}
#if SUBPROTOCOL_VERSION != 0
else if (protocol_version < remote_protocol) {
if (our_sub)
protocol_version--;
}
#endif
if (protocol_version >= 30)
rl_nulls = 1;
return 0;
}
int start_inband_exchange(int f_in, int f_out, const char *user, int argc, char *argv[])
{
int i;
char line[BIGPATHBUFLEN];
char *sargs[MAX_ARGS];
int sargc = 0;
char line[BIGPATHBUFLEN];
char *p;
char *p, *path = *argv;
if (argc == 0 && !am_sender)
list_only |= 1;
@@ -133,24 +212,8 @@ int start_inband_exchange(char *user, char *path, int f_in, int f_out,
if (!user)
user = getenv("LOGNAME");
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");
if (exchange_protocols(f_in, f_out, line, sizeof line, 1) < 0)
return -1;
}
if (sscanf(line,"@RSYNCD: %d", &remote_protocol) != 1) {
/* note that read_line strips of \n or \r */
rprintf(FERROR, "rsync: server sent \"%s\" rather than greeting\n",
line);
return -1;
}
if (protocol_version > remote_protocol)
protocol_version = remote_protocol;
if (list_only && protocol_version >= 29)
list_only |= 2;
/* set daemon_over_rsh to false since we need to build the
* true set of args passed through the rsh/ssh connection;
@@ -158,18 +221,28 @@ int start_inband_exchange(char *user, char *path, int f_in, int f_out,
daemon_over_rsh = 0;
server_options(sargs, &sargc);
if (sargc >= MAX_ARGS - 2)
goto arg_overflow;
sargs[sargc++] = ".";
if (path && *path)
sargs[sargc++] = path;
while (argc > 0) {
if (sargc >= MAX_ARGS - 1) {
arg_overflow:
rprintf(FERROR, "internal: args[] overflowed in do_cmd()\n");
exit_cleanup(RERR_SYNTAX);
}
sargs[sargc++] = *argv++;
argc--;
}
sargs[sargc] = NULL;
if (verbose > 1)
print_child_argv(sargs);
print_child_argv("sending daemon args:", sargs);
p = strchr(path,'/');
if (p) *p = 0;
p = strchr(path, '/');
if (p) *p = '\0';
io_printf(f_out, "%s\n", path);
if (p) *p = '/';
@@ -178,7 +251,7 @@ int start_inband_exchange(char *user, char *path, int f_in, int f_out,
kluge_around_eof = list_only && protocol_version < 25 ? 1 : 0;
while (1) {
if (!read_line(f_in, line, sizeof line - 1)) {
if (!read_line_old(f_in, line, sizeof line)) {
rprintf(FERROR, "rsync: didn't get server startup line\n");
return -1;
}
@@ -213,10 +286,17 @@ int start_inband_exchange(char *user, char *path, int f_in, int f_out,
}
kluge_around_eof = 0;
for (i = 0; i < sargc; i++) {
io_printf(f_out, "%s\n", sargs[i]);
if (rl_nulls) {
for (i = 0; i < sargc; i++) {
write_sbuf(f_out, sargs[i]);
write_byte(f_out, 0);
}
write_byte(f_out, 0);
} else {
for (i = 0; i < sargc; i++)
io_printf(f_out, "%s\n", sargs[i]);
write_sbuf(f_out, "\n");
}
io_printf(f_out, "\n");
if (protocol_version < 23) {
if (protocol_version == 22 || !am_sender)
@@ -231,12 +311,12 @@ static char *finish_pre_exec(pid_t pid, int fd, char *request,
{
int j, status = -1;
if (request) {
write_buf(fd, request, strlen(request)+1);
for (j = 0; j < argc; j++)
write_buf(fd, argv[j], strlen(argv[j])+1);
}
if (!request)
request = "(NONE)";
write_buf(fd, request, strlen(request)+1);
for (j = 0; j < argc; j++)
write_buf(fd, argv[j], strlen(argv[j])+1);
write_byte(fd, 0);
close(fd);
@@ -244,7 +324,9 @@ static char *finish_pre_exec(pid_t pid, int fd, char *request,
if (wait_process(pid, &status, 0) < 0
|| !WIFEXITED(status) || WEXITSTATUS(status) != 0) {
char *e;
if (asprintf(&e, "pre-xfer exec returned failure (%d)\n", status) < 0)
if (asprintf(&e, "pre-xfer exec returned failure (%d)%s%s\n",
status, status < 0 ? ": " : "",
status < 0 ? strerror(errno) : "") < 0)
out_of_memory("finish_pre_exec");
return e;
}
@@ -270,8 +352,7 @@ static int read_arg_from_pipe(int fd, char *buf, int limit)
static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
{
int argc = 0;
int maxargs;
int argc, opt_cnt;
char **argv;
char line[BIGPATHBUFLEN];
uid_t uid = (uid_t)-2; /* canonically "nobody" */
@@ -279,7 +360,6 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
char *p, *err_msg = NULL;
char *name = lp_name(i);
int use_chroot = lp_use_chroot(i);
int start_glob = 0;
int ret, pre_exec_fd = -1;
pid_t pre_exec_pid = 0;
char *request = NULL;
@@ -340,7 +420,7 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
if (am_root) {
p = lp_uid(i);
if (!name_to_uid(p, &uid)) {
if (!isdigit(*(unsigned char *)p)) {
if (!isDigit(p)) {
rprintf(FLOG, "Invalid uid %s\n", p);
io_printf(f_out, "@ERROR: invalid uid %s\n", p);
return -1;
@@ -350,7 +430,7 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
p = lp_gid(i);
if (!name_to_gid(p, &gid)) {
if (!isdigit(*(unsigned char *)p)) {
if (!isDigit(p)) {
rprintf(FLOG, "Invalid gid %s\n", p);
io_printf(f_out, "@ERROR: invalid gid %s\n", p);
return -1;
@@ -366,11 +446,22 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
/* TODO: Perhaps take a list of gids, and make them into the
* supplementary groups. */
if (use_chroot || (module_dirlen = strlen(lp_path(i))) == 1) {
/* We do a push_dir() without actually calling chdir() in order
* to make sure that the module's path is absolute. After this
* check, module_dir will be set to an absolute path. */
module_dir = lp_path(i);
strlcpy(line, curr_dir, sizeof line);
if (!push_dir(module_dir, 1))
goto chdir_failed;
if (strcmp(curr_dir, module_dir) != 0)
module_dir = strdup(curr_dir);
push_dir(line, 1); /* Restore curr_dir. */
if (use_chroot || (module_dirlen = strlen(module_dir)) == 1) {
module_dirlen = 0;
set_filter_dir("/", 1);
} else
set_filter_dir(lp_path(i), module_dirlen);
set_filter_dir(module_dir, module_dirlen);
p = lp_filter(i);
parse_rule(&server_filter_list, p, MATCHFLG_WORD_SPLIT,
@@ -400,7 +491,7 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
char *modname, *modpath, *hostaddr, *hostname, *username;
int status;
if (asprintf(&modname, "RSYNC_MODULE_NAME=%s", name) < 0
|| asprintf(&modpath, "RSYNC_MODULE_PATH=%s", lp_path(i)) < 0
|| asprintf(&modpath, "RSYNC_MODULE_PATH=%s", module_dir) < 0
|| asprintf(&hostaddr, "RSYNC_HOST_ADDR=%s", addr) < 0
|| asprintf(&hostname, "RSYNC_HOST_NAME=%s", host) < 0
|| asprintf(&username, "RSYNC_USER_NAME=%s", auth_user) < 0)
@@ -500,24 +591,17 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
* a warning, unless a "require chroot" flag is set,
* in which case we fail.
*/
if (chroot(lp_path(i))) {
rsyserr(FLOG, errno, "chroot %s failed",
lp_path(i));
if (chroot(module_dir)) {
rsyserr(FLOG, errno, "chroot %s failed", module_dir);
io_printf(f_out, "@ERROR: chroot failed\n");
return -1;
}
if (!push_dir("/", 0)) {
rsyserr(FLOG, errno, "chdir %s failed\n",
lp_path(i));
io_printf(f_out, "@ERROR: chdir failed\n");
return -1;
}
if (!push_dir("/", 0))
goto chdir_failed;
} else {
if (!push_dir(lp_path(i), 0)) {
rsyserr(FLOG, errno, "chdir %s failed\n",
lp_path(i));
if (!push_dir(module_dir, 0)) {
chdir_failed:
rsyserr(FLOG, errno, "chdir %s failed\n", module_dir);
io_printf(f_out, "@ERROR: chdir failed\n");
return -1;
}
@@ -571,59 +655,23 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
io_printf(f_out, "@RSYNCD: OK\n");
maxargs = MAX_ARGS;
if (!(argv = new_array(char *, maxargs)))
out_of_memory("rsync_module");
argv[argc++] = "rsyncd";
while (1) {
if (!read_line(f_in, line, sizeof line - 1))
return -1;
if (!*line)
break;
p = line;
if (argc == maxargs) {
maxargs += MAX_ARGS;
if (!(argv = realloc_array(argv, char *, maxargs)))
out_of_memory("rsync_module");
}
if (!(argv[argc] = strdup(p)))
out_of_memory("rsync_module");
switch (start_glob) {
case 0:
argc++;
if (strcmp(line, ".") == 0)
start_glob = 1;
break;
case 1:
if (pre_exec_pid) {
err_msg = finish_pre_exec(pre_exec_pid,
pre_exec_fd, p,
argc, argv);
pre_exec_pid = 0;
}
request = strdup(p);
start_glob = 2;
/* FALL THROUGH */
default:
if (!err_msg)
glob_expand(name, &argv, &argc, &maxargs);
break;
}
}
opt_cnt = read_args(f_in, name, line, sizeof line, rl_nulls, &argv, &argc, &request);
if (pre_exec_pid) {
err_msg = finish_pre_exec(pre_exec_pid, pre_exec_fd, request,
argc, argv);
opt_cnt, argv);
}
verbose = 0; /* future verbosity is controlled by client options */
ret = parse_arguments(&argc, (const char ***) &argv, 0);
quiet = 0; /* Don't let someone try to be tricky. */
am_server = 1; /* Don't let someone try to be tricky. */
if (lp_ignore_errors(module_id))
ignore_errors = 1;
if (lp_fake_super(i))
am_root = -1;
else if (am_root < 0) /* Treat --fake-super from client as --super. */
am_root = 2;
if (filesfrom_fd == 0)
filesfrom_fd = f_in;
@@ -678,7 +726,7 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
if (!ret || err_msg) {
if (err_msg)
rprintf(FERROR, err_msg);
rwrite(FERROR, err_msg, strlen(err_msg), 0);
else
option_error();
msleep(400);
@@ -728,7 +776,7 @@ static void send_listing(int fd)
int start_daemon(int f_in, int f_out)
{
char line[1024];
char *motd, *addr, *host;
char *addr, *host;
int i;
io_set_sock_fds(f_in, f_out);
@@ -753,35 +801,11 @@ int start_daemon(int f_in, int f_out)
set_nonblocking(f_in);
}
io_printf(f_out, "@RSYNCD: %d\n", protocol_version);
motd = lp_motd_file();
if (motd && *motd) {
FILE *f = fopen(motd,"r");
while (f && !feof(f)) {
int len = fread(line, 1, sizeof line - 1, f);
if (len > 0) {
line[len] = 0;
io_printf(f_out, "%s", line);
}
}
if (f)
fclose(f);
io_printf(f_out, "\n");
}
if (!read_line(f_in, line, sizeof line - 1))
if (exchange_protocols(f_in, f_out, line, sizeof line, 0) < 0)
return -1;
if (sscanf(line,"@RSYNCD: %d", &remote_protocol) != 1) {
io_printf(f_out, "@ERROR: protocol startup error\n");
return -1;
}
if (protocol_version > remote_protocol)
protocol_version = remote_protocol;
line[0] = 0;
if (!read_line(f_in, line, sizeof line - 1))
if (!read_line_old(f_in, line, sizeof line))
return -1;
if (!*line || strcmp(line, "#list") == 0) {
@@ -812,9 +836,70 @@ int start_daemon(int f_in, int f_out)
return rsync_module(f_in, f_out, i, addr, host);
}
static void create_pid_file(void)
{
char *pid_file = lp_pid_file();
char pidbuf[16];
pid_t pid = getpid();
int fd;
if (!pid_file || !*pid_file)
return;
cleanup_set_pid(pid);
if ((fd = do_open(pid_file, O_WRONLY|O_CREAT|O_EXCL, 0666 & ~orig_umask)) == -1) {
cleanup_set_pid(0);
fprintf(stderr, "failed to create pid file %s: %s\n", pid_file, strerror(errno));
rsyserr(FLOG, errno, "failed to create pid file %s", pid_file);
exit_cleanup(RERR_FILEIO);
}
snprintf(pidbuf, sizeof pidbuf, "%ld\n", (long)pid);
write(fd, pidbuf, strlen(pidbuf));
close(fd);
}
/* Become a daemon, discarding the controlling terminal. */
static void become_daemon(void)
{
int i;
pid_t pid = fork();
if (pid) {
if (pid < 0) {
fprintf(stderr, "failed to fork: %s\n", strerror(errno));
exit_cleanup(RERR_FILEIO);
}
_exit(0);
}
create_pid_file();
/* detach from the terminal */
#ifdef HAVE_SETSID
setsid();
#elif defined TIOCNOTTY
i = open("/dev/tty", O_RDWR);
if (i >= 0) {
ioctl(i, (int)TIOCNOTTY, (char *)0);
close(i);
}
#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);
open("/dev/null", O_RDWR);
}
}
int daemon_main(void)
{
char *pid_file;
if (!config_file) {
if (am_server && am_root <= 0)
config_file = RSYNCD_USERCONF;
else
config_file = RSYNCD_SYSCONF;
}
if (is_a_socket(STDIN_FILENO)) {
int i;
@@ -830,11 +915,15 @@ int daemon_main(void)
return start_daemon(STDIN_FILENO, STDIN_FILENO);
}
if (!no_detach)
become_daemon();
if (!lp_load(config_file, 1))
if (!lp_load(config_file, 1)) {
fprintf(stderr, "Failed to parse config file: %s\n", config_file);
exit_cleanup(RERR_SYNTAX);
}
if (no_detach)
create_pid_file();
else
become_daemon();
if (rsync_port == 0 && (rsync_port = lp_rsync_port()) == 0)
rsync_port = RSYNC_PORT;
@@ -849,23 +938,6 @@ int daemon_main(void)
* address too. In fact, why not just do inet_ntop on the
* local address??? */
if (((pid_file = lp_pid_file()) != NULL) && (*pid_file != '\0')) {
char pidbuf[16];
int fd;
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) {
cleanup_set_pid(0);
rsyserr(FLOG, errno, "failed to create pid file %s",
pid_file);
exit_cleanup(RERR_FILEIO);
}
snprintf(pidbuf, sizeof pidbuf, "%ld\n", (long)pid);
write(fd, pidbuf, strlen(pidbuf));
close(fd);
}
start_accept_loop(rsync_port, start_daemon);
return -1;
}

146
compat.c
View File

@@ -3,11 +3,11 @@
*
* Copyright (C) Andrew Tridgell 1996
* Copyright (C) Paul Mackerras 1996
* Copyright (C) 2004, 2005, 2006 Wayne Davison
* Copyright (C) 2004-2007 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
@@ -16,28 +16,110 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
* with this program; if not, visit the http://fsf.org website.
*/
#include "rsync.h"
int remote_protocol = 0;
int file_extra_cnt = 0; /* count of file-list extras that everyone gets */
int inc_recurse = 0;
extern int verbose;
extern int am_server;
extern int am_sender;
extern int local_server;
extern int inplace;
extern int recurse;
extern int use_qsort;
extern int allow_inc_recurse;
extern int append_mode;
extern int fuzzy_basis;
extern int read_batch;
extern int delay_updates;
extern int checksum_seed;
extern int basis_dir_cnt;
extern int prune_empty_dirs;
extern int protocol_version;
extern int protect_args;
extern int preserve_uid;
extern int preserve_gid;
extern int preserve_acls;
extern int preserve_xattrs;
extern int need_messages_from_generator;
extern int delete_mode, delete_before, delete_during, delete_after;
extern char *shell_cmd; /* contains VER.SUB string if client is a pre-release */
extern char *partial_dir;
extern char *dest_option;
extern char *files_from;
extern char *filesfrom_host;
extern struct filter_list_struct filter_list;
#ifdef ICONV_OPTION
extern char *iconv_opt;
extern iconv_t ic_send, ic_recv;
#endif
/* These index values are for the file-list's extra-attribute array. */
int uid_ndx, gid_ndx, acls_ndx, xattrs_ndx;
#ifdef ICONV_OPTION
int ic_ndx;
int filesfrom_convert = 0;
#endif
/* The server makes sure that if either side only supports a pre-release
* version of a protocol, that both sides must speak a compatible version
* of that protocol for it to be advertised as available. */
static void check_sub_protocol(void)
{
char *dot;
int their_protocol, their_sub;
#if SUBPROTOCOL_VERSION != 0
int our_sub = protocol_version < PROTOCOL_VERSION ? 0 : SUBPROTOCOL_VERSION;
#else
int our_sub = 0;
#endif
if (!shell_cmd || !(dot = strchr(shell_cmd, '.'))
|| !(their_protocol = atoi(shell_cmd))
|| !(their_sub = atoi(dot+1))) {
#if SUBPROTOCOL_VERSION != 0
if (our_sub)
protocol_version--;
#endif
return;
}
if (their_protocol < protocol_version) {
if (their_sub)
protocol_version = their_protocol - 1;
return;
}
if (their_protocol > protocol_version)
their_sub = 0; /* 0 == final version of older protocol */
if (their_sub != our_sub)
protocol_version--;
}
void setup_protocol(int f_out,int f_in)
{
if (am_sender)
file_extra_cnt += PTR_EXTRA_CNT;
else
file_extra_cnt++;
if (preserve_uid)
uid_ndx = ++file_extra_cnt;
if (preserve_gid)
gid_ndx = ++file_extra_cnt;
if (preserve_acls && !am_sender)
acls_ndx = ++file_extra_cnt;
if (preserve_xattrs)
xattrs_ndx = ++file_extra_cnt;
if (remote_protocol == 0) {
if (am_server && !local_server)
check_sub_protocol();
if (!read_batch)
write_int(f_out, protocol_version);
remote_protocol = read_int(f_in);
@@ -45,7 +127,7 @@ void setup_protocol(int f_out,int f_in)
protocol_version = remote_protocol;
}
if (read_batch && remote_protocol > protocol_version) {
rprintf(FERROR, "The protocol version in the batch file is too new (%d > %d).\n",
rprintf(FERROR, "The protocol version in the batch file is too new (%d > %d).\n",
remote_protocol, protocol_version);
exit_cleanup(RERR_PROTOCOL);
}
@@ -75,6 +157,32 @@ void setup_protocol(int f_out,int f_in)
exit_cleanup(RERR_PROTOCOL);
}
if (protocol_version < 30) {
if (append_mode == 1)
append_mode = 2;
if (preserve_acls && !local_server) {
rprintf(FERROR,
"--acls requires protocol 30 or higher"
" (negotiated %d).\n",
protocol_version);
exit_cleanup(RERR_PROTOCOL);
}
if (preserve_xattrs && !local_server) {
rprintf(FERROR,
"--xattrs requires protocol 30 or higher"
" (negotiated %d).\n",
protocol_version);
exit_cleanup(RERR_PROTOCOL);
}
}
if (delete_mode && !(delete_before+delete_during+delete_after)) {
if (protocol_version < 30)
delete_before = 1;
else
delete_during = 1;
}
if (protocol_version < 29) {
if (fuzzy_basis) {
rprintf(FERROR,
@@ -107,8 +215,36 @@ void setup_protocol(int f_out,int f_in)
protocol_version);
exit_cleanup(RERR_PROTOCOL);
}
} else if (protocol_version >= 30) {
if (recurse && allow_inc_recurse
&& !delete_before && !delete_after && !delay_updates
&& !use_qsort && !prune_empty_dirs)
inc_recurse = 1;
need_messages_from_generator = 1;
}
#ifdef ICONV_OPTION
if (iconv_opt && (!am_sender || inc_recurse))
ic_ndx = ++file_extra_cnt;
#endif
if (partial_dir && *partial_dir != '/' && (!am_server || local_server)) {
int flags = MATCHFLG_NO_PREFIXES | MATCHFLG_DIRECTORY;
if (!am_sender || protocol_version >= 30)
flags |= MATCHFLG_PERISHABLE;
parse_rule(&filter_list, partial_dir, flags, 0);
}
#ifdef ICONV_OPTION
if (protect_args && files_from) {
if (am_sender)
filesfrom_convert = filesfrom_host && ic_send != (iconv_t)-1;
else
filesfrom_convert = !filesfrom_host && ic_recv != (iconv_t)-1;
}
#endif
if (am_server) {
if (!checksum_seed)
checksum_seed = time(NULL);

View File

@@ -5,7 +5,7 @@ AC_CONFIG_SRCDIR([byteorder.h])
AC_CONFIG_HEADER(config.h)
AC_PREREQ(2.59)
RSYNC_VERSION=2.6.9
RSYNC_VERSION=3.0.0pre2
AC_SUBST(RSYNC_VERSION)
AC_MSG_NOTICE([Configuring rsync $RSYNC_VERSION])
@@ -38,7 +38,7 @@ fi
AC_MSG_CHECKING([whether to include debugging symbols])
AC_ARG_ENABLE(debug,
AC_HELP_STRING([--disable-debug],
[turn off debugging symbols and features]))
[disable debugging symbols and features]))
if test x"$enable_debug" = x"no"; then
AC_MSG_RESULT(no)
@@ -283,7 +283,7 @@ fi
dnl Do you want to disable use of locale functions
AC_ARG_ENABLE([locale],
AC_HELP_STRING([--disable-locale],
[turn off locale features]))
[disable locale features]))
AH_TEMPLATE([CONFIG_LOCALE],
[Undefine if you don't want locale features. By default this is defined.])
if test x"$enable_locale" != x"no"; then
@@ -339,8 +339,14 @@ AC_CHECK_SIZEOF(int)
AC_CHECK_SIZEOF(long)
AC_CHECK_SIZEOF(long long)
AC_CHECK_SIZEOF(short)
AC_CHECK_SIZEOF(int16_t)
AC_CHECK_SIZEOF(uint16_t)
AC_CHECK_SIZEOF(int32_t)
AC_CHECK_SIZEOF(uint32_t)
AC_CHECK_SIZEOF(int64_t)
AC_CHECK_SIZEOF(off_t)
AC_CHECK_SIZEOF(off64_t)
AC_CHECK_SIZEOF(time_t)
AC_C_INLINE
AC_C_LONG_DOUBLE
@@ -405,6 +411,28 @@ AC_SEARCH_LIBS(inet_ntop, resolv)
# Search for libiconv_open (not iconv_open) to discover if -liconv is needed!
AC_SEARCH_LIBS(libiconv_open, iconv)
AC_MSG_CHECKING([for iconv declaration])
AC_CACHE_VAL(am_cv_proto_iconv, [
AC_TRY_COMPILE([
#include <stdlib.h>
#include <iconv.h>
extern
#ifdef __cplusplus
"C"
#endif
#if defined(__STDC__) || defined(__cplusplus)
size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);
#else
size_t iconv();
#endif
], [], am_cv_proto_iconv_arg1="", am_cv_proto_iconv_arg1="const")
am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);"])
am_cv_proto_iconv=`echo "[$]am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'`
AC_MSG_RESULT([$]{ac_t:-
}[$]am_cv_proto_iconv)
AC_DEFINE_UNQUOTED(ICONV_CONST, $am_cv_proto_iconv_arg1,
[Define as const if the declaration of iconv() needs const.])
dnl AC_MSG_NOTICE([Looking in libraries: $LIBS])
AC_CHECK_FUNCS(inet_ntop, , [AC_LIBOBJ(lib/inet_ntop)])
@@ -515,6 +543,11 @@ if test x"$ac_cv_func_strcasecmp" = x"no"; then
AC_CHECK_LIB(resolv, strcasecmp)
fi
AC_CHECK_FUNCS(aclsort)
if test x"$ac_cv_func_aclsort" = x"no"; then
AC_CHECK_LIB(sec, aclsort)
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.
@@ -527,14 +560,30 @@ AC_CHECK_FUNCS(waitpid wait4 getcwd strdup chown chmod lchmod mknod mkfifo \
memmove lchown vsnprintf snprintf vasprintf asprintf setsid glob strpbrk \
strlcat strlcpy strtol mallinfo getgroups setgroups geteuid getegid \
setlocale setmode open64 lseek64 mkstemp64 mtrace va_copy __va_copy \
strerror putenv iconv_open locale_charset nl_langinfo \
sigaction sigprocmask)
strerror putenv iconv_open locale_charset nl_langinfo getxattr \
extattr_get_link sigaction sigprocmask)
AC_CHECK_FUNCS(getpgrp tcgetpgrp)
if test $ac_cv_func_getpgrp = yes; then
AC_FUNC_GETPGRP
fi
AC_ARG_ENABLE(iconv,
AC_HELP_STRING([--disable-iconv],
[disable rsync's --iconv option]),
[], [enable_iconv=$ac_cv_func_iconv_open])
AH_TEMPLATE([ICONV_OPTION],
[Define if you want the --iconv option. Specifing a value will set the
default iconv setting (a NULL means no --iconv processing by default).])
if test x"$enable_iconv" != x"no"; then
if test x"$enable_iconv" = x"yes"; then
AC_DEFINE(ICONV_OPTION, NULL)
else
AC_DEFINE_UNQUOTED(ICONV_OPTION, "$enable_iconv")
fi
AC_DEFINE(UTF8_CHARSET, "UTF-8", [String to pass to iconv() for the UTF-8 charset.])
fi
AC_CACHE_CHECK([whether chown() modifies symlinks],rsync_cv_chown_modifies_symlink,[
AC_TRY_RUN([
#if HAVE_UNISTD_H
@@ -779,6 +828,133 @@ AC_SUBST(OBJ_RESTORE)
AC_SUBST(CC_SHOBJ_FLAG)
AC_SUBST(BUILD_POPT)
AC_CHECK_HEADERS(sys/acl.h acl/libacl.h)
AC_CHECK_FUNCS(_acl __acl _facl __facl)
#################################################
# check for ACL support
AC_MSG_CHECKING([whether to support ACLs])
AC_ARG_ENABLE(acl-support,
AC_HELP_STRING([--disable-acl-support],
[disable ACL support]))
if test x"$enable_acl_support" = x"no"; then
AC_MSG_RESULT(no)
else
case "$host_os" in
*sysv5*)
AC_MSG_RESULT(Using UnixWare ACLs)
AC_DEFINE(HAVE_UNIXWARE_ACLS, 1, [true if you have UnixWare ACLs])
AC_DEFINE(SUPPORT_ACLS, 1, [Define to 1 to add support for ACLs])
;;
*solaris*|*cygwin*)
AC_MSG_RESULT(Using solaris ACLs)
AC_DEFINE(HAVE_SOLARIS_ACLS, 1, [true if you have solaris ACLs])
AC_DEFINE(SUPPORT_ACLS, 1)
;;
*hpux*)
AC_MSG_RESULT(Using HPUX ACLs)
AC_DEFINE(HAVE_HPUX_ACLS, 1, [true if you have HPUX ACLs])
AC_DEFINE(SUPPORT_ACLS, 1)
;;
*irix*)
AC_MSG_RESULT(Using IRIX ACLs)
AC_DEFINE(HAVE_IRIX_ACLS, 1, [true if you have IRIX ACLs])
AC_DEFINE(SUPPORT_ACLS, 1)
;;
*aix*)
AC_MSG_RESULT(Using AIX ACLs)
AC_DEFINE(HAVE_AIX_ACLS, 1, [true if you have AIX ACLs])
AC_DEFINE(SUPPORT_ACLS, 1)
;;
*osf*)
AC_MSG_RESULT(Using Tru64 ACLs)
AC_DEFINE(HAVE_TRU64_ACLS, 1, [true if you have Tru64 ACLs])
AC_DEFINE(SUPPORT_ACLS, 1)
LIBS="$LIBS -lpacl"
;;
darwin*)
AC_MSG_RESULT(Using OS X ACLs)
AC_DEFINE(HAVE_OSX_ACLS, 1, [true if you have Mac OS X ACLs])
AC_DEFINE(SUPPORT_ACLS, 1)
;;
*)
AC_MSG_RESULT(running tests:)
AC_CHECK_LIB(acl,acl_get_file)
AC_CACHE_CHECK([for ACL support],samba_cv_HAVE_POSIX_ACLS,[
AC_TRY_LINK([#include <sys/types.h>
#include <sys/acl.h>],
[ acl_t acl; int entry_id; acl_entry_t *entry_p; return acl_get_entry( acl, entry_id, entry_p);],
samba_cv_HAVE_POSIX_ACLS=yes,samba_cv_HAVE_POSIX_ACLS=no)])
AC_MSG_CHECKING(ACL test results)
if test x"$samba_cv_HAVE_POSIX_ACLS" = x"yes"; then
AC_MSG_RESULT(Using posix ACLs)
AC_DEFINE(HAVE_POSIX_ACLS, 1, [true if you have posix ACLs])
AC_DEFINE(SUPPORT_ACLS, 1)
AC_CACHE_CHECK([for acl_get_perm_np],samba_cv_HAVE_ACL_GET_PERM_NP,[
AC_TRY_LINK([#include <sys/types.h>
#include <sys/acl.h>],
[ acl_permset_t permset_d; acl_perm_t perm; return acl_get_perm_np( permset_d, perm);],
samba_cv_HAVE_ACL_GET_PERM_NP=yes,samba_cv_HAVE_ACL_GET_PERM_NP=no)])
if test x"$samba_cv_HAVE_ACL_GET_PERM_NP" = x"yes"; then
AC_DEFINE(HAVE_ACL_GET_PERM_NP, 1, [true if you have acl_get_perm_np])
fi
else
if test x"$enable_acl_support" = x"yes"; then
AC_MSG_ERROR(Failed to find ACL support)
else
AC_MSG_RESULT(No ACL support found)
fi
fi
;;
esac
fi
AC_CHECK_HEADERS(attr/xattr.h)
AC_CHECK_HEADERS(sys/xattr.h)
AC_CHECK_HEADERS(sys/extattr.h)
#################################################
# check for extended attribute support
AC_MSG_CHECKING(whether to support extended attributes)
AC_ARG_ENABLE(xattr-support,
AC_HELP_STRING([--disable-xattr-support],
[disable extended attributes]),
[], [case "$ac_cv_func_getxattr$ac_cv_func_extattr_get_link" in
*yes*) enable_xattr_support=maybe ;;
*) enable_xattr_support=no ;;
esac])
AH_TEMPLATE([SUPPORT_XATTRS],
[Define to 1 to add support for extended attributes])
if test x"$enable_xattr_support" = x"no"; then
AC_MSG_RESULT(no)
else
case "$host_os" in
*linux*)
AC_MSG_RESULT(Using Linux xattrs)
AC_DEFINE(HAVE_LINUX_XATTRS, 1, [True if you have Linux xattrs])
AC_DEFINE(SUPPORT_XATTRS, 1)
;;
darwin*)
AC_MSG_RESULT(Using OS X xattrs)
AC_DEFINE(HAVE_OSX_XATTRS, 1, [True if you have Mac OS X xattrs])
AC_DEFINE(SUPPORT_XATTRS, 1)
;;
freebsd*)
AC_MSG_RESULT(Using FreeBSD extattrs)
AC_DEFINE(HAVE_FREEBSD_XATTRS, 1, [True if you have FreeBSD xattrs])
AC_DEFINE(SUPPORT_XATTRS, 1)
;;
*)
if test x"$enable_xattr_support" = x"yes"; then
AC_MSG_ERROR(Failed to find extended attribute support)
else
AC_MSG_RESULT(No extended attribute support found)
fi
;;
esac
fi
AC_CONFIG_FILES([Makefile lib/dummy zlib/dummy popt/dummy shconfig])
AC_OUTPUT

View File

@@ -5,7 +5,7 @@
*
* 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
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
@@ -14,36 +14,33 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
* with this program; if not, visit the http://fsf.org website.
*/
#include "rsync.h"
/****************************************************************************
simple routine to do connection counting
****************************************************************************/
int claim_connection(char *fname,int max_connections)
/* A simple routine to do connection counting. This returns 1 on success
* and 0 on failure, with errno also being set if the open() failed (errno
* will be 0 if the lock request failed). */
int claim_connection(char *fname, int max_connections)
{
int fd, i;
if (max_connections <= 0)
if (max_connections == 0)
return 1;
fd = open(fname,O_RDWR|O_CREAT, 0600);
if (fd == -1) {
if ((fd = open(fname, O_RDWR|O_CREAT, 0600)) < 0)
return 0;
}
/* find a free spot */
for (i=0;i<max_connections;i++) {
if (lock_range(fd, i*4, 4)) return 1;
/* Find a free spot. */
for (i = 0; i < max_connections; i++) {
if (lock_range(fd, i*4, 4))
return 1;
}
/* only interested in open failures */
errno = 0;
close(fd);
/* A lock failure needs to return an errno of 0. */
errno = 0;
return 0;
}

View File

@@ -2,11 +2,11 @@
* Error codes returned by rsync.
*
* Copyright (C) 1998-2000 Andrew Tridgell
* Copyright (C) 2003, 2005 Wayne Davison
* Copyright (C) 2003-2007 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
@@ -15,8 +15,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
* with this program; if not, visit the http://fsf.org website.
*/
/* If you change these, please also update the string mappings in log.c and

View File

@@ -4,11 +4,11 @@
* Copyright (C) 1996-2001 Andrew Tridgell <tridge@samba.org>
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2002 Martin Pool
* Copyright (C) 2003, 2004, 2005, 2006 Wayne Davison
* Copyright (C) 2003-2007 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
@@ -17,8 +17,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
* with this program; if not, visit the http://fsf.org website.
*/
#include "rsync.h"
@@ -27,11 +26,11 @@ extern int verbose;
extern int am_server;
extern int am_sender;
extern int eol_nulls;
extern int list_only;
extern int recurse;
extern int io_error;
extern int local_server;
extern int prune_empty_dirs;
extern int ignore_perishable;
extern int delete_mode;
extern int delete_excluded;
extern int cvs_exclude;
@@ -51,8 +50,8 @@ struct filter_list_struct server_filter_list = { 0, 0, " [daemon]" };
#define MAX_RULE_PREFIX (16)
#define MODIFIERS_MERGE_FILE "-+Cenw"
#define MODIFIERS_INCL_EXCL "/!Crs"
#define MODIFIERS_HIDE_PROTECT "/!"
#define MODIFIERS_INCL_EXCL "/!Crsp"
#define MODIFIERS_HIDE_PROTECT "/!p"
/* The dirbuf is set by push_local_filters() to the current subdirectory
* relative to curr_dir that is being processed. The path always has a
@@ -144,9 +143,8 @@ static void add_rule(struct filter_list_struct *listp, const char *pat,
}
}
if (!(ret = new(struct filter_struct)))
if (!(ret = new0(struct filter_struct)))
out_of_memory("add_rule");
memset(ret, 0, sizeof ret[0]);
if (!(mflags & (MATCHFLG_ABS_PATH | MATCHFLG_MERGE_FILE))
&& ((xflags & (XFLG_ANCHORED2ABS|XFLG_ABS_IF_SLASH) && *pat == '/')
@@ -492,6 +490,34 @@ void pop_local_filters(void *mem)
free(pop);
}
void change_local_filter_dir(const char *dname, int dlen, int dir_depth)
{
static int cur_depth = -1;
static void *filt_array[MAXPATHLEN/2+1];
if (!dname) {
for ( ; cur_depth >= 0; cur_depth--) {
if (filt_array[cur_depth]) {
pop_local_filters(filt_array[cur_depth]);
filt_array[cur_depth] = NULL;
}
}
return;
}
assert(dir_depth < MAXPATHLEN/2+1);
for ( ; cur_depth >= dir_depth; cur_depth--) {
if (filt_array[cur_depth]) {
pop_local_filters(filt_array[cur_depth]);
filt_array[cur_depth] = NULL;
}
}
cur_depth = dir_depth;
filt_array[cur_depth] = push_local_filters(dname, dlen);
}
static int rule_matches(char *name, struct filter_struct *ex, int name_is_dir)
{
int slash_handling, str_cnt = 0, anchored_match = 0;
@@ -601,6 +627,8 @@ int check_filter(struct filter_list_struct *listp, char *name, int name_is_dir)
struct filter_struct *ent;
for (ent = listp->head; ent; ent = ent->next) {
if (ignore_perishable && ent->match_flags & MATCHFLG_PERISHABLE)
continue;
if (ent->match_flags & MATCHFLG_PERDIR_MERGE) {
int rc = check_filter(ent->u.mergelist, name,
name_is_dir);
@@ -808,6 +836,9 @@ static const char *parse_rule_tok(const char *p, uint32 mflags, int xflags,
case 'n':
new_mflags |= MATCHFLG_NO_INHERIT;
break;
case 'p':
new_mflags |= MATCHFLG_PERISHABLE;
break;
case 'r':
new_mflags |= MATCHFLG_RECEIVER_SIDE;
break;
@@ -873,14 +904,16 @@ static char default_cvsignore[] =
static void get_cvs_excludes(uint32 mflags)
{
char *p, fname[MAXPATHLEN];
static int initialized = 0;
char *p, fname[MAXPATHLEN];
if (initialized)
return;
initialized = 1;
parse_rule(&cvs_filter_list, default_cvsignore, mflags, 0);
parse_rule(&cvs_filter_list, default_cvsignore,
mflags | (protocol_version >= 30 ? MATCHFLG_PERISHABLE : 0),
0);
p = module_id >= 0 && lp_use_chroot(module_id) ? "/" : getenv("HOME");
if (p && pathjoin(fname, MAXPATHLEN, p, ".cvsignore") < MAXPATHLEN)
@@ -1064,6 +1097,8 @@ char *get_rule_prefix(int match_flags, const char *pat, int for_xfer,
else
legal_len = 0;
if (match_flags & MATCHFLG_NEGATE)
*op++ = '!';
if (match_flags & MATCHFLG_CVS_IGNORE)
*op++ = 'C';
else {
@@ -1087,6 +1122,12 @@ char *get_rule_prefix(int match_flags, const char *pat, int for_xfer,
&& (!for_xfer || protocol_version >= 29
|| (delete_excluded && am_sender)))
*op++ = 'r';
if (match_flags & MATCHFLG_PERISHABLE) {
if (!for_xfer || protocol_version >= 30)
*op++ = 'p';
else if (am_sender)
return NULL;
}
if (op - buf > legal_len)
return NULL;
if (legal_len)
@@ -1141,7 +1182,7 @@ static void send_rules(int f_out, struct filter_list_struct *flp)
if (!p) {
rprintf(FERROR,
"filter rules are too modern for remote rsync.\n");
exit_cleanup(RERR_SYNTAX);
exit_cleanup(RERR_PROTOCOL);
}
if (f_out < 0)
continue;
@@ -1173,11 +1214,6 @@ void send_filter_list(int f_out)
parse_rule(&filter_list, "-C", 0, 0);
}
/* This is a complete hack - blame Rusty. FIXME!
* Remove this hack when older rsyncs (below 2.6.4) are gone. */
if (list_only == 1 && !recurse)
parse_rule(&filter_list, "/*/*", MATCHFLG_NO_PREFIXES, 0);
send_rules(f_out, &filter_list);
if (f_out >= 0)

View File

@@ -3,11 +3,11 @@
*
* Copyright (C) 1998 Andrew Tridgell
* Copyright (C) 2002 Martin Pool
* Copyright (C) 2004, 2005, 2006 Wayne Davison
* Copyright (C) 2004-2007 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
@@ -16,8 +16,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
* with this program; if not, visit the http://fsf.org website.
*/
#include "rsync.h"
@@ -29,47 +28,55 @@
extern int sparse_files;
static char last_byte;
static int last_sparse;
static size_t sparse_seek = 0;
int sparse_end(int f)
{
if (last_sparse) {
do_lseek(f,-1,SEEK_CUR);
return (write(f,&last_byte,1) == 1 ? 0 : -1);
}
last_sparse = 0;
return 0;
int ret;
if (!sparse_seek)
return 0;
do_lseek(f, sparse_seek-1, SEEK_CUR);
sparse_seek = 0;
do {
ret = write(f, "", 1);
} while (ret < 0 && errno == EINTR);
return ret <= 0 ? -1 : 0;
}
static int write_sparse(int f,char *buf,size_t len)
static int write_sparse(int f, char *buf, size_t len)
{
size_t l1=0, l2=0;
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++) {}
/* XXX Riddle me this: why does this function SLOW DOWN when I
* remove the following (unneeded) line?? Core Duo weirdness? */
last_byte = buf[len-1];
if (l1 == len || l2 > 0)
last_sparse=1;
if (l1 > 0) {
do_lseek(f,l1,SEEK_CUR);
}
sparse_seek += l1;
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)))
return (l1+ret);
if (sparse_seek)
do_lseek(f, sparse_seek, SEEK_CUR);
sparse_seek = l2;
if (l2 > 0)
do_lseek(f,l2,SEEK_CUR);
while ((ret = write(f, buf + l1, len - (l1+l2))) <= 0) {
if (ret < 0 && errno == EINTR)
continue;
return ret;
}
if (ret != (int)(len - (l1+l2)))
return l1+ret;
return len;
}
@@ -107,7 +114,7 @@ int write_file(int f,char *buf,size_t len)
while (len > 0) {
int r1;
if (sparse_files) {
if (sparse_files > 0) {
int len1 = MIN(len, SPARSE_WRITE_SIZE);
r1 = write_sparse(f, buf, len1);
} else {
@@ -152,13 +159,12 @@ struct map_struct *map_file(int fd, OFF_T len, int32 read_size,
{
struct map_struct *map;
if (!(map = new(struct map_struct)))
if (!(map = new0(struct map_struct)))
out_of_memory("map_file");
if (blk_size && (read_size % blk_size))
read_size += blk_size - (read_size % blk_size);
memset(map, 0, sizeof map[0]);
map->fd = fd;
map->file_size = len;
map->def_window_size = read_size;
@@ -190,7 +196,7 @@ char *map_ptr(struct map_struct *map, OFF_T offset, int32 len)
window_start = offset;
window_size = map->def_window_size;
if (window_start + window_size > map->file_size)
window_size = map->file_size - window_start;
window_size = (int32)(map->file_size - window_start);
if (len > window_size)
window_size = len;
@@ -208,7 +214,7 @@ char *map_ptr(struct map_struct *map, OFF_T offset, int32 len)
window_start < map->p_offset + map->p_len &&
window_start + window_size >= map->p_offset + map->p_len) {
read_start = map->p_offset + map->p_len;
read_offset = read_start - window_start;
read_offset = (int32)(read_start - window_start);
read_size = window_size - read_offset;
memmove(map->p, map->p + (map->p_len - read_offset), read_offset);
} else {

2244
flist.c
View File

File diff suppressed because it is too large Load Diff

View File

File diff suppressed because it is too large Load Diff

View File

@@ -3,12 +3,11 @@
* `id -G` on Linux, but it's too hard to find a portable equivalent.
*
* Copyright (C) 2002 Martin Pool
* Copyright (C) 2003, 2004 Wayne Davison
* Copyright (C) 2003-2007 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* it under the terms of the GNU General Public License version 3 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
@@ -16,8 +15,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
* with this program; if not, visit the http://fsf.org website.
*/
#include "rsync.h"

145
hashtable.c Normal file
View File

@@ -0,0 +1,145 @@
/*
* Routines to provide a memory-efficient hashtable.
*
* Copyright (C) 2007 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 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, visit the http://fsf.org website.
*/
#include "rsync.h"
#define HASH_LOAD_LIMIT(size) ((size)*3/4)
struct hashtable *hashtable_create(int size, int key64)
{
struct hashtable *tbl;
int node_size = key64 ? sizeof (struct ht_int64_node )
: sizeof (struct ht_int32_node);
/* Pick a power of 2 that can hold the requested size. */
if (size & (size-1) || size < 16) {
int req = size;
size = 16;
while (size < req)
size *= 2;
}
if (!(tbl = new(struct hashtable))
|| !(tbl->nodes = new_array0(char, size * node_size)))
out_of_memory("hashtable_create");
tbl->size = size;
tbl->entries = 0;
tbl->node_size = node_size;
return tbl;
}
void hashtable_destroy(struct hashtable *tbl)
{
free(tbl->nodes);
free(tbl);
}
/* This returns the node for the indicated key, either newly created or
* already existing. Returns NULL if not allocating and not found. */
void *hashtable_find(struct hashtable *tbl, int64 key, int allocate_if_missing)
{
int key64 = (tbl->node_size > sizeof (struct ht_int32_node));
struct ht_int32_node *node;
uint32 ndx;
if (allocate_if_missing && tbl->entries > HASH_LOAD_LIMIT(tbl->size)) {
void *old_nodes = tbl->nodes;
int size = tbl->size * 2;
int i;
if (!(tbl->nodes = new_array0(char, size * tbl->node_size)))
out_of_memory("hashtable_node");
tbl->size = size;
tbl->entries = 0;
for (i = size / 2; i-- > 0; ) {
struct ht_int32_node *move_node = HT_NODE(tbl, old_nodes, i);
int64 move_key = HT_KEY(move_node, key64);
if (move_key == 0)
continue;
node = hashtable_find(tbl, move_key, 1);
node->data = move_node->data;
}
free(old_nodes);
}
if (!key64) {
/* Based on Jenkins One-at-a-time hash. */
uchar buf[4], *keyp = buf;
int i;
SIVAL(buf, 0, key);
for (ndx = 0, i = 0; i < 4; i++) {
ndx += keyp[i];
ndx += (ndx << 10);
ndx ^= (ndx >> 6);
}
ndx += (ndx << 3);
ndx ^= (ndx >> 11);
ndx += (ndx << 15);
} else {
/* Based on Jenkins hashword() from lookup3.c. */
uint32 a, b, c;
/* Set up the internal state */
a = b = c = 0xdeadbeef + (8 << 2);
#define rot(x,k) (((x)<<(k)) ^ ((x)>>(32-(k))))
b += (uint32)(key >> 32);
a += (uint32)key;
c ^= b; c -= rot(b, 14);
a ^= c; a -= rot(c, 11);
b ^= a; b -= rot(a, 25);
c ^= b; c -= rot(b, 16);
a ^= c; a -= rot(c, 4);
b ^= a; b -= rot(a, 14);
c ^= b; c -= rot(b, 24);
#undef rot
ndx = c;
}
/* If it already exists, return the node. If we're not
* allocating, return NULL if the key is not found. */
while (1) {
int64 nkey;
ndx &= tbl->size - 1;
node = HT_NODE(tbl, tbl->nodes, ndx);
nkey = HT_KEY(node, key64);
if (nkey == key)
return node;
if (nkey == 0) {
if (!allocate_if_missing)
return NULL;
break;
}
ndx++;
}
/* Take over this empty spot and then return the node. */
if (key64)
((struct ht_int64_node*)node)->key = key;
else
node->key = key;
tbl->entries++;
return node;
}

636
hlink.c
View File

@@ -4,11 +4,11 @@
* Copyright (C) 1996 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2002 Martin Pool <mbp@samba.org>
* Copyright (C) 2004, 2005, 2006 Wayne Davison
* Copyright (C) 2004-2007 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
@@ -17,151 +17,209 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
* with this program; if not, visit the http://fsf.org website.
*/
#include "rsync.h"
extern int verbose;
extern int dry_run;
extern int am_sender;
extern int inc_recurse;
extern int do_xfers;
extern int link_dest;
extern int preserve_acls;
extern int make_backups;
extern int protocol_version;
extern int remove_source_files;
extern int stdout_format_has_i;
extern int maybe_ATTRS_REPORT;
extern char *basis_dir[];
extern struct file_list *the_file_list;
extern struct file_list *cur_flist;
#ifdef ICONV_OPTION
extern int ic_ndx;
#endif
#ifdef SUPPORT_HARD_LINKS
#define SKIPPED_LINK (-1)
#define FINISHED_LINK (-2)
/* Starting with protocol 30, we use a simple hashtable on the sending side
* for hashing the st_dev and st_ino info. The receiving side gets told
* (via flags and a "group index") which items are hard-linked together, so
* we can avoid the pool of dev+inode data. For incremental recursion mode,
* the receiver will use a ndx hash to remember old pathnames. */
#define FPTR(i) (the_file_list->files[i])
#define LINKED(p1,p2) (FPTR(p1)->F_DEV == FPTR(p2)->F_DEV \
&& FPTR(p1)->F_INODE == FPTR(p2)->F_INODE)
static struct hashtable *dev_tbl;
static int hlink_compare(int *int1, int *int2)
{
struct file_struct *f1 = FPTR(*int1);
struct file_struct *f2 = FPTR(*int2);
static struct hashtable *prior_hlinks;
if (f1->F_DEV != f2->F_DEV)
return (int) (f1->F_DEV > f2->F_DEV ? 1 : -1);
if (f1->F_INODE != f2->F_INODE)
return (int) (f1->F_INODE > f2->F_INODE ? 1 : -1);
return f_name_cmp(f1, f2);
}
static int32 *hlink_list;
static int32 hlink_count;
/* 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(void)
{
int32 cur, from, to, start;
alloc_pool_t hlink_pool;
alloc_pool_t idev_pool = the_file_list->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;
while (1) {
cur = hlink_list[from];
if (from == hlink_count-1
|| !LINKED(cur, hlink_list[from+1]))
break;
pool_free(idev_pool, 0, FPTR(cur)->link_u.idev);
FPTR(cur)->link_u.links = pool_talloc(hlink_pool,
struct hlink, 1, "hlink_list");
FPTR(cur)->F_HLINDEX = to;
FPTR(cur)->F_NEXT = hlink_list[++from];
FPTR(cur)->link_u.links->link_dest_used = 0;
}
pool_free(idev_pool, 0, FPTR(cur)->link_u.idev);
if (from > start) {
int head = hlink_list[start];
FPTR(cur)->link_u.links = pool_talloc(hlink_pool,
struct hlink, 1, "hlink_list");
FPTR(head)->flags |= FLAG_HLINK_TOL;
FPTR(cur)->F_HLINDEX = to;
FPTR(cur)->F_NEXT = head;
FPTR(cur)->flags |= FLAG_HLINK_EOL;
FPTR(cur)->link_u.links->link_dest_used = 0;
hlink_list[to++] = head;
} else
FPTR(cur)->link_u.links = NULL;
}
if (!to) {
free(hlink_list);
hlink_list = NULL;
pool_destroy(hlink_pool);
hlink_pool = NULL;
} else {
hlink_count = to;
hlink_list = realloc_array(hlink_list, int32, hlink_count);
if (!hlink_list)
out_of_memory("init_hard_links");
}
the_file_list->hlink_pool = hlink_pool;
pool_destroy(idev_pool);
}
#endif
static struct file_list *hlink_flist;
void init_hard_links(void)
{
#ifdef SUPPORT_HARD_LINKS
int i;
if (hlink_list)
free(hlink_list);
if (!(hlink_list = new_array(int32, the_file_list->count)))
out_of_memory("init_hard_links");
hlink_count = 0;
for (i = 0; i < the_file_list->count; i++) {
if (FPTR(i)->link_u.idev)
hlink_list[hlink_count++] = i;
}
qsort(hlink_list, hlink_count,
sizeof hlink_list[0], (int (*)()) hlink_compare);
if (!hlink_count) {
free(hlink_list);
hlink_list = NULL;
} else
link_idev_data();
#endif
if (am_sender || protocol_version < 30)
dev_tbl = hashtable_create(16, SIZEOF_INT64 == 8);
else if (inc_recurse)
prior_hlinks = hashtable_create(1024, 0);
}
struct ht_int64_node *idev_find(int64 dev, int64 ino)
{
static struct ht_int64_node *dev_node = NULL;
struct hashtable *tbl;
if (!dev_node || dev_node->key != dev) {
/* We keep a separate hash table of inodes for every device. */
dev_node = hashtable_find(dev_tbl, dev, 1);
if (!(tbl = dev_node->data))
tbl = dev_node->data = hashtable_create(512, SIZEOF_INT64 == 8);
} else
tbl = dev_node->data;
return hashtable_find(tbl, ino, 1);
}
void idev_destroy(void)
{
int i;
for (i = 0; i < dev_tbl->size; i++) {
struct ht_int32_node *node = HT_NODE(dev_tbl, dev_tbl->nodes, i);
if (node->data)
hashtable_destroy(node->data);
}
hashtable_destroy(dev_tbl);
}
static int hlink_compare_gnum(int *int1, int *int2)
{
struct file_struct *f1 = hlink_flist->sorted[*int1];
struct file_struct *f2 = hlink_flist->sorted[*int2];
int32 gnum1 = F_HL_GNUM(f1);
int32 gnum2 = F_HL_GNUM(f2);
if (gnum1 != gnum2)
return gnum1 > gnum2 ? 1 : -1;
return *int1 > *int2 ? 1 : -1;
}
static void match_gnums(int32 *ndx_list, int ndx_count)
{
int32 from, prev;
struct file_struct *file, *file_next;
struct ht_int32_node *node = NULL;
int32 gnum, gnum_next;
qsort(ndx_list, ndx_count, sizeof ndx_list[0],
(int (*)()) hlink_compare_gnum);
for (from = 0; from < ndx_count; from++) {
file = hlink_flist->sorted[ndx_list[from]];
gnum = F_HL_GNUM(file);
if (inc_recurse) {
node = hashtable_find(prior_hlinks, gnum, 1);
if (!node->data) {
node->data = new_array0(char, 5);
assert(gnum >= hlink_flist->ndx_start);
file->flags |= FLAG_HLINK_FIRST;
prev = -1;
} else if (CVAL(node->data, 0) == 0) {
struct file_list *flist;
struct file_struct *fp;
prev = IVAL(node->data, 1);
flist = flist_for_ndx(prev);
assert(flist != NULL);
fp = flist->files[prev - flist->ndx_start];
fp->flags &= ~FLAG_HLINK_LAST;
} else
prev = -1;
} else {
file->flags |= FLAG_HLINK_FIRST;
prev = -1;
}
for ( ; from < ndx_count-1; file = file_next, gnum = gnum_next, from++) { /*SHARED ITERATOR*/
file_next = hlink_flist->sorted[ndx_list[from+1]];
gnum_next = F_HL_GNUM(file_next);
if (gnum != gnum_next)
break;
F_HL_PREV(file) = prev;
/* The linked list must use raw ndx values. */
#ifdef ICONV_OPTION
if (ic_ndx)
prev = F_NDX(file);
else
#endif
prev = ndx_list[from] + hlink_flist->ndx_start;
}
if (prev < 0 && !inc_recurse) {
/* Disable hard-link bit and set DONE so that
* HLINK_BUMP()-dependent values are unaffected. */
file->flags &= ~(FLAG_HLINKED | FLAG_HLINK_FIRST);
file->flags |= FLAG_HLINK_DONE;
continue;
}
file->flags |= FLAG_HLINK_LAST;
F_HL_PREV(file) = prev;
if (inc_recurse && CVAL(node->data, 0) == 0) {
#ifdef ICONV_OPTION
if (ic_ndx)
prev = F_NDX(file);
else
#endif
prev = ndx_list[from] + hlink_flist->ndx_start;
SIVAL(node->data, 1, prev);
}
}
}
/* Analyze the hard-links in the file-list by creating a list of all the
* items that have hlink data, sorting them, and matching up identical
* values into clusters. These will be a single linked list from last
* to first when we're done. */
void match_hard_links(struct file_list *flist)
{
int i, ndx_count = 0;
int32 *ndx_list;
if (!(ndx_list = new_array(int32, flist->used)))
out_of_memory("match_hard_links");
for (i = 0; i < flist->used; i++) {
if (F_IS_HLINKED(flist->sorted[i]))
ndx_list[ndx_count++] = i;
}
hlink_flist = flist;
if (ndx_count)
match_gnums(ndx_list, ndx_count);
free(ndx_list);
if (protocol_version < 30)
idev_destroy();
}
#ifdef SUPPORT_HARD_LINKS
static int maybe_hard_link(struct file_struct *file, int ndx,
char *fname, int statret, STRUCT_STAT *st,
char *toname, STRUCT_STAT *to_st,
int itemizing, enum logcode code)
const char *fname, int statret, stat_x *sxp,
const char *oldname, STRUCT_STAT *old_stp,
const char *realname, int itemizing, enum logcode code)
{
if (statret == 0) {
if (st->st_dev == to_st->st_dev
&& st->st_ino == to_st->st_ino) {
if (sxp->st.st_dev == old_stp->st_dev
&& sxp->st.st_ino == old_stp->st_ino) {
if (itemizing) {
itemize(file, ndx, statret, st,
itemize(fname, file, ndx, statret, sxp,
ITEM_LOCAL_CHANGE | ITEM_XNAME_FOLLOWS,
0, "");
}
if (verbose > 1 && maybe_ATTRS_REPORT)
rprintf(FCLIENT, "%s is uptodate\n", fname);
file->flags |= FLAG_HLINK_DONE;
return 0;
}
if (make_backups) {
if (make_backups > 0) {
if (!make_backup(fname))
return -1;
} else if (robust_unlink(fname)) {
@@ -170,90 +228,171 @@ static int maybe_hard_link(struct file_struct *file, int ndx,
return -1;
}
}
return hard_link_one(file, ndx, fname, statret, st, toname,
0, itemizing, code);
}
#endif
int hard_link_check(struct file_struct *file, int ndx, char *fname,
int statret, STRUCT_STAT *st, int itemizing,
enum logcode code, int skip)
{
#ifdef SUPPORT_HARD_LINKS
int head;
if (skip && !(file->flags & FLAG_HLINK_EOL))
head = hlink_list[file->F_HLINDEX] = file->F_NEXT;
else
head = hlink_list[file->F_HLINDEX];
if (ndx != head) {
struct file_struct *head_file = FPTR(head);
if (!stdout_format_has_i && verbose > 1) {
rprintf(FINFO, "\"%s\" is a hard link\n",
f_name(file, NULL));
if (hard_link_one(file, fname, oldname, 0)) {
if (itemizing) {
itemize(fname, file, ndx, statret, sxp,
ITEM_LOCAL_CHANGE | ITEM_XNAME_FOLLOWS, 0,
realname);
}
if (head_file->F_HLINDEX == FINISHED_LINK) {
STRUCT_STAT st2, st3;
char toname[MAXPATHLEN];
int ldu = head_file->link_u.links->link_dest_used;
if (ldu) {
pathjoin(toname, MAXPATHLEN, basis_dir[ldu-1],
f_name(head_file, NULL));
} else
f_name(head_file, toname);
if (link_stat(toname, &st2, 0) < 0) {
rsyserr(FERROR, errno, "stat %s failed",
full_fname(toname));
return -1;
}
if (statret < 0 && basis_dir[0] != NULL) {
char cmpbuf[MAXPATHLEN];
int j = 0;
do {
pathjoin(cmpbuf, MAXPATHLEN, basis_dir[j], fname);
if (link_stat(cmpbuf, &st3, 0) < 0)
continue;
if (link_dest) {
if (st2.st_dev != st3.st_dev
|| st2.st_ino != st3.st_ino)
continue;
statret = 1;
st = &st3;
if (verbose < 2 || !stdout_format_has_i) {
itemizing = 0;
code = FNONE;
}
break;
}
if (!unchanged_file(cmpbuf, file, &st3))
continue;
statret = 1;
st = &st3;
if (unchanged_attrs(file, &st3))
break;
} while (basis_dir[++j] != NULL);
}
maybe_hard_link(file, ndx, fname, statret, st,
toname, &st2, itemizing, code);
if (remove_source_files == 1 && do_xfers) {
char numbuf[4];
SIVAL(numbuf, 0, ndx);
send_msg(MSG_SUCCESS, numbuf, 4);
}
file->F_HLINDEX = FINISHED_LINK;
} else
file->F_HLINDEX = SKIPPED_LINK;
return 1;
if (code != FNONE && verbose)
rprintf(code, "%s => %s\n", fname, realname);
return 0;
}
#endif
return 0;
return -1;
}
#ifdef SUPPORT_HARD_LINKS
int hard_link_one(struct file_struct *file, int ndx, char *fname,
int statret, STRUCT_STAT *st, char *toname, int terse,
int itemizing, enum logcode code)
/* Figure out if a prior entry is still there or if we just have a
* cached name for it. Never called with a FLAG_HLINK_FIRST entry. */
static char *check_prior(int prev_ndx, int gnum, struct file_list **flist_p)
{
if (do_link(toname, fname)) {
struct file_list *flist = flist_for_ndx(prev_ndx);
struct ht_int32_node *node;
if (flist) {
*flist_p = flist;
return NULL;
}
node = hashtable_find(prior_hlinks, gnum, 0);
assert(node != NULL && node->data);
assert(CVAL(node->data, 0) != 0);
return node->data;
}
/* Only called if FLAG_HLINKED is set and FLAG_HLINK_FIRST is not. Returns:
* 0 = process the file, 1 = skip the file, -1 = error occurred. */
int hard_link_check(struct file_struct *file, int ndx, const char *fname,
int statret, stat_x *sxp, int itemizing,
enum logcode code)
{
STRUCT_STAT prev_st;
char namebuf[MAXPATHLEN], altbuf[MAXPATHLEN];
char *realname, *prev_name;
struct file_list *flist;
int gnum = inc_recurse ? F_HL_GNUM(file) : -1;
int prev_ndx = F_HL_PREV(file);
prev_name = realname = check_prior(prev_ndx, gnum, &flist);
if (!prev_name) {
struct file_struct *prev_file = flist->files[prev_ndx - flist->ndx_start];
/* Is the previous link is not complete yet? */
if (!(prev_file->flags & FLAG_HLINK_DONE)) {
/* Is the previous link being transferred? */
if (prev_file->flags & FLAG_FILE_SENT) {
/* Add ourselves to the list of files that will be
* updated when the transfer completes, and mark
* ourself as waiting for the transfer. */
F_HL_PREV(file) = F_HL_PREV(prev_file);
F_HL_PREV(prev_file) = ndx;
file->flags |= FLAG_FILE_SENT;
cur_flist->in_progress++;
return 1;
}
return 0;
}
/* There is a finished file to link with! */
if (!(prev_file->flags & FLAG_HLINK_FIRST)) {
/* The previous previous is FIRST when prev is not. */
prev_ndx = F_HL_PREV(prev_file);
prev_name = realname = check_prior(prev_ndx, gnum, &flist);
/* Update our previous pointer to point to the FIRST. */
F_HL_PREV(file) = prev_ndx;
}
if (!prev_name) {
int alt_dest;
prev_file = flist->files[prev_ndx - flist->ndx_start];
/* F_HL_PREV() is alt_dest value when DONE && FIRST. */
alt_dest = F_HL_PREV(prev_file);
if (alt_dest >= 0 && dry_run) {
pathjoin(namebuf, MAXPATHLEN, basis_dir[alt_dest],
f_name(prev_file, NULL));
prev_name = namebuf;
realname = f_name(prev_file, altbuf);
} else {
prev_name = f_name(prev_file, namebuf);
realname = prev_name;
}
}
}
if (link_stat(prev_name, &prev_st, 0) < 0) {
rsyserr(FERROR, errno, "stat %s failed",
full_fname(prev_name));
return -1;
}
if (statret < 0 && basis_dir[0] != NULL) {
/* If we match an alt-dest item, we don't output this as a change. */
char cmpbuf[MAXPATHLEN];
stat_x alt_sx;
int j = 0;
#ifdef SUPPORT_ACLS
alt_sx.acc_acl = alt_sx.def_acl = NULL;
#endif
do {
pathjoin(cmpbuf, MAXPATHLEN, basis_dir[j], fname);
if (link_stat(cmpbuf, &alt_sx.st, 0) < 0)
continue;
if (link_dest) {
if (prev_st.st_dev != alt_sx.st.st_dev
|| prev_st.st_ino != alt_sx.st.st_ino)
continue;
statret = 1;
if (verbose < 2 || !stdout_format_has_i) {
itemizing = 0;
code = FNONE;
if (verbose > 1 && maybe_ATTRS_REPORT)
rprintf(FCLIENT, "%s is uptodate\n", fname);
}
break;
}
if (!unchanged_file(cmpbuf, file, &alt_sx.st))
continue;
statret = 1;
if (unchanged_attrs(cmpbuf, file, &alt_sx))
break;
} while (basis_dir[++j] != NULL);
if (statret == 1) {
sxp->st = alt_sx.st;
#ifdef SUPPORT_ACLS
if (preserve_acls && !S_ISLNK(file->mode)) {
if (!ACL_READY(*sxp))
get_acl(cmpbuf, sxp);
else {
sxp->acc_acl = alt_sx.acc_acl;
sxp->def_acl = alt_sx.def_acl;
}
}
#endif
}
#ifdef SUPPORT_ACLS
else if (preserve_acls)
free_acl(&alt_sx);
#endif
}
if (maybe_hard_link(file, ndx, fname, statret, sxp, prev_name, &prev_st,
realname, itemizing, code) < 0)
return -1;
if (remove_source_files == 1 && do_xfers)
send_msg_int(MSG_SUCCESS, ndx);
return 1;
}
int hard_link_one(struct file_struct *file, const char *fname,
const char *oldname, int terse)
{
if (do_link(oldname, fname) < 0) {
enum logcode code;
if (terse) {
if (!verbose)
return -1;
@@ -261,55 +400,80 @@ int hard_link_one(struct file_struct *file, int ndx, char *fname,
} else
code = FERROR;
rsyserr(code, errno, "link %s => %s failed",
full_fname(fname), toname);
return -1;
full_fname(fname), oldname);
return 0;
}
if (itemizing) {
itemize(file, ndx, statret, st,
ITEM_LOCAL_CHANGE | ITEM_XNAME_FOLLOWS, 0,
terse ? "" : toname);
}
if (code != FNONE && verbose && !terse)
rprintf(code, "%s => %s\n", fname, toname);
return 0;
file->flags |= FLAG_HLINK_DONE;
return 1;
}
#endif
void hard_link_cluster(struct file_struct *file, int master, int itemizing,
enum logcode code)
void finish_hard_link(struct file_struct *file, const char *fname, int fin_ndx,
STRUCT_STAT *stp, int itemizing, enum logcode code,
int alt_dest)
{
#ifdef SUPPORT_HARD_LINKS
char hlink1[MAXPATHLEN];
char *hlink2;
STRUCT_STAT st1, st2;
int statret, ndx = master;
stat_x prev_sx;
STRUCT_STAT st;
char alt_name[MAXPATHLEN], *prev_name;
const char *our_name;
struct file_list *flist;
int prev_statret, ndx, prev_ndx = F_HL_PREV(file);
file->F_HLINDEX = FINISHED_LINK;
if (link_stat(f_name(file, hlink1), &st1, 0) < 0)
return;
if (!(file->flags & FLAG_HLINK_TOL)) {
while (!(file->flags & FLAG_HLINK_EOL)) {
ndx = file->F_NEXT;
file = FPTR(ndx);
if (stp == NULL && prev_ndx >= 0) {
if (link_stat(fname, &st, 0) < 0) {
rsyserr(FERROR, errno, "stat %s failed",
full_fname(fname));
return;
}
stp = &st;
}
do {
ndx = file->F_NEXT;
file = FPTR(ndx);
if (file->F_HLINDEX != SKIPPED_LINK)
continue;
hlink2 = f_name(file, NULL);
statret = link_stat(hlink2, &st2, 0);
maybe_hard_link(file, ndx, hlink2, statret, &st2,
hlink1, &st1, itemizing, code);
if (remove_source_files == 1 && do_xfers) {
char numbuf[4];
SIVAL(numbuf, 0, ndx);
send_msg(MSG_SUCCESS, numbuf, 4);
}
file->F_HLINDEX = FINISHED_LINK;
} while (!(file->flags & FLAG_HLINK_EOL));
/* FIRST combined with DONE means we were the first to get done. */
file->flags |= FLAG_HLINK_FIRST | FLAG_HLINK_DONE;
F_HL_PREV(file) = alt_dest;
if (alt_dest >= 0 && dry_run) {
pathjoin(alt_name, MAXPATHLEN, basis_dir[alt_dest],
f_name(file, NULL));
our_name = alt_name;
} else
our_name = fname;
#ifdef SUPPORT_ACLS
prev_sx.acc_acl = prev_sx.def_acl = NULL;
#endif
while ((ndx = prev_ndx) >= 0) {
int val;
flist = flist_for_ndx(ndx);
assert(flist != NULL);
file = flist->files[ndx - flist->ndx_start];
file->flags = (file->flags & ~FLAG_HLINK_FIRST) | FLAG_HLINK_DONE;
prev_ndx = F_HL_PREV(file);
F_HL_PREV(file) = fin_ndx;
prev_name = f_name(file, NULL);
prev_statret = link_stat(prev_name, &prev_sx.st, 0);
val = maybe_hard_link(file, ndx, prev_name, prev_statret, &prev_sx,
our_name, stp, fname, itemizing, code);
flist->in_progress--;
#ifdef SUPPORT_ACLS
if (preserve_acls)
free_acl(&prev_sx);
#endif
if (val < 0)
continue;
if (remove_source_files == 1 && do_xfers)
send_msg_int(MSG_SUCCESS, ndx);
}
if (inc_recurse) {
int gnum = F_HL_GNUM(file);
struct ht_int32_node *node = hashtable_find(prior_hlinks, gnum, 0);
assert(node != NULL && node->data != NULL);
assert(CVAL(node->data, 0) == 0);
free(node->data);
if (!(node->data = strdup(our_name)))
out_of_memory("finish_hard_link");
}
}
#endif

100
ifuncs.h Normal file
View File

@@ -0,0 +1,100 @@
/* Inline functions for rsync.
*
* Copyright (C) 2007 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 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, visit the http://fsf.org website.
*/
static inline void
alloc_xbuf(xbuf *xb, size_t sz)
{
if (!(xb->buf = new_array(char, sz)))
out_of_memory("alloc_xbuf");
xb->size = sz;
xb->len = xb->pos = 0;
}
static inline void
realloc_xbuf(xbuf *xb, size_t sz)
{
char *bf = realloc_array(xb->buf, char, sz);
if (!bf)
out_of_memory("realloc_xbuf");
xb->buf = bf;
xb->size = sz;
}
static inline int
to_wire_mode(mode_t mode)
{
#ifdef SUPPORT_LINKS
#if _S_IFLNK != 0120000
if (S_ISLNK(mode))
return (mode & ~(_S_IFMT)) | 0120000;
#endif
#endif
return mode;
}
static inline mode_t
from_wire_mode(int mode)
{
#if _S_IFLNK != 0120000
if ((mode & (_S_IFMT)) == 0120000)
return (mode & ~(_S_IFMT)) | _S_IFLNK;
#endif
return mode;
}
static inline int
isDigit(const char *ptr)
{
return isdigit(*(unsigned char *)ptr);
}
static inline int
isPrint(const char *ptr)
{
return isprint(*(unsigned char *)ptr);
}
static inline int
isSpace(const char *ptr)
{
return isspace(*(unsigned char *)ptr);
}
static inline int
isLower(const char *ptr)
{
return islower(*(unsigned char *)ptr);
}
static inline int
isUpper(const char *ptr)
{
return isupper(*(unsigned char *)ptr);
}
static inline int
toLower(const char *ptr)
{
return tolower(*(unsigned char *)ptr);
}
static inline int
toUpper(const char *ptr)
{
return toupper(*(unsigned char *)ptr);
}

1122
io.c
View File

File diff suppressed because it is too large Load Diff

52
io.h Normal file
View File

@@ -0,0 +1,52 @@
/*
* Copyright (C) 2007 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 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, visit the http://fsf.org website.
*/
extern int protocol_version;
static inline int32
read_varint30(int f)
{
if (protocol_version < 30)
return read_int(f);
return read_varint(f);
}
static inline int64
read_varlong30(int f, uchar min_bytes)
{
if (protocol_version < 30)
return read_longint(f);
return read_varlong(f, min_bytes);
}
static inline void
write_varint30(int f, int32 x)
{
if (protocol_version < 30)
write_int(f, x);
else
write_varint(f, x);
}
static inline void
write_varlong30(int f, int64 x, uchar min_bytes)
{
if (protocol_version < 30)
write_longint(f, x);
else
write_varlong(f, x, min_bytes);
}

View File

@@ -7,7 +7,7 @@
*
* 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
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
@@ -16,8 +16,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
* with this program; if not, visit the http://fsf.org website.
*/
#include "rsync.h"

304
lib/md5.c Normal file
View File

@@ -0,0 +1,304 @@
/*
* RFC 1321 compliant MD5 implementation
*
* Copyright (C) 2001-2003 Christophe Devine
*
* 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 3 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, visit the http://fsf.org website.
*/
#include "rsync.h"
void md5_begin(md_context *ctx)
{
ctx->A = 0x67452301;
ctx->B = 0xEFCDAB89;
ctx->C = 0x98BADCFE;
ctx->D = 0x10325476;
ctx->totalN = ctx->totalN2 = 0;
}
static void md5_process(md_context *ctx, const uchar data[CSUM_CHUNK])
{
uint32 X[16], A, B, C, D;
A = ctx->A;
B = ctx->B;
C = ctx->C;
D = ctx->D;
X[0] = IVAL(data, 0);
X[1] = IVAL(data, 4);
X[2] = IVAL(data, 8);
X[3] = IVAL(data, 12);
X[4] = IVAL(data, 16);
X[5] = IVAL(data, 20);
X[6] = IVAL(data, 24);
X[7] = IVAL(data, 28);
X[8] = IVAL(data, 32);
X[9] = IVAL(data, 36);
X[10] = IVAL(data, 40);
X[11] = IVAL(data, 44);
X[12] = IVAL(data, 48);
X[13] = IVAL(data, 52);
X[14] = IVAL(data, 56);
X[15] = IVAL(data, 60);
#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
#define P(a,b,c,d,k,s,t) a += F(b,c,d) + X[k] + t, a = S(a,s) + b
#define F(x,y,z) (z ^ (x & (y ^ z)))
P(A, B, C, D, 0, 7, 0xD76AA478);
P(D, A, B, C, 1, 12, 0xE8C7B756);
P(C, D, A, B, 2, 17, 0x242070DB);
P(B, C, D, A, 3, 22, 0xC1BDCEEE);
P(A, B, C, D, 4, 7, 0xF57C0FAF);
P(D, A, B, C, 5, 12, 0x4787C62A);
P(C, D, A, B, 6, 17, 0xA8304613);
P(B, C, D, A, 7, 22, 0xFD469501);
P(A, B, C, D, 8, 7, 0x698098D8);
P(D, A, B, C, 9, 12, 0x8B44F7AF);
P(C, D, A, B, 10, 17, 0xFFFF5BB1);
P(B, C, D, A, 11, 22, 0x895CD7BE);
P(A, B, C, D, 12, 7, 0x6B901122);
P(D, A, B, C, 13, 12, 0xFD987193);
P(C, D, A, B, 14, 17, 0xA679438E);
P(B, C, D, A, 15, 22, 0x49B40821);
#undef F
#define F(x,y,z) (y ^ (z & (x ^ y)))
P(A, B, C, D, 1, 5, 0xF61E2562);
P(D, A, B, C, 6, 9, 0xC040B340);
P(C, D, A, B, 11, 14, 0x265E5A51);
P(B, C, D, A, 0, 20, 0xE9B6C7AA);
P(A, B, C, D, 5, 5, 0xD62F105D);
P(D, A, B, C, 10, 9, 0x02441453);
P(C, D, A, B, 15, 14, 0xD8A1E681);
P(B, C, D, A, 4, 20, 0xE7D3FBC8);
P(A, B, C, D, 9, 5, 0x21E1CDE6);
P(D, A, B, C, 14, 9, 0xC33707D6);
P(C, D, A, B, 3, 14, 0xF4D50D87);
P(B, C, D, A, 8, 20, 0x455A14ED);
P(A, B, C, D, 13, 5, 0xA9E3E905);
P(D, A, B, C, 2, 9, 0xFCEFA3F8);
P(C, D, A, B, 7, 14, 0x676F02D9);
P(B, C, D, A, 12, 20, 0x8D2A4C8A);
#undef F
#define F(x,y,z) (x ^ y ^ z)
P(A, B, C, D, 5, 4, 0xFFFA3942);
P(D, A, B, C, 8, 11, 0x8771F681);
P(C, D, A, B, 11, 16, 0x6D9D6122);
P(B, C, D, A, 14, 23, 0xFDE5380C);
P(A, B, C, D, 1, 4, 0xA4BEEA44);
P(D, A, B, C, 4, 11, 0x4BDECFA9);
P(C, D, A, B, 7, 16, 0xF6BB4B60);
P(B, C, D, A, 10, 23, 0xBEBFBC70);
P(A, B, C, D, 13, 4, 0x289B7EC6);
P(D, A, B, C, 0, 11, 0xEAA127FA);
P(C, D, A, B, 3, 16, 0xD4EF3085);
P(B, C, D, A, 6, 23, 0x04881D05);
P(A, B, C, D, 9, 4, 0xD9D4D039);
P(D, A, B, C, 12, 11, 0xE6DB99E5);
P(C, D, A, B, 15, 16, 0x1FA27CF8);
P(B, C, D, A, 2, 23, 0xC4AC5665);
#undef F
#define F(x,y,z) (y ^ (x | ~z))
P(A, B, C, D, 0, 6, 0xF4292244);
P(D, A, B, C, 7, 10, 0x432AFF97);
P(C, D, A, B, 14, 15, 0xAB9423A7);
P(B, C, D, A, 5, 21, 0xFC93A039);
P(A, B, C, D, 12, 6, 0x655B59C3);
P(D, A, B, C, 3, 10, 0x8F0CCC92);
P(C, D, A, B, 10, 15, 0xFFEFF47D);
P(B, C, D, A, 1, 21, 0x85845DD1);
P(A, B, C, D, 8, 6, 0x6FA87E4F);
P(D, A, B, C, 15, 10, 0xFE2CE6E0);
P(C, D, A, B, 6, 15, 0xA3014314);
P(B, C, D, A, 13, 21, 0x4E0811A1);
P(A, B, C, D, 4, 6, 0xF7537E82);
P(D, A, B, C, 11, 10, 0xBD3AF235);
P(C, D, A, B, 2, 15, 0x2AD7D2BB);
P(B, C, D, A, 9, 21, 0xEB86D391);
#undef F
ctx->A += A;
ctx->B += B;
ctx->C += C;
ctx->D += D;
}
void md5_update(md_context *ctx, const uchar *input, uint32 length)
{
uint32 left, fill;
if (!length)
return;
left = ctx->totalN & 0x3F;
fill = CSUM_CHUNK - left;
ctx->totalN += length;
ctx->totalN &= 0xFFFFFFFF;
if (ctx->totalN < length)
ctx->totalN2++;
if (left && length >= fill) {
memcpy(ctx->buffer + left, input, fill);
md5_process(ctx, ctx->buffer);
length -= fill;
input += fill;
left = 0;
}
while (length >= CSUM_CHUNK) {
md5_process(ctx, input);
length -= CSUM_CHUNK;
input += CSUM_CHUNK;
}
if (length)
memcpy(ctx->buffer + left, input, length);
}
static uchar md5_padding[CSUM_CHUNK] = { 0x80 };
void md5_result(md_context *ctx, uchar digest[MD5_DIGEST_LEN])
{
uint32 last, padn;
uint32 high, low;
uchar msglen[8];
high = (ctx->totalN >> 29)
| (ctx->totalN2 << 3);
low = (ctx->totalN << 3);
SIVAL(msglen, 0, low);
SIVAL(msglen, 4, high);
last = ctx->totalN & 0x3F;
padn = last < 56 ? 56 - last : 120 - last;
md5_update(ctx, md5_padding, padn);
md5_update(ctx, msglen, 8);
SIVAL(digest, 0, ctx->A);
SIVAL(digest, 4, ctx->B);
SIVAL(digest, 8, ctx->C);
SIVAL(digest, 12, ctx->D);
}
void get_md5(uchar *out, const uchar *input, int n)
{
md_context ctx;
md5_begin(&ctx);
md5_update(&ctx, input, n);
md5_result(&ctx, out);
}
#ifdef TEST_MD5
#include <stdlib.h>
#include <stdio.h>
/*
* those are the standard RFC 1321 test vectors
*/
static struct {
char *str, *md5;
} tests[] = {
{ "",
"d41d8cd98f00b204e9800998ecf8427e" },
{ "a",
"0cc175b9c0f1b6a831c399e269772661" },
{ "abc",
"900150983cd24fb0d6963f7d28e17f72" },
{ "message digest",
"f96b697d7cb7938d525a2f31aaf161d0" },
{ "abcdefghijklmnopqrstuvwxyz",
"c3fcd3d76192e4007dfb496cca67e13b" },
{ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
"d174ab98d277d9f5a5611c2c9f419d9f" },
{ "12345678901234567890123456789012345678901234567890123456789012345678901234567890",
"57edf4a22be3c955ac49da2e2107b67a" },
{ NULL, NULL }
};
int main(int argc, char *argv[])
{
FILE *f;
int i, j;
char output[33];
md_context ctx;
uchar buf[1000];
uchar md5sum[MD5_DIGEST_LEN];
if (argc < 2) {
printf("\nMD5 Validation Tests:\n\n");
for (i = 0; tests[i].str; i++) {
char *str = tests[i].str;
char *chk = tests[i].md5;
printf(" Test %d ", i + 1);
get_md5(md5sum, str, strlen(str));
for (j = 0; j < MD5_DIGEST_LEN; j++)
sprintf(output + j * 2, "%02x", md5sum[j]);
if (memcmp(output, chk, 32)) {
printf("failed!\n");
return 1;
}
printf("passed.\n");
}
printf("\n");
return 0;
}
while (--argc) {
if (!(f = fopen(*++argv, "rb"))) {
perror("fopen");
return 1;
}
md5_begin(&ctx);
while ((i = fread(buf, 1, sizeof buf, f)) > 0)
md5_update(&ctx, buf, i);
md5_result(&ctx, md5sum);
for (j = 0; j < MD5_DIGEST_LEN; j++)
printf("%02x", md5sum[j]);
printf(" %s\n", *argv);
}
return 0;
}
#endif

View File

@@ -4,11 +4,11 @@
* An implementation of MD4 designed for use in the SMB authentication protocol.
*
* Copyright (C) 1997-1998 Andrew Tridgell
* Copyright (C) 2005 Wayne Davison
* Copyright (C) 2005-2007 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
@@ -17,8 +17,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
* with this program; if not, visit the http://fsf.org website.
*/
#include "rsync.h"
@@ -27,7 +26,7 @@
*
* It assumes that a int is at least 32 bits long. */
static struct mdfour *m;
static md_context *m;
#define MASK32 (0xffffffff)
@@ -49,32 +48,31 @@ static void mdfour64(uint32 *M)
A = m->A; B = m->B; C = m->C; D = m->D;
AA = A; BB = B; CC = C; DD = D;
ROUND1(A,B,C,D, 0, 3); ROUND1(D,A,B,C, 1, 7);
ROUND1(A,B,C,D, 0, 3); ROUND1(D,A,B,C, 1, 7);
ROUND1(C,D,A,B, 2, 11); ROUND1(B,C,D,A, 3, 19);
ROUND1(A,B,C,D, 4, 3); ROUND1(D,A,B,C, 5, 7);
ROUND1(A,B,C,D, 4, 3); ROUND1(D,A,B,C, 5, 7);
ROUND1(C,D,A,B, 6, 11); ROUND1(B,C,D,A, 7, 19);
ROUND1(A,B,C,D, 8, 3); ROUND1(D,A,B,C, 9, 7);
ROUND1(A,B,C,D, 8, 3); ROUND1(D,A,B,C, 9, 7);
ROUND1(C,D,A,B, 10, 11); ROUND1(B,C,D,A, 11, 19);
ROUND1(A,B,C,D, 12, 3); ROUND1(D,A,B,C, 13, 7);
ROUND1(A,B,C,D, 12, 3); ROUND1(D,A,B,C, 13, 7);
ROUND1(C,D,A,B, 14, 11); ROUND1(B,C,D,A, 15, 19);
ROUND2(A,B,C,D, 0, 3); ROUND2(D,A,B,C, 4, 5);
ROUND2(A,B,C,D, 0, 3); ROUND2(D,A,B,C, 4, 5);
ROUND2(C,D,A,B, 8, 9); ROUND2(B,C,D,A, 12, 13);
ROUND2(A,B,C,D, 1, 3); ROUND2(D,A,B,C, 5, 5);
ROUND2(A,B,C,D, 1, 3); ROUND2(D,A,B,C, 5, 5);
ROUND2(C,D,A,B, 9, 9); ROUND2(B,C,D,A, 13, 13);
ROUND2(A,B,C,D, 2, 3); ROUND2(D,A,B,C, 6, 5);
ROUND2(A,B,C,D, 2, 3); ROUND2(D,A,B,C, 6, 5);
ROUND2(C,D,A,B, 10, 9); ROUND2(B,C,D,A, 14, 13);
ROUND2(A,B,C,D, 3, 3); ROUND2(D,A,B,C, 7, 5);
ROUND2(A,B,C,D, 3, 3); ROUND2(D,A,B,C, 7, 5);
ROUND2(C,D,A,B, 11, 9); ROUND2(B,C,D,A, 15, 13);
ROUND3(A,B,C,D, 0, 3); ROUND3(D,A,B,C, 8, 9);
ROUND3(C,D,A,B, 4, 11); ROUND3(B,C,D,A, 12, 15);
ROUND3(A,B,C,D, 2, 3); ROUND3(D,A,B,C, 10, 9);
ROUND3(A,B,C,D, 2, 3); ROUND3(D,A,B,C, 10, 9);
ROUND3(C,D,A,B, 6, 11); ROUND3(B,C,D,A, 14, 15);
ROUND3(A,B,C,D, 1, 3); ROUND3(D,A,B,C, 9, 9);
ROUND3(A,B,C,D, 1, 3); ROUND3(D,A,B,C, 9, 9);
ROUND3(C,D,A,B, 5, 11); ROUND3(B,C,D,A, 13, 15);
ROUND3(A,B,C,D, 3, 3); ROUND3(D,A,B,C, 11, 9);
ROUND3(A,B,C,D, 3, 3); ROUND3(D,A,B,C, 11, 9);
ROUND3(C,D,A,B, 7, 11); ROUND3(B,C,D,A, 15, 15);
A += AA; B += BB;
@@ -86,16 +84,17 @@ static void mdfour64(uint32 *M)
m->A = A; m->B = B; m->C = C; m->D = D;
}
static void copy64(uint32 *M, unsigned char *in)
static void copy64(uint32 *M, const uchar *in)
{
int i;
for (i=0;i<16;i++)
M[i] = (in[i*4+3]<<24) | (in[i*4+2]<<16) |
(in[i*4+1]<<8) | (in[i*4+0]<<0);
for (i = 0; i < MD4_DIGEST_LEN; i++) {
M[i] = (in[i*4+3] << 24) | (in[i*4+2] << 16)
| (in[i*4+1] << 8) | (in[i*4+0] << 0);
}
}
static void copy4(unsigned char *out,uint32 x)
static void copy4(uchar *out,uint32 x)
{
out[0] = x&0xFF;
out[1] = (x>>8)&0xFF;
@@ -103,7 +102,7 @@ static void copy4(unsigned char *out,uint32 x)
out[3] = (x>>24)&0xFF;
}
void mdfour_begin(struct mdfour *md)
void mdfour_begin(md_context *md)
{
md->A = 0x67452301;
md->B = 0xefcdab89;
@@ -113,27 +112,26 @@ void mdfour_begin(struct mdfour *md)
md->totalN2 = 0;
}
static void mdfour_tail(unsigned char *in, uint32 n)
static void mdfour_tail(const uchar *in, uint32 length)
{
unsigned char buf[128];
uchar buf[128];
uint32 M[16];
extern int protocol_version;
/*
* Count total number of bits, modulo 2^64
*/
m->totalN += n << 3;
if (m->totalN < (n << 3)) {
m->totalN += length << 3;
if (m->totalN < (length << 3))
m->totalN2++;
}
m->totalN2 += n >> 29;
m->totalN2 += length >> 29;
memset(buf, 0, 128);
if (n) memcpy(buf, in, n);
buf[n] = 0x80;
if (length)
memcpy(buf, in, length);
buf[length] = 0x80;
if (n <= 55) {
if (length <= 55) {
copy4(buf+56, m->totalN);
/*
* Prior to protocol version 27 only the number of bits
@@ -141,9 +139,8 @@ static void mdfour_tail(unsigned char *in, uint32 n)
* of bits modulo 2^64, which was fixed starting with
* protocol version 27.
*/
if (protocol_version >= 27) {
if (protocol_version >= 27)
copy4(buf+60, m->totalN2);
}
copy64(M, buf);
mdfour64(M);
} else {
@@ -154,9 +151,8 @@ static void mdfour_tail(unsigned char *in, uint32 n)
* of bits modulo 2^64, which was fixed starting with
* protocol version 27.
*/
if (protocol_version >= 27) {
if (protocol_version >= 27)
copy4(buf+124, m->totalN2);
}
copy64(M, buf);
mdfour64(M);
copy64(M, buf+64);
@@ -164,46 +160,45 @@ static void mdfour_tail(unsigned char *in, uint32 n)
}
}
void mdfour_update(struct mdfour *md, unsigned char *in, uint32 n)
void mdfour_update(md_context *md, const uchar *in, uint32 length)
{
uint32 M[16];
m = md;
if (n == 0) mdfour_tail(in, n);
if (length == 0)
mdfour_tail(in, length);
while (n >= 64) {
while (length >= 64) {
copy64(M, in);
mdfour64(M);
in += 64;
n -= 64;
length -= 64;
m->totalN += 64 << 3;
if (m->totalN < 64 << 3) {
if (m->totalN < 64 << 3)
m->totalN2++;
}
}
if (n) mdfour_tail(in, n);
if (length)
mdfour_tail(in, length);
}
void mdfour_result(struct mdfour *md, unsigned char *out)
void mdfour_result(md_context *md, uchar digest[MD4_DIGEST_LEN])
{
m = md;
copy4(out, m->A);
copy4(out+4, m->B);
copy4(out+8, m->C);
copy4(out+12, m->D);
copy4(digest, m->A);
copy4(digest+4, m->B);
copy4(digest+8, m->C);
copy4(digest+12, m->D);
}
void mdfour(unsigned char *out, unsigned char *in, int n)
void mdfour(uchar digest[MD4_DIGEST_LEN], uchar *in, int length)
{
struct mdfour md;
md_context md;
mdfour_begin(&md);
mdfour_update(&md, in, n);
mdfour_result(&md, out);
mdfour_update(&md, in, length);
mdfour_result(&md, digest);
}
#ifdef TEST_MDFOUR
@@ -212,8 +207,8 @@ int protocol_version = 28;
static void file_checksum1(char *fname)
{
int fd, i, was_multiple_of_64 = 1;
struct mdfour md;
unsigned char buf[64*1024], sum[16];
md_context md;
uchar buf[64*1024], sum[MD4_DIGEST_LEN];
fd = open(fname,O_RDONLY);
if (fd == -1) {
@@ -224,7 +219,7 @@ static void file_checksum1(char *fname)
mdfour_begin(&md);
while (1) {
int n = read(fd, buf, sizeof(buf));
int n = read(fd, buf, sizeof buf);
if (n <= 0)
break;
was_multiple_of_64 = !(n % 64);
@@ -237,54 +232,15 @@ static void file_checksum1(char *fname)
mdfour_result(&md, sum);
for (i=0;i<16;i++)
for (i = 0; i < MD4_DIGEST_LEN; i++)
printf("%02X", sum[i]);
printf("\n");
}
#if 0
#include "../md4.h"
static void file_checksum2(char *fname)
{
int fd, i;
MDstruct md;
unsigned char buf[64], sum[16];
fd = open(fname,O_RDONLY);
if (fd == -1) {
perror("fname");
exit(1);
}
MDbegin(&md);
while (1) {
int n = read(fd, buf, sizeof(buf));
if (n <= 0) break;
MDupdate(&md, buf, n*8);
}
if (!md.done) {
MDupdate(&md, buf, 0);
}
close(fd);
memcpy(sum, md.buffer, 16);
for (i=0;i<16;i++)
printf("%02X", sum[i]);
printf("\n");
}
#endif
int main(int argc, char *argv[])
{
file_checksum1(argv[1]);
#if 0
file_checksum2(argv[1]);
#endif
while (--argc)
file_checksum1(*++argv);
return 0;
}
#endif

View File

@@ -1,32 +0,0 @@
/*
* Unix SMB/Netbios implementation.
* Version 1.9.
* An implementation of MD4 designed for use in the SMB authentication protocol.
*
* Copyright (C) 1997-1998 Andrew Tridgell
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
struct mdfour {
uint32 A, B, C, D;
uint32 totalN; /* bit count, lower 32 bits */
uint32 totalN2; /* bit count, upper 32 bits */
};
void mdfour_begin(struct mdfour *md);
void mdfour_update(struct mdfour *md, unsigned char *in, uint32 n);
void mdfour_result(struct mdfour *md, unsigned char *out);
void mdfour(unsigned char *out, unsigned char *in, int n);

26
lib/mdigest.h Normal file
View File

@@ -0,0 +1,26 @@
/* The include file for both the MD4 and MD5 routines. */
#define MD4_DIGEST_LEN 16
#define MD5_DIGEST_LEN 16
#define MAX_DIGEST_LEN MD5_DIGEST_LEN
#define CSUM_CHUNK 64
typedef struct {
uint32 A, B, C, D;
uint32 totalN; /* bit count, lower 32 bits */
uint32 totalN2; /* bit count, upper 32 bits */
uchar buffer[CSUM_CHUNK];
} md_context;
void mdfour_begin(md_context *md);
void mdfour_update(md_context *md, const uchar *in, uint32 length);
void mdfour_result(md_context *md, uchar digest[MD4_DIGEST_LEN]);
void get_mdfour(uchar digest[MD4_DIGEST_LEN], const uchar *in, int length);
void md5_begin(md_context *ctx);
void md5_update(md_context *ctx, const uchar *input, uint32 length);
void md5_result(md_context *ctx, uchar digest[MD5_DIGEST_LEN]);
void get_md5(uchar digest[MD5_DIGEST_LEN], const uchar *input, int n);

View File

@@ -8,7 +8,7 @@
*
* 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
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
@@ -17,8 +17,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
* with this program; if not, visit the http://fsf.org website.
*/
#include "rsync.h"

View File

@@ -28,7 +28,7 @@ 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
pool_alloc, pool_free, pool_free_old, pool_talloc, pool_tfree, pool_create, pool_destroy, pool_boundary
\- Allocate and free memory in managed allocation pools.
.SH SYNOPSIS
.B #include "pool_alloc.h"
@@ -39,42 +39,45 @@ pool_alloc, pool_free, pool_talloc, pool_tfree, pool_create, pool_destroy
\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_free(struct alloc_pool *\fIpool\fB, size_t \fIsize\fB, void *\fIaddr\fB);
\fBvoid pool_free_old(struct alloc_pool *\fIpool\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);
\fBvoid pool_boundary(struct alloc_pool *\fIpool\fB, sise_t \fIsize\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()
What allocation pools do is cause memory within a given pool
to be allocated in large contiguous blocks
(called extents) that will be reusable when freed. Unlike
.BR malloc() ,
the allocations are not managed individually.
Instead each extent tracks the total free memory within the
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.
allocation request, the current extent ceases to be used
for allocation. See also the
.B pool_boundary()
function.
.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
underlying allocations are done in large contiguous extents,
when an extent is freed, it can release a large enough
contiguous block of memory to allow the memory to be returned
to the OS for use by whatever program needs it.
You can allocate from one or more memory pools and/or
.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.
all at the same time without interfering with how pools work.
.P
.B pool_create()
Creates an allocation pool for subsequent calls to the pool
@@ -90,22 +93,32 @@ Specifying
.B 0
for
.I quantum
Will produce a quantum that should meet maximal allignment
will produce a quantum that should meet maximal alignment
on most platforms.
If the
If
.B POOL_QALIGN
.I flag
is set allocations will be aligned to addresses that are a
is set in the
.IR flags ,
allocations will be aligned to addresses that are a
multiple of
.IR quantum .
If the
If
.B POOL_CLEAR
.I flag
is set all allocations from the pool will be zero filled.
is set in the
.IR flags ,
all allocations from the pool will be initialized to zeros.
You may specify a
.B NULL
for the
.I bomb
function pointer if you don't wish to use it. (See the
.B pool_alloc()
function for how it is used.)
.P
.B pool_destroy()
destroys an allocation pool and frees all memory allocated
in that pool.
destroys an allocation
.I pool
and frees all its associated memory.
.P
.B pool_alloc()
allocates
@@ -115,57 +128,97 @@ bytes from the specified
If
.I size
is
.B 0
.BR 0 ,
.I quantum
bytes will be freed.
If the requested memory cannot be allocated
.B pool_alloc()
will call
bytes will be allocated.
If the pool has been created with
.BR POOL_QALIGN ,
every chunk of memory that is returned will be suitably aligned.
You can use this with the default
.I quantum
size to ensure that all memory can store a variable of any type.
If the requested memory cannot be allocated, the
.I bomb()
function, if defined, with
function will be called with
.I msg
as it's sole argument and
as its sole argument (if the function was defined at the time
the pool was created), and then a
.B NULL
will be returned.
address is returned (assuming that the bomb function didn't exit).
.P
.B pool_free()
frees
.I size
bytes pointed to by
bytes pointed to by an
.I addr
previously allocated in the specified
that was 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
.BR 0 ,
.I quantum
bytes will be freed.
The memory freed within an extent will not be reusable until
all of the memory in that extent has been freed with one
exception: the most recent pool allocation may be freed back
into the pool prior to making any further allocations.
If enough free calls are made to indicate that an extent has no
remaining allocated objects (as computed by the total freed size for
an extent), its memory will be completely freed back to the system.
If
.I addr
is
.B 0
no memory will be freed but subsequent allocations will come
.BR 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
.B pool_free_old()
takes a boundary
.I addr
value that was returned by
.B pool_boundary()
and frees up any extents in the
.I pool
that have data allocated from that point backward in time.
NOTE: you must NOT mix calls to both
.B pool_free
and
.B pool_free_old
on the same pool!
.P
.B pool_boundary()
asks for a boundary value that can be sent to
.B pool_free_old()
at a later time to free up all memory allocated prior to a particular
moment in time.
If the extent that holds the boundary point has allocations from after the
boundary point, it will not be freed until a future
.B pool_free_old()
call encompasses the entirety of the extent's data.
If
.I len
is non-zero, the call will also check if the active extent has at least
that much free memory available in it, and if not, it will mark the
extent as inactive, forcing a new extent to be used for future allocations.
(You can specify -1 for
.I len
if you want to force a new extent to start.)
.P
.B pool_talloc()
is a macro that takes a
.I type
and a
.I count
instead of
.I size
and will cast the return value to the correct type.
instead of a
.IR size .
It casts the return value to the correct pointer type.
.P
.B pool_tfree
is a macro to free memory previously allocated in the
specified
.IR pool .
is a macro that calls
.B pool_free
on memory that was allocated by
.BR pool_talloc() .
.SH RETURN VALUE
.B pool_create()
returns a pointer to
@@ -176,9 +229,6 @@ 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
@@ -186,7 +236,12 @@ will normally require casting to the desired type but
will returns a pointer of the requested
.IR type .
.P
.B pool_boundary()
returns a pointer that should only be used in a call to
.BR pool_free_old() .
.P
.BR pool_free() ,
.BR pool_free_old() ,
.B pool_tfree()
and
.B pool_destroy()

View File

@@ -6,11 +6,8 @@ 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
struct pool_extent *extents; /* top extent is "live" */
void (*bomb)(); /* function to call if
* malloc fails */
int flags;
@@ -33,8 +30,8 @@ struct pool_extent
};
struct align_test {
void *foo;
int64 bar;
void *foo;
int64 bar;
};
#define MINALIGN offsetof(struct align_test, bar)
@@ -44,19 +41,18 @@ struct align_test {
#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)
pool_create(size_t size, size_t quantum, void (*bomb)(const char *), int flags)
{
struct alloc_pool *pool;
if (!(pool = (struct alloc_pool*) malloc(sizeof (struct alloc_pool))))
if (!(pool = new(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) {
if (flags & POOL_INTERN) {
pool->size -= sizeof (struct pool_extent);
flags |= POOL_APPEND;
}
@@ -76,13 +72,7 @@ pool_destroy(alloc_pool_t p)
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) {
for (cur = pool->extents; cur; cur = next) {
next = cur->next;
free(cur->start);
if (!(pool->flags & POOL_APPEND))
@@ -92,7 +82,7 @@ pool_destroy(alloc_pool_t p)
}
void *
pool_alloc(alloc_pool_t p, size_t len, char *bomb)
pool_alloc(alloc_pool_t p, size_t len, const char *bomb_msg)
{
struct alloc_pool *pool = (struct alloc_pool *) p;
if (!pool)
@@ -104,19 +94,15 @@ pool_alloc(alloc_pool_t p, size_t len, char *bomb)
len += pool->quantum - len % pool->quantum;
if (len > pool->size)
goto bomb;
goto bomb_out;
if (!pool->live || len > pool->live->free) {
if (!pool->extents || len > pool->extents->free) {
void *start;
size_t free;
size_t bound;
size_t sqew;
size_t skew;
size_t asize;
if (pool->live) {
pool->live->next = pool->free;
pool->free = pool->live;
}
struct pool_extent *ext;
free = pool->size;
bound = 0;
@@ -125,25 +111,26 @@ pool_alloc(alloc_pool_t p, size_t len, char *bomb)
if (pool->flags & POOL_APPEND)
asize += sizeof (struct pool_extent);
if (!(start = (void *) malloc(asize)))
goto bomb;
if (!(start = new_array(char, asize)))
goto bomb_out;
if (pool->flags & POOL_CLEAR)
memset(start, 0, pool->size);
memset(start, 0, free);
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;
ext = PTR_ADD(start, free);
else if (!(ext = new(struct pool_extent)))
goto bomb_out;
if (pool->flags & POOL_QALIGN && pool->quantum > 1
&& (sqew = (size_t)PTR_ADD(start, free) % pool->quantum)) {
bound += sqew;
free -= sqew;
&& (skew = (size_t)PTR_ADD(start, free) % pool->quantum)) {
bound += skew;
free -= skew;
}
pool->live->start = start;
pool->live->free = free;
pool->live->bound = bound;
pool->live->next = NULL;
ext->start = start;
ext->free = free;
ext->bound = bound;
ext->next = pool->extents;
pool->extents = ext;
pool->e_created++;
}
@@ -151,22 +138,24 @@ pool_alloc(alloc_pool_t p, size_t len, char *bomb)
pool->n_allocated++;
pool->b_allocated += len;
pool->live->free -= len;
pool->extents->free -= len;
return PTR_ADD(pool->live->start, pool->live->free);
return PTR_ADD(pool->extents->start, pool->extents->free);
bomb:
bomb_out:
if (pool->bomb)
(*pool->bomb)(bomb);
(*pool->bomb)(bomb_msg);
return NULL;
}
/* This function allows you to declare memory in the pool that you are done
* using. If you free all the memory in a pool's extent, that extent will
* be freed. */
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;
struct alloc_pool *pool = (struct alloc_pool *)p;
struct pool_extent *cur, *prev;
if (!pool)
return;
@@ -176,38 +165,10 @@ pool_free(alloc_pool_t p, size_t len, void *addr)
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) {
for (prev = NULL, cur = pool->extents; cur; prev = cur, cur = cur->next) {
if (addr >= cur->start
&& addr < PTR_ADD(cur->start, pool->size))
break;
@@ -215,22 +176,122 @@ pool_free(alloc_pool_t p, size_t len, void *addr)
if (!cur)
return;
if (prev) {
prev->next = cur->next;
cur->next = pool->free;
pool->free = cur;
if (!prev) {
/* The "live" extent is kept ready for more allocations. */
if (cur->free + cur->bound + len >= pool->size) {
size_t skew;
if (pool->flags & POOL_CLEAR) {
memset(PTR_ADD(cur->start, cur->free), 0,
pool->size - cur->free);
}
cur->free = pool->size;
cur->bound = 0;
if (pool->flags & POOL_QALIGN && pool->quantum > 1
&& (skew = (size_t)PTR_ADD(cur->start, cur->free) % pool->quantum)) {
cur->bound += skew;
cur->free -= skew;
}
} else if (addr == PTR_ADD(cur->start, cur->free)) {
if (pool->flags & POOL_CLEAR)
memset(addr, 0, len);
cur->free += len;
} else
cur->bound += len;
} else {
cur->bound += len;
if (cur->free + cur->bound >= pool->size) {
prev->next = cur->next;
free(cur->start);
if (!(pool->flags & POOL_APPEND))
free(cur);
pool->e_freed++;
} else if (prev != pool->extents) {
/* Move the extent to be the first non-live extent. */
prev->next = cur->next;
cur->next = pool->extents->next;
pool->extents->next = cur;
}
}
cur->bound += len;
}
if (cur->free + cur->bound >= pool->size) {
pool->free = cur->next;
/* This allows you to declare that the given address marks the edge of some
* pool memory that is no longer needed. Any extents that hold only data
* older than the boundary address are freed. NOTE: You MUST NOT USE BOTH
* pool_free() and pool_free_old() on the same pool!! */
void
pool_free_old(alloc_pool_t p, void *addr)
{
struct alloc_pool *pool = (struct alloc_pool *)p;
struct pool_extent *cur, *prev, *next;
if (!pool || !addr)
return;
for (prev = NULL, cur = pool->extents; cur; prev = cur, cur = cur->next) {
if (addr >= cur->start
&& addr < PTR_ADD(cur->start, pool->size))
break;
}
if (!cur)
return;
if (addr == PTR_ADD(cur->start, cur->free)) {
if (prev) {
prev->next = NULL;
next = cur;
} else {
size_t skew;
/* The most recent live extent can just be reset. */
if (pool->flags & POOL_CLEAR)
memset(addr, 0, pool->size - cur->free);
cur->free = pool->size;
cur->bound = 0;
if (pool->flags & POOL_QALIGN && pool->quantum > 1
&& (skew = (size_t)PTR_ADD(cur->start, cur->free) % pool->quantum)) {
cur->bound += skew;
cur->free -= skew;
}
next = cur->next;
cur->next = NULL;
}
} else {
next = cur->next;
cur->next = NULL;
}
while ((cur = next) != NULL) {
next = cur->next;
free(cur->start);
if (!(pool->flags & POOL_APPEND))
free(cur);
pool->e_freed++;
}
return;
}
/* If the current extent doesn't have "len" free space in it, mark it as full
* so that the next alloc will start a new extent. If len is (size_t)-1, this
* bump will always occur. The function returns a boundary address that can
* be used with pool_free_old(), or a NULL if no memory is allocated. */
void *
pool_boundary(alloc_pool_t p, size_t len)
{
struct alloc_pool *pool = (struct alloc_pool *)p;
struct pool_extent *cur;
if (!pool || !pool->extents)
return NULL;
cur = pool->extents;
if (cur->free < len) {
cur->bound += cur->free;
cur->free = 0;
}
return PTR_ADD(cur->start, cur->free);
}
#define FDPRINT(label, value) \
@@ -259,22 +320,17 @@ pool_stats(alloc_pool_t p, int fd, int summarize)
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);
FDPRINT(" Bytes allocated: %12.0f\n", (double) pool->b_allocated);
FDPRINT(" Bytes freed: %12.0f\n", (double) pool->b_freed);
if (summarize)
return;
if (!pool->live && !pool->free)
if (!pool->extents)
return;
write(fd, "\n", 1);
if (pool->live)
FDEXTSTAT(pool->live);
strlcpy(buf, " FREE BOUND\n", sizeof buf);
write(fd, buf, strlen(buf));
for (cur = pool->free; cur; cur = cur->next)
for (cur = pool->extents; cur; cur = cur->next)
FDEXTSTAT(cur);
}

View File

@@ -7,14 +7,15 @@
typedef void *alloc_pool_t;
alloc_pool_t pool_create(size_t size, size_t quantum, void (*bomb)(char *), int flags);
alloc_pool_t pool_create(size_t size, size_t quantum, void (*bomb)(const char *), int flags);
void pool_destroy(alloc_pool_t pool);
void *pool_alloc(alloc_pool_t pool, size_t size, char *bomb);
void *pool_alloc(alloc_pool_t pool, size_t size, const char *bomb_msg);
void pool_free(alloc_pool_t pool, size_t size, void *addr);
void pool_free_old(alloc_pool_t pool, void *addr);
void *pool_boundary(alloc_pool_t pool, size_t size);
#define pool_talloc(pool, type, count, bomb) \
((type *)pool_alloc(pool, sizeof(type) * count, bomb))
#define pool_talloc(pool, type, count, bomb_msg) \
((type *)pool_alloc(pool, sizeof(type) * count, bomb_msg))
#define pool_tfree(pool, type, count, addr) \
(pool_free(pool, sizeof(type) * count, addr))

2771
lib/sysacls.c Normal file
View File

File diff suppressed because it is too large Load Diff

304
lib/sysacls.h Normal file
View File

@@ -0,0 +1,304 @@
/*
* Unix SMB/Netbios implementation.
* Version 2.2.x
* Portable SMB ACL interface
* Copyright (C) Jeremy Allison 2000
*
* 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 3 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
* with this program; if not, visit the http://fsf.org website.
*/
#ifdef SUPPORT_ACLS
#ifdef HAVE_SYS_ACL_H
#include <sys/acl.h>
#endif
#ifdef HAVE_ACL_LIBACL_H
#include <acl/libacl.h>
#endif
#define SMB_MALLOC(cnt) new_array(char, cnt)
#define SMB_MALLOC_P(obj) new_array(obj, 1)
#define SMB_MALLOC_ARRAY(obj, cnt) new_array(obj, cnt)
#define SMB_REALLOC(mem, cnt) realloc_array(mem, char, cnt)
#define slprintf snprintf
#if defined HAVE_POSIX_ACLS /*-----------------------------------------------*/
/* This is an identity mapping (just remove the SMB_). */
#define SMB_ACL_TAG_T acl_tag_t
#define SMB_ACL_TYPE_T acl_type_t
/* Types of ACLs. */
#define SMB_ACL_USER ACL_USER
#define SMB_ACL_USER_OBJ ACL_USER_OBJ
#define SMB_ACL_GROUP ACL_GROUP
#define SMB_ACL_GROUP_OBJ ACL_GROUP_OBJ
#define SMB_ACL_OTHER ACL_OTHER
#define SMB_ACL_MASK ACL_MASK
#define SMB_ACL_T acl_t
#define SMB_ACL_ENTRY_T acl_entry_t
#define SMB_ACL_FIRST_ENTRY ACL_FIRST_ENTRY
#define SMB_ACL_NEXT_ENTRY ACL_NEXT_ENTRY
#define SMB_ACL_TYPE_ACCESS ACL_TYPE_ACCESS
#define SMB_ACL_TYPE_DEFAULT ACL_TYPE_DEFAULT
#define SMB_ACL_VALID_NAME_BITS (4 | 2 | 1)
#define SMB_ACL_VALID_OBJ_BITS (4 | 2 | 1)
#define SMB_ACL_NEED_SORT
#elif defined HAVE_TRU64_ACLS /*---------------------------------------------*/
/* This is for DEC/Compaq Tru64 UNIX */
#define SMB_ACL_TAG_T acl_tag_t
#define SMB_ACL_TYPE_T acl_type_t
/* Types of ACLs. */
#define SMB_ACL_USER ACL_USER
#define SMB_ACL_USER_OBJ ACL_USER_OBJ
#define SMB_ACL_GROUP ACL_GROUP
#define SMB_ACL_GROUP_OBJ ACL_GROUP_OBJ
#define SMB_ACL_OTHER ACL_OTHER
#define SMB_ACL_MASK ACL_MASK
#define SMB_ACL_T acl_t
#define SMB_ACL_ENTRY_T acl_entry_t
#define SMB_ACL_FIRST_ENTRY 0
#define SMB_ACL_NEXT_ENTRY 1
#define SMB_ACL_TYPE_ACCESS ACL_TYPE_ACCESS
#define SMB_ACL_TYPE_DEFAULT ACL_TYPE_DEFAULT
#define SMB_ACL_VALID_NAME_BITS (4 | 2 | 1)
#define SMB_ACL_VALID_OBJ_BITS (4 | 2 | 1)
#define SMB_ACL_NEED_SORT
#elif defined HAVE_UNIXWARE_ACLS || defined HAVE_SOLARIS_ACLS /*-------------*/
/* Donated by Michael Davidson <md@sco.COM> for UnixWare / OpenUNIX.
* Modified by Toomas Soome <tsoome@ut.ee> for Solaris. */
/* SVR4.2 ES/MP ACLs */
typedef int SMB_ACL_TAG_T;
typedef int SMB_ACL_TYPE_T;
/* Types of ACLs. */
#define SMB_ACL_USER USER
#define SMB_ACL_USER_OBJ USER_OBJ
#define SMB_ACL_GROUP GROUP
#define SMB_ACL_GROUP_OBJ GROUP_OBJ
#define SMB_ACL_OTHER OTHER_OBJ
#define SMB_ACL_MASK CLASS_OBJ
typedef struct SMB_ACL_T {
int size;
int count;
int next;
struct acl acl[1];
} *SMB_ACL_T;
typedef struct acl *SMB_ACL_ENTRY_T;
#define SMB_ACL_FIRST_ENTRY 0
#define SMB_ACL_NEXT_ENTRY 1
#define SMB_ACL_TYPE_ACCESS 0
#define SMB_ACL_TYPE_DEFAULT 1
#define SMB_ACL_VALID_NAME_BITS (4 | 2 | 1)
#define SMB_ACL_VALID_OBJ_BITS (4 | 2 | 1)
#define SMB_ACL_NEED_SORT
#ifdef __CYGWIN__
#define SMB_ACL_LOSES_SPECIAL_MODE_BITS
#endif
#elif defined HAVE_HPUX_ACLS /*----------------------------------------------*/
/* Based on the Solaris & UnixWare code. */
#undef GROUP
#include <sys/aclv.h>
/* SVR4.2 ES/MP ACLs */
typedef int SMB_ACL_TAG_T;
typedef int SMB_ACL_TYPE_T;
/* Types of ACLs. */
#define SMB_ACL_USER USER
#define SMB_ACL_USER_OBJ USER_OBJ
#define SMB_ACL_GROUP GROUP
#define SMB_ACL_GROUP_OBJ GROUP_OBJ
#define SMB_ACL_OTHER OTHER_OBJ
#define SMB_ACL_MASK CLASS_OBJ
typedef struct SMB_ACL_T {
int size;
int count;
int next;
struct acl acl[1];
} *SMB_ACL_T;
typedef struct acl *SMB_ACL_ENTRY_T;
#define SMB_ACL_FIRST_ENTRY 0
#define SMB_ACL_NEXT_ENTRY 1
#define SMB_ACL_TYPE_ACCESS 0
#define SMB_ACL_TYPE_DEFAULT 1
#define SMB_ACL_VALID_NAME_BITS (4 | 2 | 1)
#define SMB_ACL_VALID_OBJ_BITS (4 | 2 | 1)
#define SMB_ACL_NEED_SORT
#elif defined HAVE_IRIX_ACLS /*----------------------------------------------*/
/* IRIX ACLs */
#define SMB_ACL_TAG_T acl_tag_t
#define SMB_ACL_TYPE_T acl_type_t
/* Types of ACLs. */
#define SMB_ACL_USER ACL_USER
#define SMB_ACL_USER_OBJ ACL_USER_OBJ
#define SMB_ACL_GROUP ACL_GROUP
#define SMB_ACL_GROUP_OBJ ACL_GROUP_OBJ
#define SMB_ACL_OTHER ACL_OTHER_OBJ
#define SMB_ACL_MASK ACL_MASK
typedef struct SMB_ACL_T {
int next;
BOOL freeaclp;
struct acl *aclp;
} *SMB_ACL_T;
#define SMB_ACL_ENTRY_T acl_entry_t
#define SMB_ACL_FIRST_ENTRY 0
#define SMB_ACL_NEXT_ENTRY 1
#define SMB_ACL_TYPE_ACCESS ACL_TYPE_ACCESS
#define SMB_ACL_TYPE_DEFAULT ACL_TYPE_DEFAULT
#define SMB_ACL_VALID_NAME_BITS (4 | 2 | 1)
#define SMB_ACL_VALID_OBJ_BITS (4 | 2 | 1)
#define SMB_ACL_NEED_SORT
#elif defined HAVE_AIX_ACLS /*-----------------------------------------------*/
/* Donated by Medha Date, mdate@austin.ibm.com, for IBM */
#include "/usr/include/acl.h"
struct acl_entry_link{
struct acl_entry_link *prevp;
struct new_acl_entry *entryp;
struct acl_entry_link *nextp;
int count;
};
struct new_acl_entry{
unsigned short ace_len;
unsigned short ace_type;
unsigned int ace_access;
struct ace_id ace_id[1];
};
#define SMB_ACL_ENTRY_T struct new_acl_entry*
#define SMB_ACL_T struct acl_entry_link*
#define SMB_ACL_TAG_T unsigned short
#define SMB_ACL_TYPE_T int
/* Types of ACLs. */
#define SMB_ACL_USER ACEID_USER
#define SMB_ACL_USER_OBJ 3
#define SMB_ACL_GROUP ACEID_GROUP
#define SMB_ACL_GROUP_OBJ 4
#define SMB_ACL_OTHER 5
#define SMB_ACL_MASK 6
#define SMB_ACL_FIRST_ENTRY 1
#define SMB_ACL_NEXT_ENTRY 2
#define SMB_ACL_TYPE_ACCESS 0
#define SMB_ACL_TYPE_DEFAULT 1
#define SMB_ACL_VALID_NAME_BITS (4 | 2 | 1)
#define SMB_ACL_VALID_OBJ_BITS (4 | 2 | 1)
#define SMB_ACL_NEED_SORT
#elif defined(HAVE_OSX_ACLS) /*----------------------------------------------*/
/* Special handling for OS X ACLs */
#define SMB_ACL_TAG_T acl_tag_t
#define SMB_ACL_TYPE_T acl_type_t
#define SMB_ACL_T acl_t
#define SMB_ACL_ENTRY_T acl_entry_t
#define SMB_ACL_USER 1
#define SMB_ACL_GROUP 2
#define SMB_ACL_FIRST_ENTRY ACL_FIRST_ENTRY
#define SMB_ACL_NEXT_ENTRY ACL_NEXT_ENTRY
#define SMB_ACL_TYPE_ACCESS ACL_TYPE_EXTENDED
#define SMB_ACL_TYPE_DEFAULT ACL_TYPE_DEFAULT
#define SMB_ACL_VALID_NAME_BITS ((1<<25)-1)
#define SMB_ACL_VALID_OBJ_BITS 0
/*#undef SMB_ACL_NEED_SORT*/
#else /*---------------------------------------------------------------------*/
/* Unknown platform. */
#error Cannot handle ACLs on this platform!
#endif
int sys_acl_get_entry(SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p);
int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p);
int sys_acl_get_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T *tag_type_p, uint32 *bits_p, id_t *u_g_id_p);
SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type);
SMB_ACL_T sys_acl_get_fd(int fd);
SMB_ACL_T sys_acl_init(int count);
int sys_acl_create_entry(SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry);
int sys_acl_set_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype, uint32 bits, id_t u_g_id);
int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry, uint32 bits);
int sys_acl_valid(SMB_ACL_T theacl);
int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl);
int sys_acl_set_fd(int fd, SMB_ACL_T theacl);
int sys_acl_delete_def_file(const char *name);
int sys_acl_free_acl(SMB_ACL_T the_acl);
int no_acl_syscall_error(int err);
#endif /* SUPPORT_ACLS */

134
lib/sysxattrs.c Normal file
View File

@@ -0,0 +1,134 @@
/*
* Extended attribute support for rsync.
*
* Copyright (C) 2004 Red Hat, Inc.
* Written by Jay Fenlason.
*
* 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 3 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, visit the http://fsf.org website.
*/
#include "rsync.h"
#include "sysxattrs.h"
#ifdef SUPPORT_XATTRS
#if defined HAVE_LINUX_XATTRS
ssize_t sys_lgetxattr(const char *path, const char *name, void *value, size_t size)
{
return lgetxattr(path, name, value, size);
}
ssize_t sys_fgetxattr(int filedes, const char *name, void *value, size_t size)
{
return fgetxattr(filedes, name, value, size);
}
int sys_lsetxattr(const char *path, const char *name, const void *value, size_t size)
{
return lsetxattr(path, name, value, size, 0);
}
int sys_lremovexattr(const char *path, const char *name)
{
return lremovexattr(path, name);
}
ssize_t sys_llistxattr(const char *path, char *list, size_t size)
{
return llistxattr(path, list, size);
}
#elif HAVE_OSX_XATTRS
ssize_t sys_lgetxattr(const char *path, const char *name, void *value, size_t size)
{
return getxattr(path, name, value, size, 0, XATTR_NOFOLLOW);
}
ssize_t sys_fgetxattr(int filedes, const char *name, void *value, size_t size)
{
return fgetxattr(filedes, name, value, size, 0, 0);
}
int sys_lsetxattr(const char *path, const char *name, const void *value, size_t size)
{
return setxattr(path, name, value, size, 0, XATTR_NOFOLLOW);
}
int sys_lremovexattr(const char *path, const char *name)
{
return removexattr(path, name, XATTR_NOFOLLOW);
}
ssize_t sys_llistxattr(const char *path, char *list, size_t size)
{
return listxattr(path, list, size, XATTR_NOFOLLOW);
}
#elif HAVE_FREEBSD_XATTRS
ssize_t sys_lgetxattr(const char *path, const char *name, void *value, size_t size)
{
return extattr_get_link(path, EXTATTR_NAMESPACE_USER, name, value, size);
}
ssize_t sys_fgetxattr(int filedes, const char *name, void *value, size_t size)
{
return extattr_get_fd(filedes, EXTATTR_NAMESPACE_USER, name, value, size);
}
int sys_lsetxattr(const char *path, const char *name, const void *value, size_t size)
{
return extattr_set_link(path, EXTATTR_NAMESPACE_USER, name, value, size);
}
int sys_lremovexattr(const char *path, const char *name)
{
return extattr_delete_link(path, EXTATTR_NAMESPACE_USER, name);
}
ssize_t sys_llistxattr(const char *path, char *list, size_t size)
{
unsigned char keylen;
ssize_t off, len = extattr_list_link(path, EXTATTR_NAMESPACE_USER, list, size);
if (len <= 0 || (size_t)len > size)
return len;
/* FreeBSD puts a single-byte length before each string, with no '\0'
* terminator. We need to change this into a series of null-terminted
* strings. Since the size is the same, we can simply transform the
* output in place. */
for (off = 0; off < len; off += keylen + 1) {
keylen = ((unsigned char*)list)[off];
if (off + keylen >= len) {
/* Should be impossible, but kernel bugs happen! */
errno = EINVAL;
return -1;
}
memmove(list+off, list+off+1, keylen);
list[off+keylen] = '\0';
}
return len;
}
#else
#error You need to create xattr compatibility functions.
#endif
#endif /* SUPPORT_XATTRS */

26
lib/sysxattrs.h Normal file
View File

@@ -0,0 +1,26 @@
#ifdef SUPPORT_XATTRS
#if defined HAVE_ATTR_XATTR_H
#include <attr/xattr.h>
#elif defined HAVE_SYS_XATTR_H
#include <sys/xattr.h>
#elif defined HAVE_SYS_EXTATTR_H
#include <sys/extattr.h>
#endif
/* Linux 2.4 does not define this as a distinct errno value: */
#ifndef ENOATTR
#define ENOATTR ENODATA
#endif
ssize_t sys_lgetxattr(const char *path, const char *name, void *value, size_t size);
ssize_t sys_fgetxattr(int filedes, const char *name, void *value, size_t size);
int sys_lsetxattr(const char *path, const char *name, const void *value, size_t size);
int sys_lremovexattr(const char *path, const char *name);
ssize_t sys_llistxattr(const char *path, char *list, size_t size);
#else
/* No xattrs available */
#endif

View File

@@ -165,7 +165,7 @@ static int dowild(const uchar *p, const uchar *text, const uchar*const *a)
} else if (p_ch == '[' && p[1] == ':') {
const uchar *s;
int i;
for (s = p += 2; (p_ch = *p) && p_ch != ']'; p++) {}
for (s = p += 2; (p_ch = *p) && p_ch != ']'; p++) {} /*SHARED ITERATOR*/
if (!p_ch)
return ABORT_ALL;
i = p - s - 1;

View File

@@ -4,7 +4,7 @@
/*
* 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
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
@@ -13,8 +13,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
* with this program; if not, visit the http://fsf.org website.
*/
/* some fixes
@@ -51,6 +50,7 @@
/* TODO: Parameter to set debug level on server. */
#include "rsync.h"
#include "ifuncs.h"
#define PTR_DIFF(p1,p2) ((ptrdiff_t)(((char *)(p1)) - (char *)(p2)))
#define strequal(a,b) (strcasecmp(a,b)==0)
#define BOOLSTR(b) ((b) ? "Yes" : "No")
@@ -61,6 +61,9 @@ typedef char pstring[1024];
#define LOG_DAEMON 0
#endif
#define DEFAULT_DONT_COMPRESS "*.gz *.zip *.z *.rpm *.deb *.iso *.bz2" \
" *.t[gb]z *.7z *.mp[34] *.mov *.avi *.ogg *.jpg *.jpeg"
/* the following are used by loadparm for option lists */
typedef enum
{
@@ -150,6 +153,7 @@ typedef struct
int syslog_facility;
int timeout;
BOOL fake_super;
BOOL ignore_errors;
BOOL ignore_nonreadable;
BOOL list;
@@ -169,7 +173,7 @@ static service sDefault =
{
/* auth_users; */ NULL,
/* comment; */ NULL,
/* dont_compress; */ "*.gz *.tgz *.zip *.z *.rpm *.deb *.iso *.bz2 *.tbz",
/* dont_compress; */ DEFAULT_DONT_COMPRESS,
/* exclude; */ NULL,
/* exclude_from; */ NULL,
/* filter; */ NULL,
@@ -197,6 +201,7 @@ static service sDefault =
/* syslog_facility; */ LOG_DAEMON,
/* timeout; */ 0,
/* fake_super; */ False,
/* ignore_errors; */ False,
/* ignore_nonreadable; */ False,
/* list; */ True,
@@ -298,6 +303,7 @@ static struct parm_struct parm_table[] =
{"dont compress", P_STRING, P_LOCAL, &sDefault.dont_compress, NULL,0},
{"exclude from", P_STRING, P_LOCAL, &sDefault.exclude_from, NULL,0},
{"exclude", P_STRING, P_LOCAL, &sDefault.exclude, NULL,0},
{"fake super", P_BOOL, P_LOCAL, &sDefault.fake_super, NULL,0},
{"filter", P_STRING, P_LOCAL, &sDefault.filter, NULL,0},
{"gid", P_STRING, P_LOCAL, &sDefault.gid, NULL,0},
{"hosts allow", P_STRING, P_LOCAL, &sDefault.hosts_allow, NULL,0},
@@ -412,6 +418,7 @@ FN_LOCAL_INTEGER(lp_max_connections, max_connections)
FN_LOCAL_INTEGER(lp_max_verbosity, max_verbosity)
FN_LOCAL_INTEGER(lp_timeout, timeout)
FN_LOCAL_BOOL(lp_fake_super, fake_super)
FN_LOCAL_BOOL(lp_ignore_errors, ignore_errors)
FN_LOCAL_BOOL(lp_ignore_nonreadable, ignore_nonreadable)
FN_LOCAL_BOOL(lp_list, list)
@@ -524,12 +531,11 @@ static int strwicmp(char *psz1, char *psz2)
/* sync the strings on first non-whitespace */
while (1)
{
while (isspace(* (unsigned char *) psz1))
while (isSpace(psz1))
psz1++;
while (isspace(* (unsigned char *) psz2))
while (isSpace(psz2))
psz2++;
if (toupper(* (unsigned char *) psz1) != toupper(* (unsigned char *) psz2)
|| *psz1 == '\0' || *psz2 == '\0')
if (toUpper(psz1) != toUpper(psz2) || *psz1 == '\0' || *psz2 == '\0')
break;
psz1++;
psz2++;
@@ -803,8 +809,6 @@ static BOOL do_section(char *sectionname)
***************************************************************************/
BOOL lp_load(char *pszFname, int globals_only)
{
extern int am_server;
extern int am_root;
pstring n2;
BOOL bRetval;
@@ -814,12 +818,7 @@ BOOL lp_load(char *pszFname, int globals_only)
init_globals();
if (pszFname)
pstrcpy(n2,pszFname);
else if (am_server && !am_root)
pstrcpy(n2,RSYNCD_USERCONF);
else
pstrcpy(n2,RSYNCD_SYSCONF);
pstrcpy(n2, pszFname);
/* We get sections first, so have to start 'behind' to make up */
iServiceIndex = -1;

260
log.c
View File

@@ -3,11 +3,11 @@
*
* Copyright (C) 1998-2001 Andrew Tridgell <tridge@samba.org>
* Copyright (C) 2000-2001 Martin Pool <mbp@samba.org>
* Copyright (C) 2003, 2004, 2005, 2006 Wayne Davison
* Copyright (C) 2003-2007 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
@@ -16,20 +16,18 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
* with this program; if not, visit the http://fsf.org website.
*/
#include "rsync.h"
#if defined HAVE_ICONV_OPEN && defined HAVE_ICONV_H
#include <iconv.h>
#endif
#include "ifuncs.h"
extern int verbose;
extern int dry_run;
extern int am_daemon;
extern int am_server;
extern int am_sender;
extern int am_generator;
extern int local_server;
extern int quiet;
extern int module_id;
@@ -37,6 +35,8 @@ extern int msg_fd_out;
extern int allow_8bit_chars;
extern int protocol_version;
extern int preserve_times;
extern int uid_ndx;
extern int gid_ndx;
extern int stdout_format_has_i;
extern int stdout_format_has_o_or_i;
extern int logfile_format_has_i;
@@ -46,10 +46,14 @@ extern char *auth_user;
extern char *stdout_format;
extern char *logfile_format;
extern char *logfile_name;
#if defined HAVE_ICONV_OPEN && defined HAVE_ICONV_H
#ifdef ICONV_CONST
extern iconv_t ic_chck;
#endif
#ifdef ICONV_OPTION
extern iconv_t ic_send, ic_recv;
#endif
extern char curr_dir[];
extern char *module_dir;
extern unsigned int module_dirlen;
static int log_initialised;
@@ -103,7 +107,7 @@ static char const *rerr_name(int code)
return NULL;
}
static void logit(int priority, char *buf)
static void logit(int priority, const char *buf)
{
if (logfile_was_closed)
logfile_reopen();
@@ -214,11 +218,11 @@ static void filtered_fwrite(FILE *f, const char *buf, int len, int use_isprint)
for (s = buf; s < end; s++) {
if ((s < end - 4
&& *s == '\\' && s[1] == '#'
&& isdigit(*(uchar*)(s+2))
&& isdigit(*(uchar*)(s+3))
&& isdigit(*(uchar*)(s+4)))
&& isDigit(s + 2)
&& isDigit(s + 3)
&& isDigit(s + 4))
|| (*s != '\t'
&& ((use_isprint && !isprint(*(uchar*)s))
&& ((use_isprint && !isPrint(s))
|| *(uchar*)s < ' '))) {
if (s != buf && fwrite(buf, s - buf, 1, f) != 1)
exit_cleanup(RERR_MESSAGEIO);
@@ -233,17 +237,25 @@ static void filtered_fwrite(FILE *f, const char *buf, int len, int use_isprint)
/* this is the underlying (unformatted) rsync debugging function. Call
* it with FINFO, FERROR or FLOG. Note: recursion can happen with
* certain fatal conditions. */
void rwrite(enum logcode code, char *buf, int len)
void rwrite(enum logcode code, const char *buf, int len, int is_utf8)
{
int trailing_CR_or_NL;
FILE *f = NULL;
#ifdef ICONV_OPTION
iconv_t ic = is_utf8 && ic_recv != (iconv_t)-1 ? ic_recv : ic_chck;
#else
#ifdef ICONV_CONST
iconv_t ic = ic_chck;
#endif
#endif
if (len < 0)
exit_cleanup(RERR_MESSAGEIO);
if (am_server && msg_fd_out >= 0) {
assert(!is_utf8);
/* Pass the message to our sibling. */
send_msg((enum msgcode)code, buf, len);
send_msg((enum msgcode)code, buf, len, 0);
return;
}
@@ -276,7 +288,7 @@ void rwrite(enum logcode code, char *buf, int len)
if (am_server) {
/* Pass the message to the non-server side. */
if (send_msg((enum msgcode)code, buf, len))
if (send_msg((enum msgcode)code, buf, len, !is_utf8))
return;
if (am_daemon) {
/* TODO: can we send the error to the user somehow? */
@@ -299,27 +311,27 @@ void rwrite(enum logcode code, char *buf, int len)
trailing_CR_or_NL = len && (buf[len-1] == '\n' || buf[len-1] == '\r')
? buf[--len] : 0;
#if defined HAVE_ICONV_OPEN && defined HAVE_ICONV_H
if (ic_chck != (iconv_t)-1) {
#ifdef ICONV_CONST
if (ic != (iconv_t)-1) {
xbuf outbuf, inbuf;
char convbuf[1024];
char *in_buf = buf, *out_buf = convbuf;
size_t in_cnt = len, out_cnt = sizeof convbuf - 1;
int ierrno;
iconv(ic_chck, NULL, 0, NULL, 0);
while (iconv(ic_chck, &in_buf,&in_cnt,
&out_buf,&out_cnt) == (size_t)-1) {
if (out_buf != convbuf) {
filtered_fwrite(f, convbuf, out_buf - convbuf, 0);
out_buf = convbuf;
out_cnt = sizeof convbuf - 1;
INIT_CONST_XBUF(outbuf, convbuf);
INIT_XBUF(inbuf, (char*)buf, len, -1);
while (inbuf.len) {
iconvbufs(ic, &inbuf, &outbuf, 0);
ierrno = errno;
if (outbuf.len) {
filtered_fwrite(f, convbuf, outbuf.len, 0);
outbuf.len = 0;
}
if (errno == E2BIG)
if (!ierrno || ierrno == E2BIG)
continue;
fprintf(f, "\\#%03o", *(uchar*)in_buf++);
in_cnt--;
fprintf(f, "\\#%03o", CVAL(inbuf.buf, inbuf.pos++));
inbuf.len--;
}
if (out_buf != convbuf)
filtered_fwrite(f, convbuf, out_buf - convbuf, 0);
} else
#endif
filtered_fwrite(f, buf, len, !allow_8bit_chars);
@@ -368,7 +380,7 @@ void rprintf(enum logcode code, const char *format, ...)
}
}
rwrite(code, buf, len);
rwrite(code, buf, len, 0);
}
/* This is like rprintf, but it also tries to print some
@@ -399,7 +411,7 @@ void rsyserr(enum logcode code, int errcode, const char *format, ...)
if (len >= sizeof buf)
exit_cleanup(RERR_MESSAGEIO);
rwrite(code, buf, len);
rwrite(code, buf, len, 0);
}
void rflush(enum logcode code)
@@ -418,12 +430,14 @@ void rflush(enum logcode code)
}
/* A generic logging routine for send/recv, with parameter substitiution. */
static void log_formatted(enum logcode code, char *format, char *op,
struct file_struct *file, struct stats *initial_stats,
int iflags, char *hlink)
static void log_formatted(enum logcode code, const char *format, const char *op,
struct file_struct *file, const char *fname,
struct stats *initial_stats, int iflags,
const char *hlink)
{
char buf[MAXPATHLEN+1024], buf2[MAXPATHLEN], fmt[32];
char *p, *s, *n;
char *p, *s, *c;
const char *n;
size_t len, total;
int64 b;
@@ -442,14 +456,14 @@ static void log_formatted(enum logcode code, char *format, char *op,
for (p = buf; (p = strchr(p, '%')) != NULL; ) {
s = p++;
n = fmt + 1;
c = fmt + 1;
if (*p == '-')
*n++ = *p++;
while (isdigit(*(uchar*)p) && n - fmt < (int)(sizeof fmt) - 8)
*n++ = *p++;
*c++ = *p++;
while (isDigit(p) && c - fmt < (int)(sizeof fmt) - 8)
*c++ = *p++;
if (!*p)
break;
*n = '\0';
*c = '\0';
n = NULL;
switch (*p) {
@@ -464,22 +478,22 @@ static void log_formatted(enum logcode code, char *format, char *op,
case 'l':
strlcat(fmt, ".0f", sizeof fmt);
snprintf(buf2, sizeof buf2, fmt,
(double)file->length);
(double)F_LENGTH(file));
n = buf2;
break;
case 'U':
strlcat(fmt, "ld", sizeof fmt);
strlcat(fmt, "u", sizeof fmt);
snprintf(buf2, sizeof buf2, fmt,
(long)file->uid);
uid_ndx ? F_OWNER(file) : 0);
n = buf2;
break;
case 'G':
if (file->gid == GID_NONE)
if (!gid_ndx || file->flags & FLAG_SKIP_GROUP)
n = "DEFAULT";
else {
strlcat(fmt, "ld", sizeof fmt);
strlcat(fmt, "u", sizeof fmt);
snprintf(buf2, sizeof buf2, fmt,
(long)file->gid);
F_GROUP(file));
n = buf2;
}
break;
@@ -490,54 +504,65 @@ static void log_formatted(enum logcode code, char *format, char *op,
n = buf2;
break;
case 'M':
n = timestring(file->modtime);
{
char *cp = n;
while ((cp = strchr(cp, ' ')) != NULL)
*cp = '-';
}
n = c = timestring(file->modtime);
while ((c = strchr(p, ' ')) != NULL)
*c = '-';
break;
case 'B':
n = buf2 + MAXPATHLEN - PERMSTRING_SIZE;
permstring(n - 1, file->mode); /* skip the type char */
c = buf2 + MAXPATHLEN - PERMSTRING_SIZE - 1;
permstring(c, file->mode);
n = c + 1; /* skip the type char */
break;
case 'o':
n = op;
break;
case 'f':
n = f_name(file, NULL);
if (am_sender && file->dir.root) {
pathjoin(buf2, sizeof buf2,
file->dir.root, n);
clean_fname(buf2, 0);
if (fmt[1])
strlcpy(n, buf2, MAXPATHLEN);
else
n = buf2;
} else if (*n != '/') {
pathjoin(buf2, sizeof buf2,
curr_dir + module_dirlen, n);
clean_fname(buf2, 0);
if (fmt[1])
strlcpy(n, buf2, MAXPATHLEN);
else
n = buf2;
if (fname) {
c = f_name_buf();
strlcpy(c, fname, MAXPATHLEN);
} else
clean_fname(n, 0);
c = f_name(file, NULL);
if (am_sender && F_PATHNAME(file)) {
pathjoin(buf2, sizeof buf2,
F_PATHNAME(file), c);
clean_fname(buf2, 0);
if (fmt[1]) {
strlcpy(c, buf2, MAXPATHLEN);
n = c;
} else
n = buf2;
} else if (am_daemon && *c != '/') {
pathjoin(buf2, sizeof buf2,
curr_dir + module_dirlen, c);
clean_fname(buf2, 0);
if (fmt[1]) {
strlcpy(c, buf2, MAXPATHLEN);
n = c;
} else
n = buf2;
} else {
clean_fname(c, 0);
n = c;
}
if (*n == '/')
n++;
break;
case 'n':
n = f_name(file, NULL);
if (fname) {
c = f_name_buf();
strlcpy(c, fname, MAXPATHLEN);
} else
c = f_name(file, NULL);
if (S_ISDIR(file->mode))
strlcat(n, "/", MAXPATHLEN);
strlcat(c, "/", MAXPATHLEN);
n = c;
break;
case 'L':
if (hlink && *hlink) {
n = hlink;
strlcpy(buf2, " => ", sizeof buf2);
} else if (S_ISLNK(file->mode) && file->u.link) {
n = file->u.link;
} else if (S_ISLNK(file->mode) && !fname) {
n = F_SYMLINK(file);
strlcpy(buf2, " -> ", sizeof buf2);
} else {
n = "";
@@ -556,7 +581,7 @@ static void log_formatted(enum logcode code, char *format, char *op,
n = timestring(time(NULL));
break;
case 'P':
n = lp_path(module_id);
n = module_dir;
break;
case 'u':
n = auth_user;
@@ -590,40 +615,41 @@ static void log_formatted(enum logcode code, char *format, char *op,
n = "*deleting";
break;
}
n = buf2 + MAXPATHLEN - 32;
n[0] = iflags & ITEM_LOCAL_CHANGE
n = c = buf2 + MAXPATHLEN - 32;
c[0] = iflags & ITEM_LOCAL_CHANGE
? iflags & ITEM_XNAME_FOLLOWS ? 'h' : 'c'
: !(iflags & ITEM_TRANSFER) ? '.'
: !local_server && *op == 's' ? '<' : '>';
n[1] = S_ISDIR(file->mode) ? 'd'
c[1] = S_ISDIR(file->mode) ? 'd'
: IS_SPECIAL(file->mode) ? 'S'
: IS_DEVICE(file->mode) ? 'D'
: S_ISLNK(file->mode) ? 'L' : 'f';
n[2] = !(iflags & ITEM_REPORT_CHECKSUM) ? '.' : 'c';
n[3] = !(iflags & ITEM_REPORT_SIZE) ? '.' : 's';
n[4] = !(iflags & ITEM_REPORT_TIME) ? '.'
c[2] = !(iflags & ITEM_REPORT_CHECKSUM) ? '.' : 'c';
c[3] = !(iflags & ITEM_REPORT_SIZE) ? '.' : 's';
c[4] = !(iflags & ITEM_REPORT_TIME) ? '.'
: !preserve_times || S_ISLNK(file->mode) ? 'T' : 't';
n[5] = !(iflags & ITEM_REPORT_PERMS) ? '.' : 'p';
n[6] = !(iflags & ITEM_REPORT_OWNER) ? '.' : 'o';
n[7] = !(iflags & ITEM_REPORT_GROUP) ? '.' : 'g';
n[8] = '.';
n[9] = '\0';
c[5] = !(iflags & ITEM_REPORT_PERMS) ? '.' : 'p';
c[6] = !(iflags & ITEM_REPORT_OWNER) ? '.' : 'o';
c[7] = !(iflags & ITEM_REPORT_GROUP) ? '.' : 'g';
c[8] = !(iflags & ITEM_REPORT_ATIME) ? '.' : 'u';
c[9] = !(iflags & ITEM_REPORT_ACL) ? '.' : 'a';
c[10] = !(iflags & ITEM_REPORT_XATTR) ? '.' : 'x';
c[11] = '\0';
if (iflags & (ITEM_IS_NEW|ITEM_MISSING_DATA)) {
char ch = iflags & ITEM_IS_NEW ? '+' : '?';
int i;
for (i = 2; n[i]; i++)
n[i] = ch;
} else if (n[0] == '.' || n[0] == 'h'
|| (n[0] == 'c' && n[1] == 'f')) {
for (i = 2; c[i]; i++)
c[i] = ch;
} else if (c[0] == '.' || c[0] == 'h' || c[0] == 'c') {
int i;
for (i = 2; n[i]; i++) {
if (n[i] != '.')
for (i = 2; c[i]; i++) {
if (c[i] != '.')
break;
}
if (!n[i]) {
for (i = 2; n[i]; i++)
n[i] = ' ';
if (!c[i]) {
for (i = 2; c[i]; i++)
c[i] = ' ';
}
}
break;
@@ -662,7 +688,7 @@ static void log_formatted(enum logcode code, char *format, char *op,
p = s + len;
}
rwrite(code, buf, total);
rwrite(code, buf, total, 0);
}
/* Return 1 if the format escape is in the log-format string (e.g. look for
@@ -677,7 +703,7 @@ int log_format_has(const char *format, char esc)
for (p = format; (p = strchr(p, '%')) != NULL; ) {
if (*++p == '-')
p++;
while (isdigit(*(uchar*)p))
while (isDigit(p))
p++;
if (!*p)
break;
@@ -691,22 +717,22 @@ int log_format_has(const char *format, char esc)
* to stdout. If it is FLOG, it just goes to the log file. Otherwise we
* output to both. */
void log_item(enum logcode code, struct file_struct *file,
struct stats *initial_stats, int iflags, char *hlink)
struct stats *initial_stats, int iflags, const char *hlink)
{
char *s_or_r = am_sender ? "send" : "recv";
const char *s_or_r = am_sender ? "send" : "recv";
if (code != FLOG && stdout_format && !am_server) {
log_formatted(FCLIENT, stdout_format, s_or_r,
file, initial_stats, iflags, hlink);
file, NULL, initial_stats, iflags, hlink);
}
if (code != FCLIENT && logfile_format && *logfile_format) {
log_formatted(FLOG, logfile_format, s_or_r,
file, initial_stats, iflags, hlink);
file, NULL, initial_stats, iflags, hlink);
}
}
void maybe_log_item(struct file_struct *file, int iflags, int itemizing,
char *buf)
const char *buf)
{
int significant_flags = iflags & SIGNIFICANT_ITEM_FLAGS;
int see_item = itemizing && (significant_flags || *buf
@@ -723,24 +749,26 @@ void maybe_log_item(struct file_struct *file, int iflags, int itemizing,
}
}
void log_delete(char *fname, int mode)
void log_delete(const char *fname, int mode)
{
static struct file_struct file;
static struct {
union file_extras ex[4]; /* just in case... */
struct file_struct file;
} x;
int len = strlen(fname);
char *fmt;
const char *fmt;
file.mode = mode;
file.basename = fname;
x.file.mode = mode;
if (!verbose && !stdout_format)
;
else if (am_server && protocol_version >= 29 && len < MAXPATHLEN) {
if (S_ISDIR(mode))
len++; /* directories include trailing null */
send_msg(MSG_DELETED, fname, len);
send_msg(MSG_DELETED, fname, len, am_generator);
} else {
fmt = stdout_format_has_o_or_i ? stdout_format : "deleting %n";
log_formatted(FCLIENT, fmt, "del.", &file, &stats,
log_formatted(FCLIENT, fmt, "del.", &x.file, fname, &stats,
ITEM_DELETED, NULL);
}
@@ -748,7 +776,7 @@ void log_delete(char *fname, int mode)
return;
fmt = logfile_format_has_o_or_i ? logfile_format : "deleting %n";
log_formatted(FLOG, fmt, "del.", &file, &stats, ITEM_DELETED, NULL);
log_formatted(FLOG, fmt, "del.", &x.file, fname, &stats, ITEM_DELETED, NULL);
}
/*
@@ -764,7 +792,7 @@ void log_exit(int code, const char *file, int line)
(double)stats.total_written,
(double)stats.total_read,
(double)stats.total_size);
} else {
} else if (am_server != 2) {
const char *name;
name = rerr_name(code);

469
main.c
View File

@@ -4,11 +4,11 @@
* Copyright (C) 1996-2001 Andrew Tridgell <tridge@samba.org>
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
* Copyright (C) 2003, 2004, 2005, 2006 Wayne Davison
* Copyright (C) 2003-2007 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
@@ -17,11 +17,12 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
* with this program; if not, visit the http://fsf.org website.
*/
#include "rsync.h"
#include "ifuncs.h"
#include "io.h"
#if defined CONFIG_LOCALE && defined HAVE_LOCALE_H
#include <locale.h>
#endif
@@ -34,9 +35,9 @@ extern int am_server;
extern int am_sender;
extern int am_generator;
extern int am_daemon;
extern int inc_recurse;
extern int blocking_io;
extern int remove_source_files;
extern int daemon_over_rsh;
extern int need_messages_from_generator;
extern int kluge_around_eof;
extern int do_stats;
@@ -47,7 +48,10 @@ extern int copy_dirlinks;
extern int keep_dirlinks;
extern int preserve_hard_links;
extern int protocol_version;
extern int file_total;
extern int recurse;
extern int xfer_dirs;
extern int protect_args;
extern int relative_paths;
extern int sanitize_paths;
extern int curr_dir_depth;
@@ -58,7 +62,6 @@ extern int whole_file;
extern int read_batch;
extern int write_batch;
extern int batch_fd;
extern int batch_gen_fd;
extern int filesfrom_fd;
extern pid_t cleanup_child_pid;
extern struct stats stats;
@@ -68,13 +71,18 @@ extern char *basis_dir[];
extern char *rsync_path;
extern char *shell_cmd;
extern char *batch_name;
extern char *password_file;
extern char curr_dir[MAXPATHLEN];
extern struct file_list *first_flist;
extern struct filter_list_struct server_filter_list;
#ifdef ICONV_OPTION
extern iconv_t ic_send;
#endif
int local_server = 0;
int new_root_dir = 0;
int daemon_over_rsh = 0;
mode_t orig_umask = 0;
struct file_list *the_file_list;
int batch_gen_fd = -1;
/* There's probably never more than at most 2 outstanding child processes,
* but set it higher, just in case. */
@@ -103,7 +111,11 @@ static void show_malloc_stats(void);
* remember_children(), we succeed instead of returning an error. */
pid_t wait_process(pid_t pid, int *status_ptr, int flags)
{
pid_t waited_pid = waitpid(pid, status_ptr, flags);
pid_t waited_pid;
do {
waited_pid = waitpid(pid, status_ptr, flags);
} while (waited_pid == -1 && errno == EINTR);
if (waited_pid == -1 && errno == ECHILD) {
/* Status of requested child no longer available: check to
@@ -185,12 +197,12 @@ static void handle_stats(int f)
if (am_server) {
if (am_sender) {
write_longint(f, total_read);
write_longint(f, total_written);
write_longint(f, stats.total_size);
write_varlong30(f, total_read, 3);
write_varlong30(f, total_written, 3);
write_varlong30(f, stats.total_size, 3);
if (protocol_version >= 29) {
write_longint(f, stats.flist_buildtime);
write_longint(f, stats.flist_xfertime);
write_varlong30(f, stats.flist_buildtime, 3);
write_varlong30(f, stats.flist_xfertime, 3);
}
}
return;
@@ -203,22 +215,22 @@ static void handle_stats(int f)
else if (!am_sender) {
/* Read the first two in opposite order because the meaning of
* read/write swaps when switching from sender to receiver. */
total_written = read_longint(f);
total_read = read_longint(f);
stats.total_size = read_longint(f);
total_written = read_varlong30(f, 3);
total_read = read_varlong30(f, 3);
stats.total_size = read_varlong30(f, 3);
if (protocol_version >= 29) {
stats.flist_buildtime = read_longint(f);
stats.flist_xfertime = read_longint(f);
stats.flist_buildtime = read_varlong30(f, 3);
stats.flist_xfertime = read_varlong30(f, 3);
}
} else if (write_batch) {
/* The --read-batch process is going to be a client
* receiver, so we need to give it the stats. */
write_longint(batch_fd, total_read);
write_longint(batch_fd, total_written);
write_longint(batch_fd, stats.total_size);
write_varlong30(batch_fd, total_read, 3);
write_varlong30(batch_fd, total_written, 3);
write_varlong30(batch_fd, stats.total_size, 3);
if (protocol_version >= 29) {
write_longint(batch_fd, stats.flist_buildtime);
write_longint(batch_fd, stats.flist_xfertime);
write_varlong30(batch_fd, stats.flist_buildtime, 3);
write_varlong30(batch_fd, stats.flist_xfertime, 3);
}
}
}
@@ -238,7 +250,8 @@ static void output_summary(void)
human_num(stats.literal_data));
rprintf(FINFO,"Matched data: %s bytes\n",
human_num(stats.matched_data));
rprintf(FINFO,"File list size: %d\n", stats.flist_size);
rprintf(FINFO,"File list size: %s\n",
human_num(stats.flist_size));
if (stats.flist_buildtime) {
rprintf(FINFO,
"File list generation time: %.3f seconds\n",
@@ -310,8 +323,8 @@ 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 **remote_argv, int remote_argc,
int *f_in_p, int *f_out_p)
{
int i, argc = 0;
char *args[MAX_ARGS];
@@ -334,10 +347,8 @@ static pid_t do_cmd(char *cmd, char *machine, char *user, char *path,
if (*f == ' ')
continue;
/* Comparison leaves rooms for server_options(). */
if (argc >= MAX_ARGS - MAX_SERVER_ARGS) {
rprintf(FERROR, "internal: args[] overflowed in do_cmd()\n");
exit_cleanup(RERR_SYNTAX);
}
if (argc >= MAX_ARGS - MAX_SERVER_ARGS)
goto arg_overflow;
args[argc++] = t;
while (*f != ' ' || in_quote) {
if (!*f) {
@@ -401,16 +412,23 @@ static pid_t do_cmd(char *cmd, char *machine, char *user, char *path,
server_options(args,&argc);
if (argc >= MAX_ARGS - 2) {
rprintf(FERROR, "internal: args[] overflowed in do_cmd()\n");
exit_cleanup(RERR_SYNTAX);
}
if (argc >= MAX_ARGS - 2)
goto arg_overflow;
}
args[argc++] = ".";
if (!daemon_over_rsh && path && *path)
args[argc++] = path;
if (!daemon_over_rsh) {
while (remote_argc > 0) {
if (argc >= MAX_ARGS - 1) {
arg_overflow:
rprintf(FERROR, "internal: args[] overflowed in do_cmd()\n");
exit_cleanup(RERR_SYNTAX);
}
args[argc++] = *remote_argv++;
remote_argc--;
}
}
args[argc] = NULL;
@@ -427,17 +445,63 @@ static pid_t do_cmd(char *cmd, char *machine, char *user, char *path,
exit_cleanup(RERR_IPC);
}
batch_gen_fd = from_gen_pipe[0];
*f_out = from_gen_pipe[1];
*f_in = batch_fd;
*f_out_p = from_gen_pipe[1];
*f_in_p = batch_fd;
ret = -1; /* no child pid */
#ifdef ICONV_CONST
setup_iconv();
#endif
} else if (local_server) {
/* If the user didn't request --[no-]whole-file, force
* it on, but only if we're not batch processing. */
if (whole_file < 0 && !write_batch)
whole_file = 1;
ret = local_child(argc, args, f_in, f_out, child_main);
} else
ret = piped_child(args,f_in,f_out);
ret = local_child(argc, args, f_in_p, f_out_p, child_main);
#ifdef ICONV_CONST
setup_iconv();
#endif
} else {
#ifdef ICONV_CONST
setup_iconv();
#endif
if (protect_args) {
int fd;
#ifdef ICONV_OPTION
int convert = ic_send != (iconv_t)-1;
xbuf outbuf, inbuf;
if (convert)
alloc_xbuf(&outbuf, 1024);
#endif
ret = piped_child(args, f_in_p, f_out_p);
for (i = 0; args[i]; i++) {} /* find first NULL */
args[i] = "rsync"; /* set a new arg0 */
if (verbose > 1)
print_child_argv("protected args:", args + i + 1);
fd = *f_out_p;
do {
#ifdef ICONV_OPTION
if (convert) {
INIT_XBUF_STRLEN(inbuf, args[i]);
iconvbufs(ic_send, &inbuf, &outbuf,
ICB_EXPAND_OUT | ICB_INCLUDE_BAD | ICB_INCLUDE_INCOMPLETE);
outbuf.buf[outbuf.len] = '\0';
write_buf(fd, outbuf.buf, outbuf.len + 1);
outbuf.len = 0;
} else
#endif
write_buf(fd, args[i], strlen(args[i]) + 1);
} while (args[++i]);
write_byte(fd, 0);
#ifdef ICONV_OPTION
if (convert)
free(outbuf.buf);
#endif
} else
ret = piped_child(args, f_in_p, f_out_p);
}
if (dir)
free(dir);
@@ -470,7 +534,7 @@ static char *get_local_name(struct file_list *flist, char *dest_path)
if (verbose > 2) {
rprintf(FINFO, "get_local_name count=%d %s\n",
flist->count, NS(dest_path));
file_total, NS(dest_path));
}
if (!dest_path || list_only)
@@ -487,14 +551,13 @@ static char *get_local_name(struct file_list *flist, char *dest_path)
}
return NULL;
}
if (flist->count > 1) {
if (file_total > 1) {
rprintf(FERROR,
"ERROR: destination must be a directory when"
" copying more than 1 file\n");
exit_cleanup(RERR_FILESELECT);
}
/* Caution: flist->count could be 0! */
if (flist->count == 1 && S_ISDIR(flist->files[0]->mode)) {
if (file_total == 1 && S_ISDIR(flist->files[0]->mode)) {
rprintf(FERROR,
"ERROR: cannot overwrite non-directory"
" with a directory\n");
@@ -512,7 +575,7 @@ static char *get_local_name(struct file_list *flist, char *dest_path)
/* If we need a destination directory because the transfer is not
* of a single non-directory or the user has requested one via a
* destination path ending in a slash, create one and use mode 1. */
if (flist->count > 1 || (cp && !cp[1])) {
if (file_total > 1 || (cp && !cp[1])) {
/* Lop off the final slash (if any). */
if (cp && !cp[1])
*cp = '\0';
@@ -529,7 +592,9 @@ static char *get_local_name(struct file_list *flist, char *dest_path)
exit_cleanup(RERR_FILEIO);
}
new_root_dir = 1;
if (flist->high >= flist->low
&& strcmp(flist->files[flist->low]->basename, ".") == 0)
flist->files[0]->flags |= FLAG_DIR_CREATED;
if (verbose)
rprintf(FINFO, "created directory %s\n", dest_path);
@@ -603,29 +668,26 @@ static void fix_basis_dirs(void)
}
/* This is only called by the sender. */
static void read_final_goodbye(int f_in, int f_out)
static void read_final_goodbye(int f_in)
{
int i;
int i, iflags, xlen;
uchar fnamecmp_type;
char xname[MAXPATHLEN];
if (protocol_version < 29)
i = read_int(f_in);
else {
while ((i = read_int(f_in)) == the_file_list->count
&& read_shortint(f_in) == ITEM_IS_NEW) {
/* Forward the keep-alive (no-op) to the receiver. */
write_int(f_out, the_file_list->count);
write_shortint(f_out, ITEM_IS_NEW);
}
i = read_ndx_and_attrs(f_in, &iflags, &fnamecmp_type,
xname, &xlen);
}
if (i != -1) {
if (i != NDX_DONE) {
rprintf(FERROR, "Invalid packet at end of run (%d) [%s]\n",
i, who_am_i());
exit_cleanup(RERR_PROTOCOL);
}
}
static void do_server_sender(int f_in, int f_out, int argc, char *argv[])
{
struct file_list *flist;
@@ -666,25 +728,22 @@ static void do_server_sender(int f_in, int f_out, int argc, char *argv[])
}
flist = send_file_list(f_out,argc,argv);
if (!flist || flist->count == 0) {
if (!flist || flist->used == 0)
exit_cleanup(0);
}
the_file_list = flist;
io_start_buffering_in();
io_start_buffering_out();
io_start_buffering_in(f_in);
send_files(flist,f_out,f_in);
send_files(f_in, f_out);
io_flush(FULL_FLUSH);
handle_stats(f_out);
if (protocol_version >= 24)
read_final_goodbye(f_in, f_out);
read_final_goodbye(f_in);
io_flush(FULL_FLUSH);
exit_cleanup(0);
}
static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
static int do_recv(int f_in, int f_out, char *local_name)
{
int pid;
int exit_code = 0;
@@ -694,8 +753,10 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
* points to an identical file won't be replaced by the referent. */
copy_links = copy_dirlinks = 0;
if (preserve_hard_links)
init_hard_links();
#ifdef SUPPORT_HARD_LINKS
if (preserve_hard_links && !inc_recurse)
match_hard_links(first_flist);
#endif
if (fd_pair(error_pipe) < 0) {
rsyserr(FERROR, errno, "pipe failed in do_recv");
@@ -715,26 +776,32 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
close(f_out);
/* we can't let two processes write to the socket at one time */
close_multiplexing_out();
io_end_multiplex_out();
/* set place to send errors */
set_msg_fd_out(error_pipe[1]);
io_start_buffering_out(error_pipe[1]);
recv_files(f_in, flist, local_name);
recv_files(f_in, local_name);
io_flush(FULL_FLUSH);
handle_stats(f_in);
send_msg(MSG_DONE, "", 0);
send_msg(MSG_DONE, "", 1, 0);
write_varlong(error_pipe[1], stats.total_read, 3);
io_flush(FULL_FLUSH);
/* Handle any keep-alive packets from the post-processing work
* that the generator does. */
if (protocol_version >= 29) {
int iflags, xlen;
uchar fnamecmp_type;
char xname[MAXPATHLEN];
kluge_around_eof = -1;
/* This should only get stopped via a USR2 signal. */
while (read_int(f_in) == flist->count
&& read_shortint(f_in) == ITEM_IS_NEW) {}
read_ndx_and_attrs(f_in, &iflags, &fnamecmp_type,
xname, &xlen);
rprintf(FERROR, "Invalid packet at end of run [%s]\n",
who_am_i());
@@ -749,7 +816,8 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
}
am_generator = 1;
close_multiplexing_in();
io_end_multiplex_in();
if (write_batch && !am_server)
stop_write_batch();
@@ -757,17 +825,26 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
if (f_in != f_out)
close(f_in);
io_start_buffering_out();
io_start_buffering_out(f_out);
set_msg_fd_in(error_pipe[0]);
io_start_buffering_in(error_pipe[0]);
generate_files(f_out, flist, local_name);
#ifdef SUPPORT_HARD_LINKS
if (preserve_hard_links && inc_recurse) {
struct file_list *flist;
for (flist = first_flist; flist; flist = flist->next)
match_hard_links(flist);
}
#endif
generate_files(f_out, local_name);
handle_stats(-1);
io_flush(FULL_FLUSH);
if (protocol_version >= 24) {
/* send a final goodbye message */
write_int(f_out, -1);
write_ndx(f_out, NDX_DONE);
}
io_flush(FULL_FLUSH);
@@ -777,8 +854,7 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
return exit_code;
}
static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
static void do_server_recv(int f_in, int f_out, int argc, char *argv[])
{
int exit_code;
struct file_list *flist;
@@ -814,7 +890,10 @@ static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
}
}
io_start_buffering_in();
if (protocol_version >= 30)
io_start_multiplex_in();
else
io_start_buffering_in(f_in);
recv_filter_list(f_in);
if (filesfrom_fd >= 0) {
@@ -828,12 +907,13 @@ static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
}
flist = recv_file_list(f_in);
verbose = save_verbose;
if (!flist) {
rprintf(FERROR,"server_recv: recv_file_list error\n");
exit_cleanup(RERR_FILESELECT);
}
the_file_list = flist;
if (inc_recurse && file_total == 1)
recv_additional_file_list(f_in);
verbose = save_verbose;
if (argc > 0)
local_name = get_local_name(flist,argv[0]);
@@ -868,7 +948,7 @@ static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
}
}
exit_code = do_recv(f_in,f_out,flist,local_name);
exit_code = do_recv(f_in, f_out, local_name);
exit_cleanup(exit_code);
}
@@ -887,9 +967,6 @@ void start_server(int f_in, int f_out, int argc, char *argv[])
io_set_sock_fds(f_in, f_out);
setup_protocol(f_out, f_in);
#if defined HAVE_ICONV_OPEN && defined HAVE_ICONV_H
setup_iconv();
#endif
if (protocol_version >= 23)
io_start_multiplex_out();
@@ -898,12 +975,10 @@ void start_server(int f_in, int f_out, int argc, char *argv[])
keep_dirlinks = 0; /* Must be disabled on the sender. */
if (need_messages_from_generator)
io_start_multiplex_in();
recv_filter_list(f_in);
do_server_sender(f_in, f_out, argc, argv);
} else {
} else
do_server_recv(f_in, f_out, argc, argv);
}
exit_cleanup(0);
}
@@ -926,12 +1001,6 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
io_set_sock_fds(f_in, f_out);
setup_protocol(f_out,f_in);
#if defined HAVE_ICONV_OPEN && defined HAVE_ICONV_H
setup_iconv();
#endif
if (protocol_version >= 23 && !read_batch)
io_start_multiplex_in();
/* We set our stderr file handle to blocking because ssh might have
* set it to non-blocking. This can be particularly troublesome if
@@ -945,7 +1014,10 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
if (am_sender) {
keep_dirlinks = 0; /* Must be disabled on the sender. */
io_start_buffering_out();
if (protocol_version >= 30)
io_start_multiplex_out();
else
io_start_buffering_out(f_out);
if (!filesfrom_host)
set_msg_fd_in(f_in);
send_filter_list(f_out);
@@ -958,14 +1030,16 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
set_msg_fd_in(-1);
if (verbose > 3)
rprintf(FINFO,"file list sent\n");
the_file_list = flist;
if (protocol_version >= 23)
io_start_multiplex_in();
io_flush(NORMAL_FLUSH);
send_files(flist,f_out,f_in);
send_files(f_in, f_out);
io_flush(FULL_FLUSH);
handle_stats(-1);
if (protocol_version >= 24)
read_final_goodbye(f_in, f_out);
read_final_goodbye(f_in);
if (pid != -1) {
if (verbose > 3)
rprintf(FINFO,"client_run waiting on %d\n", (int) pid);
@@ -977,11 +1051,17 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
exit_cleanup(exit_code);
}
if (need_messages_from_generator && !read_batch)
io_start_multiplex_out();
if (!read_batch) {
if (protocol_version >= 23)
io_start_multiplex_in();
if (need_messages_from_generator)
io_start_multiplex_out();
}
if (argc == 0)
if (argc == 0) {
list_only |= 1;
xfer_dirs |= 1;
}
send_filter_list(read_batch ? -1 : f_out);
@@ -993,14 +1073,15 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
if (write_batch && !am_server)
start_write_batch(f_in);
flist = recv_file_list(f_in);
the_file_list = flist;
if (inc_recurse && file_total == 1)
recv_additional_file_list(f_in);
if (flist && flist->count > 0) {
if (flist && flist->used > 0) {
local_name = get_local_name(flist, argv[0]);
fix_basis_dirs();
exit_code2 = do_recv(f_in, f_out, flist, local_name);
exit_code2 = do_recv(f_in, f_out, local_name);
} else {
handle_stats(-1);
output_summary();
@@ -1016,7 +1097,7 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
return MAX(exit_code, exit_code2);
}
static int copy_argv (char *argv[])
static int copy_argv(char *argv[])
{
int i;
@@ -1042,66 +1123,69 @@ static int copy_argv (char *argv[])
**/
static int start_client(int argc, char *argv[])
{
char *p;
char *shell_machine = NULL;
char *shell_path = NULL;
char *shell_user = NULL;
char *p, *shell_machine = NULL, *shell_user = NULL;
char **remote_argv;
int remote_argc;
int f_in, f_out;
int ret;
pid_t pid;
int f_in,f_out;
int rc;
/* Don't clobber argv[] so that ps(1) can still show the right
* command line. */
if ((rc = copy_argv(argv)))
return rc;
if ((ret = copy_argv(argv)) != 0)
return ret;
if (!read_batch) { /* for read_batch, NO source is specified */
shell_path = check_for_hostspec(argv[0], &shell_machine, &rsync_port);
if (shell_path) { /* source is remote */
char *dummy1;
int dummy2;
if (--argc
&& check_for_hostspec(argv[argc], &dummy1, &dummy2)) {
char *path = check_for_hostspec(argv[0], &shell_machine, &rsync_port);
if (path) { /* source is remote */
char *dummy_host;
int dummy_port = 0;
*argv = path;
remote_argv = argv;
remote_argc = argc;
argv += argc - 1;
if (argc == 1 || **argv == ':')
argc = 0; /* no dest arg */
else if (check_for_hostspec(*argv, &dummy_host, &dummy_port)) {
rprintf(FERROR,
"The source and destination cannot both be remote.\n");
exit_cleanup(RERR_SYNTAX);
} else {
remote_argc--; /* don't count dest */
argc = 1;
}
argv++;
if (filesfrom_host && *filesfrom_host
&& strcmp(filesfrom_host, shell_machine) != 0) {
rprintf(FERROR,
"--files-from hostname is not the same as the transfer hostname\n");
exit_cleanup(RERR_SYNTAX);
}
if (rsync_port) {
if (!shell_cmd) {
return start_socket_client(shell_machine,
shell_path,
argc, argv);
}
daemon_over_rsh = 1;
}
am_sender = 0;
if (rsync_port)
daemon_over_rsh = shell_cmd ? 1 : -1;
} else { /* source is local, check dest arg */
am_sender = 1;
if (argc > 1)
if (argc > 1) {
p = argv[--argc];
else {
p = ".";
list_only = 1;
remote_argv = argv + argc;
} else {
static char *dotarg[1] = { "." };
p = dotarg[0];
remote_argv = dotarg;
list_only |= 1;
xfer_dirs |= 1;
}
remote_argc = 1;
shell_path = check_for_hostspec(p, &shell_machine, &rsync_port);
if (shell_path && filesfrom_host && *filesfrom_host
path = check_for_hostspec(p, &shell_machine, &rsync_port);
if (path && filesfrom_host && *filesfrom_host
&& strcmp(filesfrom_host, shell_machine) != 0) {
rprintf(FERROR,
"--files-from hostname is not the same as the transfer hostname\n");
exit_cleanup(RERR_SYNTAX);
}
if (!shell_path) { /* no hostspec found, so src & dest are local */
if (!path) { /* no hostspec found, so src & dest are local */
local_server = 1;
if (filesfrom_host) {
rprintf(FERROR,
@@ -1109,23 +1193,72 @@ static int start_client(int argc, char *argv[])
exit_cleanup(RERR_SYNTAX);
}
shell_machine = NULL;
shell_path = p;
} else if (rsync_port) {
if (!shell_cmd) {
return start_socket_client(shell_machine,
shell_path,
argc, argv);
}
daemon_over_rsh = 1;
} else { /* hostspec was found, so dest is remote */
argv[argc] = path;
if (rsync_port)
daemon_over_rsh = shell_cmd ? 1 : -1;
}
}
} else { /* read_batch */
local_server = 1;
shell_path = argv[argc-1];
if (check_for_hostspec(shell_path, &shell_machine, &rsync_port)) {
if (check_for_hostspec(argv[argc-1], &shell_machine, &rsync_port)) {
rprintf(FERROR, "remote destination is not allowed with --read-batch\n");
exit_cleanup(RERR_SYNTAX);
}
remote_argv = argv + argc - 1;
remote_argc = 1;
}
if (am_sender) {
char *dummy_host;
int dummy_port = rsync_port;
int i;
/* For local source, extra source args must not have hostspec. */
for (i = 1; i < argc; i++) {
if (check_for_hostspec(argv[i], &dummy_host, &dummy_port)) {
rprintf(FERROR, "Unexpected remote arg: %s\n", argv[i]);
exit_cleanup(RERR_SYNTAX);
}
}
} else {
char *dummy_host;
int dummy_port = rsync_port;
int i;
/* For remote source, any extra source args must have either
* the same hostname or an empty hostname. */
for (i = 1; i < remote_argc; i++) {
char *arg = check_for_hostspec(remote_argv[i], &dummy_host, &dummy_port);
if (!arg) {
rprintf(FERROR, "Unexpected local arg: %s\n", remote_argv[i]);
rprintf(FERROR, "If arg is a remote file/dir, prefix it with a colon (:).\n");
exit_cleanup(RERR_SYNTAX);
}
if (*dummy_host && strcmp(dummy_host, shell_machine) != 0) {
rprintf(FERROR, "All source args must come from the same machine.\n");
exit_cleanup(RERR_SYNTAX);
}
if (rsync_port != dummy_port) {
if (!rsync_port || !dummy_port)
rprintf(FERROR, "All source args must use the same hostspec format.\n");
else
rprintf(FERROR, "All source args must use the same port number.\n");
exit_cleanup(RERR_SYNTAX);
}
remote_argv[i] = arg;
}
if (argc == 0) {
list_only |= 1;
xfer_dirs |= 1;
}
}
if (daemon_over_rsh < 0)
return start_socket_client(shell_machine, remote_argc, remote_argv, argc, argv);
if (password_file && !daemon_over_rsh) {
rprintf(FERROR, "The --password-file option may only be "
"used when accessing an rsync daemon.\n");
exit_cleanup(RERR_SYNTAX);
}
if (shell_machine) {
@@ -1139,31 +1272,18 @@ static int start_client(int argc, char *argv[])
if (verbose > 3) {
rprintf(FINFO,"cmd=%s machine=%s user=%s path=%s\n",
shell_cmd ? shell_cmd : "",
shell_machine ? shell_machine : "",
shell_user ? shell_user : "",
shell_path ? shell_path : "");
NS(shell_cmd), NS(shell_machine), NS(shell_user),
remote_argv ? NS(remote_argv[0]) : "");
}
/* for remote source, only single dest arg can remain ... */
if (!am_sender && argc > 1) {
usage(FERROR);
exit_cleanup(RERR_SYNTAX);
}
/* ... or no dest at all */
if (!am_sender && argc == 0)
list_only |= 1;
pid = do_cmd(shell_cmd,shell_machine,shell_user,shell_path,
&f_in,&f_out);
pid = do_cmd(shell_cmd, shell_machine, shell_user, remote_argv, remote_argc,
&f_in, &f_out);
/* if we're running an rsync server on the remote host over a
* remote shell command, we need to do the RSYNCD protocol first */
if (daemon_over_rsh) {
int tmpret;
tmpret = start_inband_exchange(shell_user, shell_path,
f_in, f_out, argc);
tmpret = start_inband_exchange(f_in, f_out, shell_user, remote_argc, remote_argv);
if (tmpret < 0)
return tmpret;
}
@@ -1358,13 +1478,30 @@ int main(int argc,char *argv[])
}
if (read_batch)
read_stream_flags(batch_fd);
else
write_stream_flags(batch_fd);
}
if (write_batch < 0)
dry_run = 1;
if (am_daemon && !am_server)
if (am_server) {
#ifdef ICONV_CONST
setup_iconv();
#endif
} else if (am_daemon)
return daemon_main();
if (am_server && protect_args) {
char buf[MAXPATHLEN];
protect_args = 2;
read_args(STDIN_FILENO, NULL, buf, sizeof buf, 1, &argv, &argc, NULL);
if (!parse_arguments(&argc, (const char ***) &argv, 1)) {
option_error();
exit_cleanup(RERR_SYNTAX);
}
}
if (argc < 1) {
usage(FERROR);
exit_cleanup(RERR_SYNTAX);

56
match.c
View File

@@ -3,11 +3,11 @@
*
* Copyright (C) 1996 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2003, 2004, 2005, 2006 Wayne Davison
* Copyright (C) 2003-2007 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
@@ -16,8 +16,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
* with this program; if not, visit the http://fsf.org website.
*/
#include "rsync.h"
@@ -85,7 +84,7 @@ static OFF_T last_match;
static void matched(int f, struct sum_struct *s, struct map_struct *buf,
OFF_T offset, int32 i)
{
int32 n = offset - last_match; /* max value: block_size (int32) */
int32 n = (int32)(offset - last_match); /* max value: block_size (int32) */
int32 j;
if (verbose > 2 && i >= 0) {
@@ -121,8 +120,8 @@ static void matched(int f, struct sum_struct *s, struct map_struct *buf,
static void hash_search(int f,struct sum_struct *s,
struct map_struct *buf, OFF_T len)
{
OFF_T offset, end, backup;
int32 k, want_i;
OFF_T offset, end;
int32 k, want_i, backup;
char sum2[SUM_LENGTH];
uint32 s1, s2, sum;
int more;
@@ -254,7 +253,7 @@ static void hash_search(int f,struct sum_struct *s,
} while ((i = s->sums[i].chain) >= 0);
null_hash:
backup = offset - last_match;
backup = (int32)(offset - last_match);
/* We sometimes read 1 byte prior to last_match... */
if (backup < 0)
backup = 0;
@@ -304,7 +303,8 @@ 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];
char file_sum[MAX_DIGEST_LEN];
int sum_len;
last_match = 0;
false_alarms = 0;
@@ -314,22 +314,24 @@ void match_sums(int f, struct sum_struct *s, struct map_struct *buf, OFF_T len)
sum_init(checksum_seed);
if (append_mode) {
OFF_T j = 0;
for (j = CHUNK_SIZE; j < s->flength; j += CHUNK_SIZE) {
if (buf && do_progress)
show_progress(last_match, buf->file_size);
sum_update(map_ptr(buf, last_match, CHUNK_SIZE),
CHUNK_SIZE);
last_match = j;
}
if (last_match < s->flength) {
int32 len = s->flength - last_match;
if (buf && do_progress)
show_progress(last_match, buf->file_size);
sum_update(map_ptr(buf, last_match, len), len);
last_match = s->flength;
if (append_mode > 0) {
if (append_mode == 2) {
OFF_T j = 0;
for (j = CHUNK_SIZE; j < s->flength; j += CHUNK_SIZE) {
if (buf && do_progress)
show_progress(last_match, buf->file_size);
sum_update(map_ptr(buf, last_match, CHUNK_SIZE),
CHUNK_SIZE);
last_match = j;
}
if (last_match < s->flength) {
int32 n = (int32)(s->flength - last_match);
if (buf && do_progress)
show_progress(last_match, buf->file_size);
sum_update(map_ptr(buf, last_match, n), n);
}
}
last_match = s->flength;
s->count = 0;
}
@@ -339,7 +341,7 @@ void match_sums(int f, struct sum_struct *s, struct map_struct *buf, OFF_T len)
if (verbose > 2)
rprintf(FINFO,"built hash table\n");
hash_search(f,s,buf,len);
hash_search(f, s, buf, len);
if (verbose > 2)
rprintf(FINFO,"done hash search\n");
@@ -351,14 +353,14 @@ void match_sums(int f, struct sum_struct *s, struct map_struct *buf, OFF_T len)
matched(f, s, buf, len, -1);
}
sum_end(file_sum);
sum_len = sum_end(file_sum);
/* If we had a read error, send a bad checksum. */
if (buf && buf->status != 0)
file_sum[0]++;
if (verbose > 2)
rprintf(FINFO,"sending file_sum\n");
write_buf(f,file_sum,MD4_SUM_LENGTH);
write_buf(f, file_sum, sum_len);
if (verbose > 2)
rprintf(FINFO, "false_alarms=%d hash_hits=%d matches=%d\n",

66
mkrounding.c Normal file
View File

@@ -0,0 +1,66 @@
/*
* A pre-compilation helper program to aid in the creation of rounding.h.
*
* Copyright (C) 2007 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 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, visit the http://fsf.org website.
*/
#include "rsync.h"
struct test1 {
union file_extras extras1[1];
struct {
# include "mkrounding.h"
} file;
};
struct test2 {
union file_extras extras2[2];
struct {
# include "mkrounding.h"
} file;
};
struct test4 {
union file_extras extras4[4];
struct {
# include "mkrounding.h"
} file;
};
#define SIZE_TEST(n) (sizeof (struct test ## n) == EXTRA_LEN * n + sizeof (struct file_struct))
int main(UNUSED(int argc), UNUSED(char *argv[]))
{
int cnt;
if (SIZE_TEST(1))
cnt = 0;
else if (SIZE_TEST(2))
cnt = 1;
else if (SIZE_TEST(4))
cnt = 3;
else {
fprintf(stderr, "Unable to determine required file_extras rounding!\n");
cnt = 3;
}
if (cnt)
fprintf(stderr, "Rounding file_extras in multiples of %d", cnt + 1);
else
fprintf(stderr, "No rounding needed for file_extras");
fprintf(stderr, " (EXTRA_LEN=%d, FILE_STRUCT_LEN=%d)\n",
(int)EXTRA_LEN, (int)FILE_STRUCT_LEN);
printf("#define EXTRA_ROUNDING %d\n", cnt);
return 0;
}

543
options.c
View File

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
Summary: A program for synchronizing files over a network.
Name: rsync
Version: 2.6.9
Version: 3.0.0pre2
Release: 1
Group: Applications/Internet
Source: ftp://rsync.samba.org/pub/rsync/rsync-%{version}.tar.gz

View File

@@ -96,7 +96,15 @@ foreach my $fn (qw( rsync.yo rsyncd.conf.yo )) {
unlink($fn);
}
system "find . -name 'rsync-HEAD-*' -daystart -mtime +14 | xargs rm -f";
my $cnt = 0;
open(PIPE, '-|', 'ls -1t rsync-HEAD-*') or die $!;
while (<PIPE>) {
chomp;
next if $cnt++ < 10;
unlink($_);
}
close PIPE;
system 'ls -ltr';
if ($upload) {

View File

@@ -67,7 +67,7 @@ while (<CVS>) {
chdir('rsync') or die $!;
my($version, $lastversion);
open(IN, 'configure.in') or die $!;
open(IN, '<', 'configure.in') or die $!;
while (<IN>) {
if (/^RSYNC_VERSION=(.*)/) {
$version = $lastversion = $1;
@@ -76,7 +76,13 @@ while (<IN>) {
}
close IN;
$lastversion =~ s/(\d+)cvs$/ $1 - 1 /e;
if ($lastversion =~ /cvs$/) {
open(IN, '<', 'OLDNEWS') or die $!;
$_ = <IN>;
close IN;
($lastversion) = /(\d+\.\d+\.\d+)/;
}
$version =~ s/cvs/pre1/ || $version =~ s/pre(\d+)/ 'pre' . ($1 + 1) /e;
print $break, "\nPlease enter the version number of this release: [$version] ";
@@ -130,8 +136,9 @@ print "\n", $break, <<EOT;
\$release is "$release"
About to:
- make sure that configure, config.h.in, and proto.h are updated
- make sure that SUBPROTOCOL_VERSION is 0$skipping2
- tweak the version in configure.in, configure, and the spec files
- make sure that configure, config.h.in, and proto.h are updated
- tweak NEWS and OLDNEWS to update the release date$skipping2
- tweak the date in the *.yo files and re-generate the man pages
- make sure that the patches dir has been updated
@@ -148,7 +155,7 @@ system "./prepare-source && touch proto.h";
my @tweak_files = ( glob('packaging/*.spec'), glob('packaging/*/*.spec'),
glob('*.yo'), qw( configure.in configure ) );
if ($version !~ /pre/) {
push(@tweak_files, qw( NEWS OLDNEWS ));
push(@tweak_files, qw( rsync.h NEWS OLDNEWS ));
}
foreach my $fn (@tweak_files) {
open(IN, '<', $fn) or die $!;
@@ -165,6 +172,8 @@ foreach my $fn (@tweak_files) {
} elsif ($fn eq 'NEWS') {
s/^(NEWS for rsync \Q$version\E) \(UNRELEASED\)\s*\n/$1 ($today)\n/mi
or die "Couldn't update NEWS file with release date!\n";
} elsif ($fn eq 'rsync.h') {
s/(#define\s+SUBPROTOCOL_VERSION)\s+\d+/$1 0/;
} elsif ($fn eq 'OLDNEWS') {
s/^\t\S\S\s\S\S\S\s\d\d\d\d(\t\Q$version\E)/\t$ztoday$1/m
or die "Couldn't update OLDNEWS file with release date!\n";
@@ -176,8 +185,8 @@ foreach my $fn (@tweak_files) {
close OUT;
}
system "yodl2man -o rsync.1 rsync.yo; ./tweak_manpage_dashes rsync.1";
system "yodl2man -o rsyncd.conf.5 rsyncd.conf.yo; ./tweak_manpage_dashes rsyncd.conf.5";
system "yodl2man -o rsync.1 rsync.yo; ./tweak_manpage rsync.1";
system "yodl2man -o rsyncd.conf.5 rsyncd.conf.yo; ./tweak_manpage rsyncd.conf.5";
mkdir('patches/tmp') or die $!;
system "rsync -a --exclude=patches/ --exclude-from=.cvsignore . patches/tmp/cvsdir/";

View File

@@ -4,7 +4,7 @@
/*
* 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
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
@@ -13,8 +13,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
* with this program; if not, visit the http://fsf.org website.
*/
/* -------------------------------------------------------------------------- **
@@ -75,6 +74,7 @@
*/
#include "rsync.h"
#include "ifuncs.h"
/* -------------------------------------------------------------------------- **
* Constants...
@@ -165,7 +165,7 @@ static int Continuation( char *line, int pos )
*/
{
pos--;
while( (pos >= 0) && isspace(((unsigned char *)line)[pos]) )
while( pos >= 0 && isSpace(line + pos) )
pos--;
return( ((pos >= 0) && ('\\' == line[pos])) ? pos : -1 );
@@ -387,7 +387,7 @@ static BOOL Parameter( FILE *InFile, BOOL (*pfunc)(char *, char *), int c )
c = 0;
else
{
for( end = i; (end >= 0) && isspace(((unsigned char *) bufr)[end]); end-- )
for( end = i; end >= 0 && isSpace(bufr + end); end-- )
;
c = getc( InFile );
}

15
pipe.c
View File

@@ -4,11 +4,11 @@
* Copyright (C) 1996-2000 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
* Copyright (C) 2004, 2005, 2006 Wayne Davison
* Copyright (C) 2004-2007 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
@@ -17,8 +17,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
* with this program; if not, visit the http://fsf.org website.
*/
#include "rsync.h"
@@ -50,9 +49,8 @@ pid_t piped_child(char **command, int *f_in, int *f_out)
int to_child_pipe[2];
int from_child_pipe[2];
if (verbose >= 2) {
print_child_argv(command);
}
if (verbose >= 2)
print_child_argv("opening connection using:", command);
if (fd_pair(to_child_pipe) < 0 || fd_pair(from_child_pipe) < 0) {
rsyserr(FERROR, errno, "pipe");
@@ -146,6 +144,9 @@ pid_t local_child(int argc, char **argv, int *f_in, int *f_out,
close(to_child_pipe[0]);
if (from_child_pipe[1] != STDOUT_FILENO)
close(from_child_pipe[1]);
#ifdef ICONV_CONST
setup_iconv();
#endif
child_main(argc, argv);
}

View File

@@ -2,18 +2,20 @@
* \file popt/findme.c
*/
/* (C) 1998-2000 Red Hat, Inc. -- Licensing details are in the COPYING
/* (C) 1998-2002 Red Hat, Inc. -- Licensing details are in the COPYING
file accompanying popt source distributions, available from
ftp://ftp.rpm.org/pub/rpm/dist. */
#include "system.h"
#include "findme.h"
const char * findProgramPath(const char * argv0) {
const char * findProgramPath(const char * argv0)
{
char * path = getenv("PATH");
char * pathbuf;
char * start, * chptr;
char * buf;
size_t bufsize;
if (argv0 == NULL) return NULL; /* XXX can't happen */
/* If there is a / in the argv[0], it has to be an absolute path */
@@ -22,17 +24,20 @@ const char * findProgramPath(const char * argv0) {
if (path == NULL) return NULL;
start = pathbuf = alloca(strlen(path) + 1);
buf = malloc(strlen(path) + strlen(argv0) + sizeof("/"));
bufsize = strlen(path) + 1;
start = pathbuf = alloca(bufsize);
if (pathbuf == NULL) return NULL; /* XXX can't happen */
strlcpy(pathbuf, path, bufsize);
bufsize += sizeof "/" - 1 + strlen(argv0);
buf = malloc(bufsize);
if (buf == NULL) return NULL; /* XXX can't happen */
strcpy(pathbuf, path);
chptr = NULL;
/*@-branchstate@*/
do {
if ((chptr = strchr(start, ':')))
*chptr = '\0';
sprintf(buf, "%s/%s", start, argv0);
snprintf(buf, bufsize, "%s/%s", start, argv0);
if (!access(buf, X_OK))
return buf;

View File

@@ -2,7 +2,7 @@
* \file popt/popt.c
*/
/* (C) 19982000 Red Hat, Inc. -- Licensing details are in the COPYING
/* (C) 1998-2002 Red Hat, Inc. -- Licensing details are in the COPYING
file accompanying popt source distributions, available from
ftp://ftp.rpm.org/pub/rpm/dist */
@@ -18,8 +18,18 @@
#include "findme.h"
#include "poptint.h"
#ifndef HAVE_STRERROR
static char * strerror(int errno) {
#ifndef DBL_EPSILON
#define DBL_EPSILON 2.2204460492503131e-16
#endif
#ifdef MYDEBUG
/*@unchecked@*/
int _popt_debug = 0;
#endif
#if !defined(HAVE_STRERROR) && !defined(__LCLINT__)
static char * strerror(int errno)
{
extern int sys_nerr;
extern char * sys_errlist[];
@@ -31,7 +41,8 @@ static char * strerror(int errno) {
#endif
#ifdef MYDEBUG
/*@unused@*/ static void prtcon(const char *msg, poptContext con)
/*@unused@*/
static void prtcon(const char *msg, poptContext con)
{
if (msg) fprintf(stderr, "%s", msg);
fprintf(stderr, "\tcon %p os %p nextCharArg \"%s\" nextArg \"%s\" argv[%d] \"%s\"\n",
@@ -49,7 +60,7 @@ void poptSetExecPath(poptContext con, const char * path, int allowAbsolute)
con->execPath = _free(con->execPath);
con->execPath = xstrdup(path);
con->execAbsolute = allowAbsolute;
/*@-nullstate@*/ /* LCL: con->execPath can be NULL? */
/*@-nullstate@*/ /* LCL: con->execPath not NULL */
return;
/*@=nullstate@*/
}
@@ -62,17 +73,22 @@ static void invokeCallbacksPRE(poptContext con, const struct poptOption * opt)
for (; opt->longName || opt->shortName || opt->arg; opt++) {
if (opt->arg == NULL) continue; /* XXX program error. */
if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
void * arg = opt->arg;
/*@-branchstate@*/
/* XXX sick hack to preserve pretense of ABI. */
if (arg == poptHelpOptions) arg = poptHelpOptionsI18N;
/*@=branchstate@*/
/* Recurse on included sub-tables. */
invokeCallbacksPRE(con, opt->arg);
invokeCallbacksPRE(con, arg);
} else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_CALLBACK &&
(opt->argInfo & POPT_CBFLAG_PRE))
{ /*@-castfcnptr@*/
poptCallbackType cb = (poptCallbackType)opt->arg;
/*@=castfcnptr@*/
/* Perform callback. */
/*@-moduncon -noeffectuncon @*/
/*@-noeffectuncon @*/
cb(con, POPT_CALLBACK_REASON_PRE, NULL, NULL, opt->descrip);
/*@=moduncon =noeffectuncon @*/
/*@=noeffectuncon @*/
}
}
}
@@ -85,17 +101,22 @@ static void invokeCallbacksPOST(poptContext con, const struct poptOption * opt)
for (; opt->longName || opt->shortName || opt->arg; opt++) {
if (opt->arg == NULL) continue; /* XXX program error. */
if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
void * arg = opt->arg;
/*@-branchstate@*/
/* XXX sick hack to preserve pretense of ABI. */
if (arg == poptHelpOptions) arg = poptHelpOptionsI18N;
/*@=branchstate@*/
/* Recurse on included sub-tables. */
invokeCallbacksPOST(con, opt->arg);
invokeCallbacksPOST(con, arg);
} else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_CALLBACK &&
(opt->argInfo & POPT_CBFLAG_POST))
{ /*@-castfcnptr@*/
poptCallbackType cb = (poptCallbackType)opt->arg;
/*@=castfcnptr@*/
/* Perform callback. */
/*@-moduncon -noeffectuncon @*/
/*@-noeffectuncon @*/
cb(con, POPT_CALLBACK_REASON_POST, NULL, NULL, opt->descrip);
/*@=moduncon =noeffectuncon @*/
/*@=noeffectuncon @*/
}
}
}
@@ -112,6 +133,11 @@ static void invokeCallbacksOPTION(poptContext con,
if (opt != NULL)
for (; opt->longName || opt->shortName || opt->arg; opt++) {
if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
void * arg = opt->arg;
/*@-branchstate@*/
/* XXX sick hack to preserve pretense of ABI. */
if (arg == poptHelpOptions) arg = poptHelpOptionsI18N;
/*@=branchstate@*/
/* Recurse on included sub-tables. */
if (opt->arg != NULL) /* XXX program error */
invokeCallbacksOPTION(con, opt->arg, myOpt, myData, shorty);
@@ -133,10 +159,10 @@ static void invokeCallbacksOPTION(poptContext con,
const void * cbData = (cbopt->descrip ? cbopt->descrip : myData);
/* Perform callback. */
if (cb != NULL) { /* XXX program error */
/*@-moduncon -noeffectuncon @*/
/*@-noeffectuncon @*/
cb(con, POPT_CALLBACK_REASON_OPTION, myOpt,
con->os->nextArg, cbData);
/*@=moduncon =noeffectuncon @*/
/*@=noeffectuncon @*/
}
/* Terminate (unless explcitly continuing). */
if (!(cbopt->argInfo & POPT_CBFLAG_CONTINUE))
@@ -181,8 +207,12 @@ poptContext poptGetContext(const char * name, int argc, const char ** argv,
con->flags |= POPT_CONTEXT_POSIXMEHARDER;
if (name) {
char * t = malloc(strlen(name) + 1);
if (t) con->appName = strcpy(t, name);
size_t bufsize = strlen(name) + 1;
char * t = malloc(bufsize);
if (t) {
strlcpy(t, name, bufsize);
con->appName = t;
}
}
/*@-internalglobs@*/
@@ -202,6 +232,7 @@ static void cleanOSE(/*@special@*/ struct optionStackEntry *os)
os->argb = PBM_FREE(os->argb);
}
/*@-boundswrite@*/
void poptResetContext(poptContext con)
{
int i;
@@ -222,10 +253,11 @@ void poptResetContext(poptContext con)
con->doExec = NULL;
if (con->finalArgv != NULL)
for (i = 0; i < con->finalArgvCount; i++)
for (i = 0; i < con->finalArgvCount; i++) {
/*@-unqualifiedtrans@*/ /* FIX: typedef double indirection. */
con->finalArgv[i] = _free(con->finalArgv[i]);
/*@=unqualifiedtrans@*/
}
con->finalArgvCount = 0;
con->arg_strip = PBM_FREE(con->arg_strip);
@@ -233,8 +265,10 @@ void poptResetContext(poptContext con)
return;
/*@=nullstate@*/
}
/*@=boundswrite@*/
/* Only one of longName, shortName should be set, not both. */
/*@-boundswrite@*/
static int handleExec(/*@special@*/ poptContext con,
/*@null@*/ const char * longName, char shortName)
/*@uses con->execs, con->numExecs, con->flags, con->doExec,
@@ -277,12 +311,13 @@ static int handleExec(/*@special@*/ poptContext con,
i = con->finalArgvCount++;
if (con->finalArgv != NULL) /* XXX can't happen */
{ char *s = malloc((longName ? strlen(longName) : 0) + 3);
{ size_t bufsize = (longName ? strlen(longName) : 0) + 3;
char *s = malloc(bufsize);
if (s != NULL) { /* XXX can't happen */
if (longName)
sprintf(s, "--%s", longName);
snprintf(s, bufsize, "--%s", longName);
else
sprintf(s, "-%c", shortName);
snprintf(s, bufsize, "-%c", shortName);
con->finalArgv[i] = s;
} else
con->finalArgv[i] = NULL;
@@ -292,11 +327,12 @@ static int handleExec(/*@special@*/ poptContext con,
return 1;
/*@=nullstate@*/
}
/*@=boundswrite@*/
/* Only one of longName, shortName may be set at a time */
static int handleAlias(/*@special@*/ poptContext con,
/*@null@*/ const char * longName, char shortName,
/*@keep@*/ /*@null@*/ const char * nextCharArg)
/*@exposed@*/ /*@null@*/ const char * nextCharArg)
/*@uses con->aliases, con->numAliases, con->optionStack, con->os,
con->os->currAlias, con->os->currAlias->option.longName @*/
/*@modifies con @*/
@@ -330,8 +366,10 @@ static int handleAlias(/*@special@*/ poptContext con,
if ((con->os - con->optionStack + 1) == POPT_OPTION_DEPTH)
return POPT_ERROR_OPTSTOODEEP;
/*@-boundsread@*/
if (nextCharArg && *nextCharArg)
con->os->nextCharArg = nextCharArg;
/*@=boundsread@*/
con->os++;
con->os->next = 0;
@@ -346,13 +384,14 @@ static int handleAlias(/*@special@*/ poptContext con,
return (rc ? rc : 1);
}
/*@-bounds -boundswrite @*/
static int execCommand(poptContext con)
/*@*/
/*@globals internalState @*/
/*@modifies internalState @*/
{
poptItem item = con->doExec;
const char ** argv;
int argc = 0;
int rc;
if (item == NULL) /*XXX can't happen*/
return POPT_ERROR_NOARG;
@@ -363,15 +402,15 @@ static int execCommand(poptContext con)
argv = malloc(sizeof(*argv) *
(6 + item->argc + con->numLeftovers + con->finalArgvCount));
if (argv == NULL) return POPT_ERROR_MALLOC; /* XXX can't happen */
if (argv == NULL) return POPT_ERROR_MALLOC;
if (!strchr(item->argv[0], '/') && con->execPath) {
char *s = alloca(strlen(con->execPath) + strlen(item->argv[0]) + sizeof("/"));
sprintf(s, "%s/%s", con->execPath, item->argv[0]);
if (!strchr(item->argv[0], '/') && con->execPath != NULL) {
size_t bufsize = strlen(con->execPath) + strlen(item->argv[0]) + sizeof "/";
char *s = alloca(bufsize);
snprintf(s, bufsize, "%s/%s", con->execPath, item->argv[0]);
argv[argc] = s;
} else {
} else
argv[argc] = findProgramPath(item->argv[0]);
}
if (argv[argc++] == NULL) return POPT_ERROR_NOARG;
if (item->argc > 1) {
@@ -386,16 +425,16 @@ static int execCommand(poptContext con)
}
if (con->leftovers != NULL && con->numLeftovers > 0) {
#if 0
argv[argc++] = "--";
#endif
memcpy(argv + argc, con->leftovers, sizeof(*argv) * con->numLeftovers);
argc += con->numLeftovers;
}
argv[argc] = NULL;
{
#ifdef __hpux
int rc = setresgid(getgid(), getgid(),-1);
if (rc) return POPT_ERROR_ERRNO;
rc = setresuid(getuid(), getuid(),-1);
if (rc) return POPT_ERROR_ERRNO;
#else
@@ -405,19 +444,26 @@ static int execCommand(poptContext con)
* XXX from Norbert Warmuth <nwarmuth@privat.circular.de>
*/
#if defined(HAVE_SETUID)
int rc = setgid(getgid());
if (rc) return POPT_ERROR_ERRNO;
rc = setuid(getuid());
if (rc) return POPT_ERROR_ERRNO;
#elif defined (HAVE_SETREUID)
rc = setreuid(getuid(), getuid()); /*hlauer: not portable to hpux9.01 */
int rc = setregid(getgid(), getgid());
if (rc) return POPT_ERROR_ERRNO;
rc = setreuid(getuid(), getuid());
if (rc) return POPT_ERROR_ERRNO;
#else
; /* Can't drop privileges */
#endif
#endif
}
if (argv[0] == NULL)
return POPT_ERROR_NOARG;
#ifdef MYDEBUG
#ifdef MYDEBUG
if (_popt_debug)
{ const char ** avp;
fprintf(stderr, "==> execvp(%s) argv[%d]:", argv[0], argc);
for (avp = argv; *avp; avp++)
@@ -426,10 +472,13 @@ static int execCommand(poptContext con)
}
#endif
rc = execvp(argv[0], (char *const *)argv);
execvp(argv[0], (char *const *)argv);
return POPT_ERROR_ERRNO;
}
/*@=bounds =boundswrite @*/
/*@-boundswrite@*/
/*@observer@*/ /*@null@*/ static const struct poptOption *
findOption(const struct poptOption * opt, /*@null@*/ const char * longName,
char shortName,
@@ -448,10 +497,15 @@ findOption(const struct poptOption * opt, /*@null@*/ const char * longName,
if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
const struct poptOption * opt2;
void * arg = opt->arg;
/*@-branchstate@*/
/* XXX sick hack to preserve pretense of ABI. */
if (arg == poptHelpOptions) arg = poptHelpOptionsI18N;
/*@=branchstate@*/
/* Recurse on included sub-tables. */
if (opt->arg == NULL) continue; /* XXX program error */
opt2 = findOption(opt->arg, longName, shortName, callback,
if (arg == NULL) continue; /* XXX program error */
opt2 = findOption(arg, longName, shortName, callback,
callbackData, singleDash);
if (opt2 == NULL) continue;
/* Sub-table data will be inheirited if no data yet. */
@@ -496,6 +550,7 @@ findOption(const struct poptOption * opt, /*@null@*/ const char * longName,
return opt;
}
/*@=boundswrite@*/
static const char * findNextArg(/*@special@*/ poptContext con,
unsigned argx, int delete_arg)
@@ -534,6 +589,7 @@ static const char * findNextArg(/*@special@*/ poptContext con,
return arg;
}
/*@-boundswrite@*/
static /*@only@*/ /*@null@*/ const char *
expandNextArg(/*@special@*/ poptContext con, const char * s)
/*@uses con->optionStack, con->os,
@@ -541,7 +597,7 @@ expandNextArg(/*@special@*/ poptContext con, const char * s)
/*@modifies con @*/
{
const char * a = NULL;
size_t alen;
size_t alen, pos;
char *t, *te;
size_t tn = strlen(s) + 1;
char c;
@@ -567,9 +623,9 @@ expandNextArg(/*@special@*/ poptContext con, const char * s)
alen = strlen(a);
tn += alen;
*te = '\0';
pos = te - t;
t = realloc(t, tn);
te = t + strlen(t);
te = t + pos;
strncpy(te, a, alen); te += alen;
continue;
/*@notreached@*/ /*@switchbreak@*/ break;
@@ -582,6 +638,7 @@ expandNextArg(/*@special@*/ poptContext con, const char * s)
t = realloc(t, strlen(t) + 1); /* XXX memory leak, hard to plug */
return t;
}
/*@=boundswrite@*/
static void poptStripArg(/*@special@*/ poptContext con, int which)
/*@uses con->arg_strip, con->optionStack @*/
@@ -599,26 +656,26 @@ static void poptStripArg(/*@special@*/ poptContext con, int which)
/*@=compdef@*/
}
static int poptSaveLong(const struct poptOption * opt, long aLong)
/*@modifies opt->arg @*/
int poptSaveLong(long * arg, int argInfo, long aLong)
{
if (opt->arg == NULL)
/* XXX Check alignment, may fail on funky platforms. */
if (arg == NULL || (((unsigned long)arg) & (sizeof(*arg)-1)))
return POPT_ERROR_NULLARG;
if (opt->argInfo & POPT_ARGFLAG_NOT)
if (argInfo & POPT_ARGFLAG_NOT)
aLong = ~aLong;
switch (opt->argInfo & POPT_ARGFLAG_LOGICALOPS) {
switch (argInfo & POPT_ARGFLAG_LOGICALOPS) {
case 0:
*((long *) opt->arg) = aLong;
*arg = aLong;
break;
case POPT_ARGFLAG_OR:
*((long *) opt->arg) |= aLong;
*arg |= aLong;
break;
case POPT_ARGFLAG_AND:
*((long *) opt->arg) &= aLong;
*arg &= aLong;
break;
case POPT_ARGFLAG_XOR:
*((long *) opt->arg) ^= aLong;
*arg ^= aLong;
break;
default:
return POPT_ERROR_BADOPERATION;
@@ -627,26 +684,26 @@ static int poptSaveLong(const struct poptOption * opt, long aLong)
return 0;
}
static int poptSaveInt(const struct poptOption * opt, long aLong)
/*@modifies opt->arg @*/
int poptSaveInt(/*@null@*/ int * arg, int argInfo, long aLong)
{
if (opt->arg == NULL)
/* XXX Check alignment, may fail on funky platforms. */
if (arg == NULL || (((unsigned long)arg) & (sizeof(*arg)-1)))
return POPT_ERROR_NULLARG;
if (opt->argInfo & POPT_ARGFLAG_NOT)
if (argInfo & POPT_ARGFLAG_NOT)
aLong = ~aLong;
switch (opt->argInfo & POPT_ARGFLAG_LOGICALOPS) {
switch (argInfo & POPT_ARGFLAG_LOGICALOPS) {
case 0:
*((int *) opt->arg) = aLong;
*arg = aLong;
break;
case POPT_ARGFLAG_OR:
*((int *) opt->arg) |= aLong;
*arg |= aLong;
break;
case POPT_ARGFLAG_AND:
*((int *) opt->arg) &= aLong;
*arg &= aLong;
break;
case POPT_ARGFLAG_XOR:
*((int *) opt->arg) ^= aLong;
*arg ^= aLong;
break;
default:
return POPT_ERROR_BADOPERATION;
@@ -655,6 +712,7 @@ static int poptSaveInt(const struct poptOption * opt, long aLong)
return 0;
}
/*@-boundswrite@*/
/* returns 'val' element, -1 on last item, POPT_ERROR_* on error */
int poptGetNextOpt(poptContext con)
{
@@ -714,8 +772,12 @@ int poptGetNextOpt(poptContext con)
}
/* Make a copy we can hack at */
localOptString = optString =
strcpy(alloca(strlen(origOptString) + 1), origOptString);
{ size_t bufsize = strlen(origOptString) + 1;
localOptString = optString = alloca(bufsize);
if (optString == NULL) /* XXX can't happen */
return POPT_ERROR_BADOPT;
strlcpy(optString, origOptString, bufsize);
}
if (optString[0] == '\0')
return POPT_ERROR_BADOPT;
@@ -800,11 +862,11 @@ int poptGetNextOpt(poptContext con)
if (opt == NULL) return POPT_ERROR_BADOPT; /* XXX can't happen */
if (opt->arg && (opt->argInfo & POPT_ARG_MASK) == POPT_ARG_NONE) {
if (poptSaveInt(opt, 1L))
if (poptSaveInt((int *)opt->arg, opt->argInfo, 1L))
return POPT_ERROR_BADOPERATION;
} else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_VAL) {
if (opt->arg) {
if (poptSaveInt(opt, (long)opt->val))
if (poptSaveInt((int *)opt->arg, opt->argInfo, (long)opt->val))
return POPT_ERROR_BADOPERATION;
}
} else if ((opt->argInfo & POPT_ARG_MASK) != POPT_ARG_NONE) {
@@ -873,12 +935,12 @@ int poptGetNextOpt(poptContext con)
if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_LONG) {
if (aLong == LONG_MIN || aLong == LONG_MAX)
return POPT_ERROR_OVERFLOW;
if (poptSaveLong(opt, aLong))
if (poptSaveLong((long *)opt->arg, opt->argInfo, aLong))
return POPT_ERROR_BADOPERATION;
} else {
if (aLong > INT_MAX || aLong < INT_MIN)
return POPT_ERROR_OVERFLOW;
if (poptSaveInt(opt, aLong))
if (poptSaveInt((int *)opt->arg, opt->argInfo, aLong))
return POPT_ERROR_BADOPERATION;
}
} /*@switchbreak@*/ break;
@@ -904,9 +966,6 @@ int poptGetNextOpt(poptContext con)
if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_DOUBLE) {
*((double *) opt->arg) = aDouble;
} else {
#ifndef DBL_EPSILON
#define DBL_EPSILON 2.2204460492503131e-16
#endif
#define MY_ABS(a) ((((a) - 0.0) < DBL_EPSILON) ? -(a) : (a))
if ((MY_ABS(aDouble) - FLT_MAX) > DBL_EPSILON)
return POPT_ERROR_OVERFLOW;
@@ -939,14 +998,15 @@ int poptGetNextOpt(poptContext con)
}
if (con->finalArgv != NULL)
{ char *s = malloc((opt->longName ? strlen(opt->longName) : 0) + 3);
{ ssize_t bufsize = (opt->longName ? strlen(opt->longName) : 0) + 3;
char *s = malloc(bufsize);
if (s != NULL) { /* XXX can't happen */
if (opt->longName)
sprintf(s, "%s%s",
snprintf(s, bufsize, "%s%s",
((opt->argInfo & POPT_ARGFLAG_ONEDASH) ? "-" : "--"),
opt->longName);
else
sprintf(s, "-%c", opt->shortName);
snprintf(s, bufsize, "-%c", opt->shortName);
con->finalArgv[con->finalArgvCount++] = s;
} else
con->finalArgv[con->finalArgvCount++] = NULL;
@@ -967,6 +1027,7 @@ int poptGetNextOpt(poptContext con)
return (opt ? opt->val : -1); /* XXX can't happen */
}
/*@=boundswrite@*/
const char * poptGetOptArg(poptContext con)
{
@@ -996,6 +1057,7 @@ const char * poptPeekArg(poptContext con)
return ret;
}
/*@-boundswrite@*/
const char ** poptGetArgs(poptContext con)
{
if (con == NULL ||
@@ -1009,6 +1071,7 @@ const char ** poptGetArgs(poptContext con)
return (con->leftovers + con->nextLeftover);
/*@=nullret =nullstate @*/
}
/*@=boundswrite@*/
poptContext poptFreeContext(poptContext con)
{
@@ -1071,6 +1134,7 @@ int poptAddAlias(poptContext con, struct poptAlias alias,
return poptAddItem(con, item, 0);
}
/*@-boundswrite@*/
/*@-mustmod@*/ /* LCL: con not modified? */
int poptAddItem(poptContext con, poptItem newItem, int flags)
{
@@ -1115,6 +1179,7 @@ int poptAddItem(poptContext con, poptItem newItem, int flags)
return 0;
}
/*@=mustmod@*/
/*@=boundswrite@*/
const char * poptBadOption(poptContext con, int flags)
{
@@ -1184,6 +1249,7 @@ const char * poptGetInvocationName(poptContext con)
return (con->os->argv ? con->os->argv[0] : "");
}
/*@-boundswrite@*/
int poptStrippedArgv(poptContext con, int argc, char ** argv)
{
int numargs = argc;
@@ -1207,3 +1273,4 @@ int poptStrippedArgv(poptContext con, int argc, char ** argv)
return numargs;
}
/*@=boundswrite@*/

View File

@@ -112,33 +112,42 @@
/** \ingroup popt
*/
struct poptOption {
/*@observer@*/ /*@null@*/ const char * longName; /*!< may be NULL */
char shortName; /*!< may be '\0' */
/*@observer@*/ /*@null@*/
const char * longName; /*!< may be NULL */
char shortName; /*!< may be NUL */
int argInfo;
/*@shared@*/ /*@null@*/ void * arg; /*!< depends on argInfo */
/*@shared@*/ /*@null@*/
void * arg; /*!< depends on argInfo */
int val; /*!< 0 means don't return, just update flag */
/*@observer@*/ /*@null@*/ const char * descrip; /*!< description for autohelp -- may be NULL */
/*@observer@*/ /*@null@*/ const char * argDescrip; /*!< argument description for autohelp */
/*@observer@*/ /*@null@*/
const char * descrip; /*!< description for autohelp -- may be NULL */
/*@observer@*/ /*@null@*/
const char * argDescrip; /*!< argument description for autohelp */
};
/** \ingroup popt
* A popt alias argument for poptAddAlias().
*/
struct poptAlias {
/*@owned@*/ /*@null@*/ const char * longName; /*!< may be NULL */
char shortName; /*!< may be '\0' */
/*@owned@*/ /*@null@*/
const char * longName; /*!< may be NULL */
char shortName; /*!< may be NUL */
int argc;
/*@owned@*/ const char ** argv; /*!< must be free()able */
/*@owned@*/
const char ** argv; /*!< must be free()able */
};
/** \ingroup popt
* A popt alias or exec argument for poptAddItem().
*/
/*@-exporttype@*/
typedef struct poptItem_s {
struct poptOption option; /*!< alias/exec name(s) and description. */
int argc; /*!< (alias) no. of args. */
/*@owned@*/ const char ** argv; /*!< (alias) args, must be free()able. */
/*@owned@*/
const char ** argv; /*!< (alias) args, must be free()able. */
} * poptItem;
/*@=exporttype@*/
/** \ingroup popt
* \name Auto-generated help/usage
@@ -148,16 +157,26 @@ typedef struct poptItem_s {
/**
* Empty table marker to enable displaying popt alias/exec options.
*/
/*@observer@*/ /*@checked@*/
/*@-exportvar@*/
/*@unchecked@*/ /*@observer@*/
extern struct poptOption poptAliasOptions[];
/*@=exportvar@*/
#define POPT_AUTOALIAS { NULL, '\0', POPT_ARG_INCLUDE_TABLE, poptAliasOptions, \
0, "Options implemented via popt alias/exec:", NULL },
/**
* Auto help table options.
*/
/*@observer@*/ /*@checked@*/
/*@-exportvar@*/
/*@unchecked@*/ /*@observer@*/
extern struct poptOption poptHelpOptions[];
/*@=exportvar@*/
/*@-exportvar@*/
/*@unchecked@*/ /*@observer@*/
extern struct poptOption * poptHelpOptionsI18N;
/*@=exportvar@*/
#define POPT_AUTOHELP { NULL, '\0', POPT_ARG_INCLUDE_TABLE, poptHelpOptions, \
0, "Help options:", NULL },
@@ -166,19 +185,25 @@ extern struct poptOption poptHelpOptions[];
/** \ingroup popt
*/
/*@-exporttype@*/
typedef /*@abstract@*/ struct poptContext_s * poptContext;
/*@=exporttype@*/
/** \ingroup popt
*/
#ifndef __cplusplus
/*@-typeuse@*/
/*@-exporttype -typeuse@*/
typedef struct poptOption * poptOption;
/*@=typeuse@*/
/*@=exporttype =typeuse@*/
#endif
enum poptCallbackReason { POPT_CALLBACK_REASON_PRE,
POPT_CALLBACK_REASON_POST,
POPT_CALLBACK_REASON_OPTION };
/*@-exportconst@*/
enum poptCallbackReason {
POPT_CALLBACK_REASON_PRE = 0,
POPT_CALLBACK_REASON_POST = 1,
POPT_CALLBACK_REASON_OPTION = 2
};
/*@=exportconst@*/
#ifdef __cplusplus
extern "C" {
@@ -198,18 +223,20 @@ typedef void (*poptCallbackType) (poptContext con,
/*@null@*/ const struct poptOption * opt,
/*@null@*/ const char * arg,
/*@null@*/ const void * data)
/*@*/;
/*@globals internalState @*/
/*@modifies internalState @*/;
/** \ingroup popt
* Initialize popt context.
* @param name
* @param name context name (usually argv[0] program name)
* @param argc no. of arguments
* @param argv argument array
* @param options address of popt option table
* @param flags or'd POPT_CONTEXT_* bits
* @return initialized popt context
*/
/*@only@*/ /*@null@*/ poptContext poptGetContext(
/*@only@*/ /*@null@*/
poptContext poptGetContext(
/*@dependent@*/ /*@keep@*/ const char * name,
int argc, /*@dependent@*/ /*@keep@*/ const char ** argv,
/*@dependent@*/ /*@keep@*/ const struct poptOption * options,
@@ -220,6 +247,7 @@ typedef void (*poptCallbackType) (poptContext con,
* Reinitialize popt context.
* @param con context
*/
/*@unused@*/
void poptResetContext(/*@null@*/poptContext con)
/*@modifies con @*/;
@@ -229,57 +257,62 @@ void poptResetContext(/*@null@*/poptContext con)
* @return next option val, -1 on last item, POPT_ERROR_* on error
*/
int poptGetNextOpt(/*@null@*/poptContext con)
/*@globals fileSystem@*/
/*@modifies con, fileSystem @*/;
/*@globals fileSystem, internalState @*/
/*@modifies con, fileSystem, internalState @*/;
/*@-redecl@*/
/** \ingroup popt
* Return next option argument (if any).
* @param con context
* @return option argument, NULL if no more options are available
* @return option argument, NULL if no argument is available
*/
/*@observer@*/ /*@null@*/ const char * poptGetOptArg(/*@null@*/poptContext con)
/*@observer@*/ /*@null@*/ /*@unused@*/
const char * poptGetOptArg(/*@null@*/poptContext con)
/*@modifies con @*/;
/** \ingroup popt
* Return current option's argument.
* Return next argument.
* @param con context
* @return option argument, NULL if no more options are available
* @return next argument, NULL if no argument is available
*/
/*@observer@*/ /*@null@*/ const char * poptGetArg(/*@null@*/poptContext con)
/*@observer@*/ /*@null@*/ /*@unused@*/
const char * poptGetArg(/*@null@*/poptContext con)
/*@modifies con @*/;
/** \ingroup popt
* Peek at current option's argument.
* Peek at current argument.
* @param con context
* @return option argument
* @return current argument, NULL if no argument is available
*/
/*@observer@*/ /*@null@*/ const char * poptPeekArg(/*@null@*/poptContext con)
/*@observer@*/ /*@null@*/ /*@unused@*/
const char * poptPeekArg(/*@null@*/poptContext con)
/*@*/;
/** \ingroup popt
* Return remaining arguments.
* @param con context
* @return argument array, terminated with NULL
* @return argument array, NULL terminated
*/
/*@observer@*/ /*@null@*/ const char ** poptGetArgs(/*@null@*/poptContext con)
/*@observer@*/ /*@null@*/
const char ** poptGetArgs(/*@null@*/poptContext con)
/*@modifies con @*/;
/** \ingroup popt
* Return the option which caused the most recent error.
* @param con context
* @param flags
* @return offending option
*/
/*@observer@*/ const char * poptBadOption(/*@null@*/poptContext con, int flags)
/*@observer@*/
const char * poptBadOption(/*@null@*/poptContext con, int flags)
/*@*/;
/*@=redecl@*/
/** \ingroup popt
* Destroy context.
* @param con context
* @return NULL always
*/
/*@null@*/ poptContext poptFreeContext( /*@only@*/ /*@null@*/ poptContext con)
/*@null@*/
poptContext poptFreeContext( /*@only@*/ /*@null@*/ poptContext con)
/*@modifies con @*/;
/** \ingroup popt
@@ -288,6 +321,7 @@ int poptGetNextOpt(/*@null@*/poptContext con)
* @param argv argument array, NULL terminated
* @return 0 on success, POPT_ERROR_OPTSTOODEEP on failure
*/
/*@unused@*/
int poptStuffArgs(poptContext con, /*@keep@*/ const char ** argv)
/*@modifies con @*/;
@@ -307,7 +341,7 @@ int poptAddAlias(poptContext con, struct poptAlias alias, int flags)
/** \ingroup popt
* Add alias/exec item to context.
* @param con context
* @param item alias/exec item to add
* @param newItem alias/exec item to add
* @param flags 0 for alias, 1 for exec
* @return 0 on success
*/
@@ -321,9 +355,9 @@ int poptAddItem(poptContext con, poptItem newItem, int flags)
* @return 0 on success, POPT_ERROR_ERRNO on failure
*/
int poptReadConfigFile(poptContext con, const char * fn)
/*@globals fileSystem@*/
/*@modifies fileSystem,
con->execs, con->numExecs @*/;
/*@globals errno, fileSystem, internalState @*/
/*@modifies con->execs, con->numExecs,
errno, fileSystem, internalState @*/;
/** \ingroup popt
* Read default configuration from /etc/popt and $HOME/.popt.
@@ -331,10 +365,11 @@ int poptReadConfigFile(poptContext con, const char * fn)
* @param useEnv (unused)
* @return 0 on success, POPT_ERROR_ERRNO on failure
*/
/*@unused@*/
int poptReadDefaultConfig(poptContext con, /*@unused@*/ int useEnv)
/*@globals fileSystem@*/
/*@modifies fileSystem,
con->execs, con->numExecs @*/;
/*@globals fileSystem, internalState @*/
/*@modifies con->execs, con->numExecs,
fileSystem, internalState @*/;
/** \ingroup popt
* Duplicate an argument array.
@@ -363,19 +398,70 @@ 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 unsigned char * s,
int poptParseArgvString(const char * s,
/*@out@*/ int * argcPtr, /*@out@*/ const char *** argvPtr)
/*@modifies *argcPtr, *argvPtr @*/;
/** \ingroup popt
* Parses an input configuration file and returns an string that is a
* command line. For use with popt. You must free the return value when done.
*
* Given the file:
\verbatim
# this line is ignored
# this one too
aaa
bbb
ccc
bla=bla
this_is = fdsafdas
bad_line=
reall bad line
reall bad line = again
5555= 55555
test = with lots of spaces
\endverbatim
*
* The result is:
\verbatim
--aaa --bbb --ccc --bla="bla" --this_is="fdsafdas" --5555="55555" --test="with lots of spaces"
\endverbatim
*
* Passing this to poptParseArgvString() yields an argv of:
\verbatim
'--aaa'
'--bbb'
'--ccc'
'--bla=bla'
'--this_is=fdsafdas'
'--5555=55555'
'--test=with lots of spaces'
\endverbatim
*
* @bug NULL is returned if file line is too long.
* @bug Silently ignores invalid lines.
*
* @param fp file handle to read
* @param *argstrp return string of options (malloc'd)
* @param flags unused
* @return 0 on success
* @see poptParseArgvString
*/
/*@-fcnuse@*/
int poptConfigFileToString(FILE *fp, /*@out@*/ char ** argstrp, int flags)
/*@globals fileSystem @*/
/*@modifies *fp, *argstrp, fileSystem @*/;
/*@=fcnuse@*/
/** \ingroup popt
* Return formatted error string for popt failure.
* @param error popt error
* @return error string
*/
/*@-redecl@*/
/*@observer@*/ const char * poptStrerror(const int error)
/*@observer@*/
const char * poptStrerror(const int error)
/*@*/;
/*@=redecl@*/
/** \ingroup popt
* Limit search for executables.
@@ -383,6 +469,7 @@ int poptParseArgvString(const unsigned char * s,
* @param path single path to search for executables
* @param allowAbsolute absolute paths only?
*/
/*@unused@*/
void poptSetExecPath(poptContext con, const char * path, int allowAbsolute)
/*@modifies con @*/;
@@ -421,10 +508,11 @@ void poptSetOtherOptionHelp(poptContext con, const char * text)
* @param con context
* @return argv[0]
*/
/*@-redecl -fcnuse@*/
/*@observer@*/ const char * poptGetInvocationName(poptContext con)
/*@-fcnuse@*/
/*@observer@*/
const char * poptGetInvocationName(poptContext con)
/*@*/;
/*@=redecl =fcnuse@*/
/*@=fcnuse@*/
/** \ingroup popt
* Shuffle argv pointers to remove stripped args, returns new argc.
@@ -438,6 +526,36 @@ int poptStrippedArgv(poptContext con, int argc, char ** argv)
/*@modifies *argv @*/;
/*@=fcnuse@*/
/**
* Save a long, performing logical operation with value.
* @warning Alignment check may be too strict on certain platorms.
* @param arg integer pointer, aligned on int boundary.
* @param argInfo logical operation (see POPT_ARGFLAG_*)
* @param aLong value to use
* @return 0 on success, POPT_ERROR_NULLARG/POPT_ERROR_BADOPERATION
*/
/*@-incondefs@*/
/*@unused@*/
int poptSaveLong(/*@null@*/ long * arg, int argInfo, long aLong)
/*@modifies *arg @*/
/*@requires maxSet(arg) >= 0 /\ maxRead(arg) == 0 @*/;
/*@=incondefs@*/
/**
* Save an integer, performing logical operation with value.
* @warning Alignment check may be too strict on certain platorms.
* @param arg integer pointer, aligned on int boundary.
* @param argInfo logical operation (see POPT_ARGFLAG_*)
* @param aLong value to use
* @return 0 on success, POPT_ERROR_NULLARG/POPT_ERROR_BADOPERATION
*/
/*@-incondefs@*/
/*@unused@*/
int poptSaveInt(/*@null@*/ int * arg, int argInfo, long aLong)
/*@modifies *arg @*/
/*@requires maxSet(arg) >= 0 /\ maxRead(arg) == 0 @*/;
/*@=incondefs@*/
/*@=type@*/
#ifdef __cplusplus
}

View File

@@ -2,46 +2,48 @@
* \file popt/poptconfig.c
*/
/* (C) 1998-2000 Red Hat, Inc. -- Licensing details are in the COPYING
/* (C) 1998-2002 Red Hat, Inc. -- Licensing details are in the COPYING
file accompanying popt source distributions, available from
ftp://ftp.rpm.org/pub/rpm/dist. */
#include "system.h"
#include "poptint.h"
/*@access poptContext @*/
/*@-compmempass@*/ /* FIX: item->option.longName kept, not dependent. */
static void configLine(poptContext con, unsigned char * line)
static void configLine(poptContext con, char * line)
/*@modifies con @*/
{
/*@-type@*/
int nameLength = strlen(con->appName);
/*@=type@*/
size_t nameLength;
const char * entryType;
const char * opt;
poptItem item = (poptItem) alloca(sizeof(*item));
int i, j;
if (con->appName == NULL)
return;
nameLength = strlen(con->appName);
/*@-boundswrite@*/
memset(item, 0, sizeof(*item));
/*@-type@*/
if (strncmp(line, con->appName, nameLength)) return;
/*@=type@*/
line += nameLength;
if (*line == '\0' || !isspace(*line)) return;
if (*line == '\0' || !isSpace(line)) return;
while (*line != '\0' && isspace(*line)) line++;
while (*line != '\0' && isSpace(line)) line++;
entryType = line;
while (*line == '\0' || !isspace(*line)) line++;
while (*line == '\0' || !isSpace(line)) line++;
*line++ = '\0';
while (*line != '\0' && isspace(*line)) line++;
while (*line != '\0' && isSpace(line)) line++;
if (*line == '\0') return;
opt = line;
while (*line == '\0' || !isspace(*line)) line++;
while (*line == '\0' || !isSpace(line)) line++;
*line++ = '\0';
while (*line != '\0' && isspace(*line)) line++;
while (*line != '\0' && isSpace(line)) line++;
if (*line == '\0') return;
/*@-temptrans@*/ /* FIX: line alias is saved */
@@ -80,6 +82,7 @@ static void configLine(poptContext con, unsigned char * line)
item->argc = j;
}
/*@=modobserver@*/
/*@=boundswrite@*/
/*@-nullstate@*/ /* FIX: item->argv[] may be NULL */
if (!strcmp(entryType, "alias"))
@@ -92,9 +95,9 @@ static void configLine(poptContext con, unsigned char * line)
int poptReadConfigFile(poptContext con, const char * fn)
{
const unsigned char * file, * chptr, * end;
unsigned char * buf;
/*@dependent@*/ unsigned char * dst;
const char * file, * chptr, * end;
char * buf;
/*@dependent@*/ char * dst;
int fd, rc;
off_t fileLength;
@@ -106,9 +109,7 @@ int poptReadConfigFile(poptContext con, const char * fn)
if (fileLength == -1 || lseek(fd, 0, 0) == -1) {
rc = errno;
(void) close(fd);
/*@-mods@*/
errno = rc;
/*@=mods@*/
return POPT_ERROR_ERRNO;
}
@@ -116,14 +117,13 @@ int poptReadConfigFile(poptContext con, const char * fn)
if (read(fd, (char *)file, fileLength) != fileLength) {
rc = errno;
(void) close(fd);
/*@-mods@*/
errno = rc;
/*@=mods@*/
return POPT_ERROR_ERRNO;
}
if (close(fd) == -1)
return POPT_ERROR_ERRNO;
/*@-boundswrite@*/
dst = buf = alloca(fileLength + 1);
chptr = file;
@@ -134,7 +134,7 @@ int poptReadConfigFile(poptContext con, const char * fn)
case '\n':
*dst = '\0';
dst = buf;
while (*dst && isspace(*dst)) dst++;
while (*dst && isSpace(dst)) dst++;
if (*dst && *dst != '#')
configLine(con, dst);
chptr++;
@@ -155,6 +155,7 @@ int poptReadConfigFile(poptContext con, const char * fn)
}
}
/*@=infloops@*/
/*@=boundswrite@*/
return 0;
}
@@ -164,18 +165,16 @@ int poptReadDefaultConfig(poptContext con, /*@unused@*/ UNUSED(int useEnv))
char * fn, * home;
int rc;
/*@-type@*/
if (!con->appName) return 0;
/*@=type@*/
if (con->appName == NULL) return 0;
rc = poptReadConfigFile(con, "/etc/popt");
if (rc) return rc;
if (getuid() != geteuid()) return 0;
if ((home = getenv("HOME"))) {
fn = alloca(strlen(home) + 20);
strcpy(fn, home);
strcat(fn, "/.popt");
size_t bufsize = strlen(home) + 20;
fn = alloca(bufsize);
if (fn == NULL) return 0;
snprintf(fn, bufsize, "%s/.popt", home);
rc = poptReadConfigFile(con, fn);
if (rc) return rc;
}

View File

@@ -1,20 +1,31 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/*@-type@*/
/** \ingroup popt
* \file popt/popthelp.c
*/
/* (C) 1998-2000 Red Hat, Inc. -- Licensing details are in the COPYING
/* (C) 1998-2002 Red Hat, Inc. -- Licensing details are in the COPYING
file accompanying popt source distributions, available from
ftp://ftp.rpm.org/pub/rpm/dist. */
#include "system.h"
/*#define POPT_WCHAR_HACK*/
#ifdef POPT_WCHAR_HACK
#include <wchar.h> /* for mbsrtowcs */
/*@access mbstate_t @*/
#endif
#include "poptint.h"
/*@access poptContext@*/
/**
* Display arguments.
* @param con context
* @param foo (unused)
* @param key option(s)
* @param arg (unused)
* @param data (unused)
*/
static void displayArgs(poptContext con,
/*@unused@*/ UNUSED(enum poptCallbackReason foo),
@@ -49,6 +60,17 @@ struct poptOption poptAliasOptions[] = {
/*@-castfcnptr@*/
/*@observer@*/ /*@unchecked@*/
struct poptOption poptHelpOptions[] = {
{ NULL, '\0', POPT_ARG_CALLBACK, (void *)&displayArgs, '\0', NULL, NULL },
{ "help", '?', 0, NULL, '?', N_("Show this help message"), NULL },
{ "usage", '\0', 0, NULL, 'u', N_("Display brief usage message"), NULL },
POPT_TABLEEND
} ;
/*@observer@*/ /*@unchecked@*/
static struct poptOption poptHelpOptions2[] = {
/*@-readonlytrans@*/
{ NULL, '\0', POPT_ARG_INTL_DOMAIN, PACKAGE, 0, NULL, NULL},
/*@=readonlytrans@*/
{ NULL, '\0', POPT_ARG_CALLBACK, (void *)&displayArgs, '\0', NULL, NULL },
{ "help", '?', 0, NULL, '?', N_("Show this help message"), NULL },
{ "usage", '\0', 0, NULL, 'u', N_("Display brief usage message"), NULL },
@@ -58,6 +80,9 @@ struct poptOption poptHelpOptions[] = {
#endif
POPT_TABLEEND
} ;
/*@observer@*/ /*@unchecked@*/
struct poptOption * poptHelpOptionsI18N = poptHelpOptions2;
/*@=castfcnptr@*/
/**
@@ -83,7 +108,7 @@ getTableTranslationDomain(/*@null@*/ const struct poptOption *table)
*/
/*@observer@*/ /*@null@*/ static const char *
getArgDescrip(const struct poptOption * opt,
/*@-paramuse@*/ /* FIX: wazzup? */
/*@-paramuse@*/ /* FIX: i18n macros disabled with lclint */
/*@null@*/ UNUSED(const char * translation_domain))
/*@=paramuse@*/
/*@*/
@@ -97,7 +122,11 @@ getArgDescrip(const struct poptOption * opt,
switch (opt->argInfo & POPT_ARG_MASK) {
case POPT_ARG_NONE: return POPT_("NONE");
#ifdef DYING
case POPT_ARG_VAL: return POPT_("VAL");
#else
case POPT_ARG_VAL: return NULL;
#endif
case POPT_ARG_INT: return POPT_("INT");
case POPT_ARG_LONG: return POPT_("LONG");
case POPT_ARG_STRING: return POPT_("STRING");
@@ -108,61 +137,65 @@ getArgDescrip(const struct poptOption * opt,
}
/**
* Display default value for an option.
* @param lineLength display positions remaining
* @param opt option(s)
* @param translation_domain translation domain
* @return
*/
static /*@only@*/ /*@null@*/ char *
singleOptionDefaultValue(int lineLength,
singleOptionDefaultValue(size_t lineLength,
const struct poptOption * opt,
/*@-paramuse@*/ /* FIX: i18n macros disable with lclint */
/*@-paramuse@*/ /* FIX: i18n macros disabled with lclint */
/*@null@*/ UNUSED(const char * translation_domain))
/*@=paramuse@*/
/*@*/
{
const char * defstr = D_(translation_domain, "default");
char * le = malloc(4*lineLength + 1);
size_t limit, bufsize = 4*lineLength + 1;
char * le = malloc(bufsize);
char * l = le;
if (le == NULL) return NULL; /* XXX can't happen */
*le = '\0';
/*@-boundswrite@*/
*le++ = '(';
strcpy(le, defstr); le += strlen(le);
le += strlcpy(le, defstr, bufsize - 3);
*le++ = ':';
*le++ = ' ';
limit = bufsize - (le - l) - 1; /* -1 for closing paren */
if (opt->arg) /* XXX programmer error */
switch (opt->argInfo & POPT_ARG_MASK) {
case POPT_ARG_VAL:
case POPT_ARG_INT:
{ long aLong = *((int *)opt->arg);
sprintf(le, "%ld", aLong);
le += strlen(le);
le += snprintf(le, limit, "%ld", aLong);
} break;
case POPT_ARG_LONG:
{ long aLong = *((long *)opt->arg);
sprintf(le, "%ld", aLong);
le += strlen(le);
le += snprintf(le, limit, "%ld", aLong);
} break;
case POPT_ARG_FLOAT:
{ double aDouble = *((float *)opt->arg);
sprintf(le, "%g", aDouble);
le += strlen(le);
le += snprintf(le, limit, "%g", aDouble);
} break;
case POPT_ARG_DOUBLE:
{ double aDouble = *((double *)opt->arg);
sprintf(le, "%g", aDouble);
le += strlen(le);
le += snprintf(le, limit, "%g", aDouble);
} break;
case POPT_ARG_STRING:
{ const char * s = *(const char **)opt->arg;
if (s == NULL) {
strcpy(le, "null"); le += strlen(le);
le += strlcpy(le, "null", limit);
} else {
size_t slen = 4*lineLength - (le - l) - sizeof("\"...\")");
size_t len;
limit -= 2; /* make room for quotes */
*le++ = '"';
strncpy(le, s, slen); le[slen] = '\0'; le += strlen(le);
if (slen < strlen(s)) {
strcpy(le, "..."); le += strlen(le);
}
len = strlcpy(le, s, limit);
if (len >= limit) {
le += limit - 3 - 1;
*le++ = '.'; *le++ = '.'; *le++ = '.';
} else
le += len;
*le++ = '"';
}
} break;
@@ -174,50 +207,57 @@ singleOptionDefaultValue(int lineLength,
}
*le++ = ')';
*le = '\0';
/*@=boundswrite@*/
return l;
}
/**
* Display help text for an option.
* @param fp output file handle
* @param maxLeftCol largest argument display width
* @param opt option(s)
* @param translation_domain translation domain
*/
static void singleOptionHelp(FILE * fp, int maxLeftCol,
static void singleOptionHelp(FILE * fp, size_t maxLeftCol,
const struct poptOption * opt,
/*@null@*/ const char * translation_domain)
/*@null@*/ UNUSED(const char * translation_domain))
/*@globals fileSystem @*/
/*@modifies *fp, fileSystem @*/
{
int indentLength = maxLeftCol + 5;
int lineLength = 79 - indentLength;
const unsigned char * help = D_(translation_domain, opt->descrip);
size_t indentLength = maxLeftCol + 5;
size_t lineLength = 79 - indentLength;
const char * help = D_(translation_domain, opt->descrip);
const char * argDescrip = getArgDescrip(opt, translation_domain);
int helpLength;
unsigned char * defs = NULL;
unsigned char * left;
int nb = maxLeftCol + 1;
size_t helpLength;
char * defs = NULL;
char * left;
size_t lelen, limit;
size_t nb = maxLeftCol + 1;
int displaypad = 0;
/* Make sure there's more than enough room in target buffer. */
if (opt->longName) nb += strlen(opt->longName);
if (argDescrip) nb += strlen(argDescrip);
/*@-boundswrite@*/
left = malloc(nb);
if (left == NULL) return; /* XXX can't happen */
left[0] = '\0';
left[maxLeftCol] = '\0';
if (opt->longName && opt->shortName)
sprintf(left, "-%c, %s%s", opt->shortName,
snprintf(left, nb, "-%c, %s%s", opt->shortName,
((opt->argInfo & POPT_ARGFLAG_ONEDASH) ? "-" : "--"),
opt->longName);
else if (opt->shortName != '\0')
sprintf(left, "-%c", opt->shortName);
snprintf(left, nb, "-%c", opt->shortName);
else if (opt->longName)
sprintf(left, "%s%s",
snprintf(left, nb, "%s%s",
((opt->argInfo & POPT_ARGFLAG_ONEDASH) ? "-" : "--"),
opt->longName);
if (!*left) goto out;
if (argDescrip) {
char * le = left + strlen(left);
@@ -229,16 +269,10 @@ static void singleOptionHelp(FILE * fp, int maxLeftCol,
if (opt->argInfo & POPT_ARGFLAG_SHOW_DEFAULT) {
defs = singleOptionDefaultValue(lineLength, opt, translation_domain);
if (defs) {
char * t = malloc((help ? strlen(help) : 0) +
strlen(defs) + sizeof(" "));
size_t bufsize = (help ? strlen(help) : 0) + sizeof " " + strlen(defs);
char * t = malloc(bufsize);
if (t) {
char * te = t;
*te = '\0';
if (help) {
strcpy(te, help); te += strlen(te);
}
*te++ = ' ';
strcpy(te, defs);
snprintf(t, bufsize, "%s %s", help ? help : "", defs);
defs = _free(defs);
}
defs = t;
@@ -251,6 +285,7 @@ static void singleOptionHelp(FILE * fp, int maxLeftCol,
case POPT_ARG_NONE:
break;
case POPT_ARG_VAL:
#ifdef NOTNOW /* XXX pug ugly nerdy output */
{ long aLong = opt->val;
int ops = (opt->argInfo & POPT_ARGFLAG_LOGICALOPS);
int negate = (opt->argInfo & POPT_ARGFLAG_NOT);
@@ -272,65 +307,94 @@ static void singleOptionHelp(FILE * fp, int maxLeftCol,
default:
/*@innerbreak@*/ break;
}
*le++ = '=';
*le++ = (opt->longName != NULL ? '=' : ' ');
if (negate) *le++ = '~';
/*@-formatconst@*/
sprintf(le, (ops ? "0x%lx" : "%ld"), aLong);
le += strlen(le);
limit = nb - (le - left);
lelen = snprintf(le, limit, (ops ? "0x%lx" : "%ld"), aLong);
le += lelen >= limit ? limit - 1 : lelen;
/*@=formatconst@*/
*le++ = ']';
} break;
}
#endif
break;
case POPT_ARG_INT:
case POPT_ARG_LONG:
case POPT_ARG_FLOAT:
case POPT_ARG_DOUBLE:
case POPT_ARG_STRING:
*le++ = '=';
strcpy(le, argDescrip); le += strlen(le);
*le++ = (opt->longName != NULL ? '=' : ' ');
limit = nb - (le - left);
lelen = strlcpy(le, argDescrip, limit);
le += lelen >= limit ? limit - 1 : lelen;
break;
default:
break;
}
} else {
*le++ = '=';
strcpy(le, argDescrip); le += strlen(le);
limit = nb - (le - left);
lelen = strlcpy(le, argDescrip, limit);
if (lelen >= limit)
lelen = limit - 1;
le += lelen;
#ifdef POPT_WCHAR_HACK
{ const char * scopy = argDescrip;
mbstate_t t;
size_t n;
memset ((void *)&t, '\0', sizeof (t)); /* In initial state. */
/* Determine number of characters. */
n = mbsrtowcs (NULL, &scopy, strlen(scopy), &t);
displaypad = (int) (lelen-n);
}
#endif
}
if (opt->argInfo & POPT_ARGFLAG_OPTIONAL)
*le++ = ']';
*le = '\0';
}
/*@=boundswrite@*/
if (help)
fprintf(fp," %-*s ", maxLeftCol, left);
fprintf(fp," %-*s ", (int)maxLeftCol+displaypad, left);
else {
fprintf(fp," %s\n", left);
goto out;
}
left = _free(left);
/*@-branchstate@*/
if (defs) {
help = defs; defs = NULL;
help = defs;
defs = NULL;
}
/*@=branchstate@*/
helpLength = strlen(help);
/*@-boundsread@*/
while (helpLength > lineLength) {
const unsigned char * ch;
char format[10];
const char * ch;
char format[16];
ch = help + lineLength - 1;
while (ch > help && !isspace(*ch)) ch--;
while (ch > help && !isSpace(ch)) ch--;
if (ch == help) break; /* give up */
while (ch > (help + 1) && isspace(*ch)) ch--;
while (ch > (help + 1) && isSpace(ch)) ch--;
ch++;
sprintf(format, "%%.%ds\n%%%ds", (int) (ch - help), indentLength);
snprintf(format, sizeof format, "%%.%ds\n%%%ds", (int) (ch - help), (int) indentLength);
/*@-formatconst@*/
fprintf(fp, format, help, " ");
/*@=formatconst@*/
help = ch;
while (isspace(*help) && *help) help++;
while (isSpace(help) && *help) help++;
helpLength = strlen(help);
}
/*@=boundsread@*/
if (helpLength) fprintf(fp, "%s\n", help);
@@ -342,15 +406,17 @@ out:
}
/**
* Find display width for longest argument string.
* @param opt option(s)
* @param translation_domain translation domain
* @return display width
*/
static int maxArgWidth(const struct poptOption * opt,
/*@null@*/ const char * translation_domain)
static size_t maxArgWidth(const struct poptOption * opt,
/*@null@*/ UNUSED(const char * translation_domain))
/*@*/
{
int max = 0;
int len = 0;
size_t max = 0;
size_t len = 0;
const char * s;
if (opt != NULL)
@@ -370,8 +436,26 @@ static int maxArgWidth(const struct poptOption * opt,
}
s = getArgDescrip(opt, translation_domain);
#ifdef POPT_WCHAR_HACK
/* XXX Calculate no. of display characters. */
if (s) {
const char * scopy = s;
mbstate_t t;
size_t n;
/*@-boundswrite@*/
memset ((void *)&t, '\0', sizeof (t)); /* In initial state. */
/*@=boundswrite@*/
/* Determine number of characters. */
n = mbsrtowcs (NULL, &scopy, strlen(scopy), &t);
len += sizeof("=")-1 + n;
}
#else
if (s)
len += sizeof("=")-1 + strlen(s);
#endif
if (opt->argInfo & POPT_ARGFLAG_OPTIONAL) len += sizeof("[]")-1;
if (len > max) max = len;
}
@@ -387,11 +471,12 @@ static int maxArgWidth(const struct poptOption * opt,
* @param fp output file handle
* @param items alias/exec array
* @param nitems no. of alias/exec entries
* @param left largest argument display width
* @param translation_domain translation domain
*/
static void itemHelp(FILE * fp,
/*@null@*/ poptItem items, int nitems, int left,
/*@null@*/ const char * translation_domain)
/*@null@*/ poptItem items, int nitems, size_t left,
/*@null@*/ UNUSED(const char * translation_domain))
/*@globals fileSystem @*/
/*@modifies *fp, fileSystem @*/
{
@@ -409,13 +494,16 @@ static void itemHelp(FILE * fp,
}
/**
* Display help text for a table of options.
* @param con context
* @param fp output file handle
* @param table option(s)
* @param left largest argument display width
* @param translation_domain translation domain
*/
static void singleTableHelp(poptContext con, FILE * fp,
/*@null@*/ const struct poptOption * table, int left,
/*@null@*/ const char * translation_domain)
/*@null@*/ const struct poptOption * table, size_t left,
/*@null@*/ UNUSED(const char * translation_domain))
/*@globals fileSystem @*/
/*@modifies *fp, fileSystem @*/
{
@@ -463,9 +551,11 @@ static int showHelpIntro(poptContext con, FILE * fp)
fprintf(fp, POPT_("Usage:"));
if (!(con->flags & POPT_CONTEXT_KEEP_FIRST)) {
/*@-nullderef@*/ /* LCL: wazzup? */
/*@-boundsread@*/
/*@-nullderef -type@*/ /* LCL: wazzup? */
fn = con->optionStack->argv[0];
/*@=nullderef@*/
/*@=nullderef =type@*/
/*@=boundsread@*/
if (fn == NULL) return len;
if (strchr(fn, '/')) fn = strrchr(fn, '/') + 1;
fprintf(fp, " %s", fn);
@@ -477,7 +567,7 @@ static int showHelpIntro(poptContext con, FILE * fp)
void poptPrintHelp(poptContext con, FILE * fp, /*@unused@*/ UNUSED(int flags))
{
int leftColWidth;
size_t leftColWidth;
(void) showHelpIntro(con, fp);
if (con->otherHelp)
@@ -490,47 +580,76 @@ void poptPrintHelp(poptContext con, FILE * fp, /*@unused@*/ UNUSED(int flags))
}
/**
* Display usage text for an option.
* @param fp output file handle
* @param cursor current display position
* @param opt option(s)
* @param translation_domain translation domain
*/
static int singleOptionUsage(FILE * fp, int cursor,
static size_t singleOptionUsage(FILE * fp, size_t cursor,
const struct poptOption * opt,
/*@null@*/ const char *translation_domain)
/*@globals fileSystem @*/
/*@modifies *fp, fileSystem @*/
{
int len = 3;
size_t len = 4;
char shortStr[2] = { '\0', '\0' };
const char * item = shortStr;
const char * argDescrip = getArgDescrip(opt, translation_domain);
if (opt->shortName!= '\0' ) {
if (!(opt->argInfo & POPT_ARG_MASK))
return cursor; /* we did these already */
if (opt->shortName != '\0' && opt->longName != NULL) {
len += 2;
if (!(opt->argInfo & POPT_ARGFLAG_ONEDASH)) len++;
len += strlen(opt->longName);
} else if (opt->shortName != '\0') {
len++;
shortStr[0] = opt->shortName;
shortStr[1] = '\0';
} else if (opt->longName) {
len += 1 + strlen(opt->longName);
len += strlen(opt->longName);
if (!(opt->argInfo & POPT_ARGFLAG_ONEDASH)) len++;
item = opt->longName;
}
if (len == 3) return cursor;
if (len == 4) return cursor;
#ifdef POPT_WCHAR_HACK
/* XXX Calculate no. of display characters. */
if (argDescrip) {
const char * scopy = argDescrip;
mbstate_t t;
size_t n;
/*@-boundswrite@*/
memset ((void *)&t, '\0', sizeof (t)); /* In initial state. */
/*@=boundswrite@*/
/* Determine number of characters. */
n = mbsrtowcs (NULL, &scopy, strlen(scopy), &t);
len += sizeof("=")-1 + n;
}
#else
if (argDescrip)
len += strlen(argDescrip) + 1;
len += sizeof("=")-1 + strlen(argDescrip);
#endif
if ((cursor + len) > 79) {
fprintf(fp, "\n ");
cursor = 7;
}
fprintf(fp, " [-%s%s%s%s]",
((opt->shortName || (opt->argInfo & POPT_ARGFLAG_ONEDASH)) ? "" : "-"),
item,
(argDescrip ? (opt->shortName != '\0' ? " " : "=") : ""),
(argDescrip ? argDescrip : ""));
if (opt->longName && opt->shortName) {
fprintf(fp, " [-%c|-%s%s%s%s]",
opt->shortName, ((opt->argInfo & POPT_ARGFLAG_ONEDASH) ? "" : "-"),
opt->longName,
(argDescrip ? " " : ""),
(argDescrip ? argDescrip : ""));
} else {
fprintf(fp, " [-%s%s%s%s]",
((opt->shortName || (opt->argInfo & POPT_ARGFLAG_ONEDASH)) ? "" : "-"),
item,
(argDescrip ? (opt->shortName != '\0' ? " " : "=") : ""),
(argDescrip ? argDescrip : ""));
}
return cursor + len + 1;
}
@@ -538,12 +657,14 @@ static int singleOptionUsage(FILE * fp, int cursor,
/**
* Display popt alias and exec usage.
* @param fp output file handle
* @param cursor current display position
* @param item alias/exec array
* @param nitems no. of ara/exec entries
* @param translation_domain translation domain
*/
static int itemUsage(FILE * fp, int cursor, poptItem item, int nitems,
/*@null@*/ const char * translation_domain)
static size_t itemUsage(FILE * fp, size_t cursor,
/*@null@*/ poptItem item, int nitems,
/*@null@*/ UNUSED(const char * translation_domain))
/*@globals fileSystem @*/
/*@modifies *fp, fileSystem @*/
{
@@ -567,15 +688,30 @@ static int itemUsage(FILE * fp, int cursor, poptItem item, int nitems,
}
/**
* Keep track of option tables already processed.
*/
typedef struct poptDone_s {
int nopts;
int maxopts;
const void ** opts;
} * poptDone;
/**
* Display usage text for a table of options.
* @param con context
* @param fp output file handle
* @param cursor current display position
* @param opt option(s)
* @param translation_domain translation domain
* @param done tables already processed
* @return
*/
static int singleTableUsage(poptContext con, FILE * fp,
int cursor, const struct poptOption * opt,
/*@null@*/ const char * translation_domain)
static size_t singleTableUsage(poptContext con, FILE * fp, size_t cursor,
/*@null@*/ const struct poptOption * opt,
/*@null@*/ UNUSED(const char * translation_domain),
/*@null@*/ poptDone done)
/*@globals fileSystem @*/
/*@modifies *fp, fileSystem @*/
/*@modifies *fp, done, fileSystem @*/
{
/*@-branchstate@*/ /* FIX: W2DO? */
if (opt != NULL)
@@ -583,9 +719,26 @@ static int singleTableUsage(poptContext con, FILE * fp,
if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INTL_DOMAIN) {
translation_domain = (const char *)opt->arg;
} else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
if (opt->arg) /* XXX program error */
if (done) {
int i = 0;
for (i = 0; i < done->nopts; i++) {
/*@-boundsread@*/
const void * that = done->opts[i];
/*@=boundsread@*/
if (that == NULL || that != opt->arg)
/*@innercontinue@*/ continue;
/*@innerbreak@*/ break;
}
/* Skip if this table has already been processed. */
if (opt->arg == NULL || i < done->nopts)
continue;
/*@-boundswrite@*/
if (done->nopts < done->maxopts)
done->opts[done->nopts++] = (const void *) opt->arg;
/*@=boundswrite@*/
}
cursor = singleTableUsage(con, fp, cursor, opt->arg,
translation_domain);
translation_domain, done);
} else if ((opt->longName || opt->shortName) &&
!(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN)) {
cursor = singleOptionUsage(fp, cursor, opt, translation_domain);
@@ -598,6 +751,7 @@ static int singleTableUsage(poptContext con, FILE * fp,
/**
* Return concatenated short options for display.
* @todo Sub-tables should be recursed.
* @param opt option(s)
* @param fp output file handle
* @retval str concatenation of short options
@@ -607,42 +761,51 @@ static int showShortOptions(const struct poptOption * opt, FILE * fp,
/*@null@*/ char * str)
/*@globals fileSystem @*/
/*@modifies *str, *fp, fileSystem @*/
/*@requires maxRead(str) >= 0 @*/
{
char * s = alloca(300); /* larger then the ascii set */
s[0] = '\0';
/*@-branchstate@*/ /* FIX: W2DO? */
if (str == NULL) {
memset(s, 0, sizeof(s));
str = s;
}
/*@=branchstate@*/
/* bufsize larger then the ascii set, lazy alloca on top level call. */
char * s = (str != NULL ? str : memset(alloca(300), 0, 300));
int len = 0;
/*@-boundswrite@*/
if (opt != NULL)
for (; (opt->longName || opt->shortName || opt->arg); opt++) {
if (opt->shortName && !(opt->argInfo & POPT_ARG_MASK))
str[strlen(str)] = opt->shortName;
s[strlen(s)] = opt->shortName;
else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE)
if (opt->arg) /* XXX program error */
(void) showShortOptions(opt->arg, fp, str);
len = showShortOptions(opt->arg, fp, s);
}
/*@=boundswrite@*/
if (s != str || *s != '\0')
return 0;
fprintf(fp, " [-%s]", s);
return strlen(s) + 4;
/* On return to top level, print the short options, return print length. */
if (s == str && *s != '\0') {
fprintf(fp, " [-%s]", s);
len = strlen(s) + sizeof(" [-]")-1;
}
return len;
}
void poptPrintUsage(poptContext con, FILE * fp, /*@unused@*/ UNUSED(int flags))
{
int cursor;
poptDone done = memset(alloca(sizeof(*done)), 0, sizeof(*done));
size_t cursor;
done->nopts = 0;
done->maxopts = 64;
cursor = done->maxopts * sizeof(*done->opts);
/*@-boundswrite@*/
done->opts = memset(alloca(cursor), 0, cursor);
/*@-keeptrans@*/
done->opts[done->nopts++] = (const void *) con->options;
/*@=keeptrans@*/
/*@=boundswrite@*/
cursor = showHelpIntro(con, fp);
cursor += showShortOptions(con->options, fp, NULL);
(void) singleTableUsage(con, fp, cursor, con->options, NULL);
(void) itemUsage(fp, cursor, con->aliases, con->numAliases, NULL);
(void) itemUsage(fp, cursor, con->execs, con->numExecs, NULL);
cursor = singleTableUsage(con, fp, cursor, con->options, NULL, done);
cursor = itemUsage(fp, cursor, con->aliases, con->numAliases, NULL);
cursor = itemUsage(fp, cursor, con->execs, con->numExecs, NULL);
if (con->otherHelp) {
cursor += strlen(con->otherHelp) + 1;
@@ -658,4 +821,3 @@ void poptSetOtherOptionHelp(poptContext con, const char * text)
con->otherHelp = _free(con->otherHelp);
con->otherHelp = xstrdup(text);
}
/*@=type@*/

View File

@@ -22,14 +22,24 @@ _free(/*@only@*/ /*@null@*/ const void * p)
return NULL;
}
static inline int
isSpace(const char *ptr)
{
return isspace(*(unsigned char *)ptr);
}
/* Bit mask macros. */
/*@-exporttype -redef @*/
typedef unsigned int __pbm_bits;
/*@=exporttype =redef @*/
#define __PBM_NBITS (8 * sizeof (__pbm_bits))
#define __PBM_IX(d) ((d) / __PBM_NBITS)
#define __PBM_MASK(d) ((__pbm_bits) 1 << (((unsigned)(d)) % __PBM_NBITS))
/*@-exporttype -redef @*/
typedef struct {
__pbm_bits bits[1];
} pbm_set;
/*@=exporttype =redef @*/
#define __PBM_BITS(set) ((set)->bits)
#define PBM_ALLOC(d) calloc(__PBM_IX (d) + 1, sizeof(__pbm_bits))
@@ -40,37 +50,53 @@ typedef struct {
struct optionStackEntry {
int argc;
/*@only@*/ /*@null@*/ const char ** argv;
/*@only@*/ /*@null@*/ pbm_set * argb;
/*@only@*/ /*@null@*/
const char ** argv;
/*@only@*/ /*@null@*/
pbm_set * argb;
int next;
/*@only@*/ /*@null@*/ const char * nextArg;
/*@keep@*/ /*@null@*/ const char * nextCharArg;
/*@dependent@*/ /*@null@*/ poptItem currAlias;
/*@only@*/ /*@null@*/
const char * nextArg;
/*@observer@*/ /*@null@*/
const char * nextCharArg;
/*@dependent@*/ /*@null@*/
poptItem currAlias;
int stuffed;
};
struct poptContext_s {
struct optionStackEntry optionStack[POPT_OPTION_DEPTH];
/*@dependent@*/ struct optionStackEntry * os;
/*@owned@*/ /*@null@*/ const char ** leftovers;
/*@dependent@*/
struct optionStackEntry * os;
/*@owned@*/ /*@null@*/
const char ** leftovers;
int numLeftovers;
int nextLeftover;
/*@keep@*/ const struct poptOption * options;
/*@keep@*/
const struct poptOption * options;
int restLeftover;
/*@only@*/ /*@null@*/ const char * appName;
/*@only@*/ /*@null@*/ poptItem aliases;
/*@only@*/ /*@null@*/
const char * appName;
/*@only@*/ /*@null@*/
poptItem aliases;
int numAliases;
int flags;
/*@owned@*/ /*@null@*/ poptItem execs;
/*@owned@*/ /*@null@*/
poptItem execs;
int numExecs;
/*@only@*/ /*@null@*/ const char ** finalArgv;
/*@only@*/ /*@null@*/
const char ** finalArgv;
int finalArgvCount;
int finalArgvAlloced;
/*@dependent@*/ /*@null@*/ poptItem doExec;
/*@only@*/ const char * execPath;
/*@dependent@*/ /*@null@*/
poptItem doExec;
/*@only@*/
const char * execPath;
int execAbsolute;
/*@only@*/ const char * otherHelp;
/*@null@*/ pbm_set * arg_strip;
/*@only@*/ /*@relnull@*/
const char * otherHelp;
/*@null@*/
pbm_set * arg_strip;
};
#ifdef HAVE_LIBINTL_H
@@ -83,7 +109,7 @@ struct poptContext_s {
#define _(foo) foo
#endif
#if defined(HAVE_DGETTEXT) && !defined(__LCLINT__)
#if defined(HAVE_DCGETTEXT) && !defined(__LCLINT__)
#define D_(dom, str) dgettext(dom, str)
#define POPT_(foo) D_("popt", foo)
#else

View File

@@ -2,14 +2,17 @@
* \file popt/poptparse.c
*/
/* (C) 1998-2000 Red Hat, Inc. -- Licensing details are in the COPYING
/* (C) 1998-2002 Red Hat, Inc. -- Licensing details are in the COPYING
file accompanying popt source distributions, available from
ftp://ftp.rpm.org/pub/rpm/dist. */
#include "system.h"
#include "poptint.h"
#define POPT_ARGV_ARRAY_GROW_DELTA 5
/*@-boundswrite@*/
int poptDupArgv(int argc, const char **argv,
int * argcPtr, const char *** argvPtr)
{
@@ -35,7 +38,7 @@ int poptDupArgv(int argc, const char **argv,
/*@-branchstate@*/
for (i = 0; i < argc; i++) {
argv2[i] = dst;
dst += strlen(strcpy(dst, argv[i])) + 1;
dst += strlcpy(dst, argv[i], nb) + 1;
}
/*@=branchstate@*/
argv2[argc] = NULL;
@@ -50,11 +53,13 @@ int poptDupArgv(int argc, const char **argv,
*argcPtr = argc;
return 0;
}
/*@=boundswrite@*/
int poptParseArgvString(const unsigned char * s, int * argcPtr, const char *** argvPtr)
/*@-bounds@*/
int poptParseArgvString(const char * s, int * argcPtr, const char *** argvPtr)
{
const unsigned char * src;
unsigned char quote = '\0';
const char * src;
char quote = '\0';
int argvAlloced = POPT_ARGV_ARRAY_GROW_DELTA;
const char ** argv = malloc(sizeof(*argv) * argvAlloced);
int argc = 0;
@@ -78,7 +83,7 @@ int poptParseArgvString(const unsigned char * s, int * argcPtr, const char *** a
if (*src != quote) *buf++ = '\\';
}
*buf++ = *src;
} else if (isspace(*src)) {
} else if (isSpace(src)) {
if (*argv[argc] != '\0') {
buf++, argc++;
if (argc == argvAlloced) {
@@ -116,3 +121,109 @@ exit:
if (argv) free(argv);
return rc;
}
/*@=bounds@*/
/* still in the dev stage.
* return values, perhaps 1== file erro
* 2== line to long
* 3== umm.... more?
*/
int poptConfigFileToString(FILE *fp, char ** argstrp, /*@unused@*/ UNUSED(int flags))
{
char line[999];
char * argstr;
char * p;
char * q;
char * x;
int t;
int argvlen = 0;
size_t maxlinelen = sizeof(line);
size_t linelen;
int maxargvlen = 480;
int linenum = 0;
*argstrp = NULL;
/* | this_is = our_line
* p q x
*/
if (fp == NULL)
return POPT_ERROR_NULLARG;
argstr = calloc(maxargvlen, sizeof(*argstr));
if (argstr == NULL) return POPT_ERROR_MALLOC;
while (fgets(line, (int)maxlinelen, fp) != NULL) {
linenum++;
p = line;
/* loop until first non-space char or EOL */
while( *p != '\0' && isSpace(p) )
p++;
linelen = strlen(p);
if (linelen >= maxlinelen-1)
return POPT_ERROR_OVERFLOW; /* XXX line too long */
if (*p == '\0' || *p == '\n') continue; /* line is empty */
if (*p == '#') continue; /* comment line */
q = p;
while (*q != '\0' && (!isSpace(q)) && *q != '=')
q++;
if (isSpace(q)) {
/* a space after the name, find next non space */
*q++='\0';
while( *q != '\0' && isSpace(q) ) q++;
}
if (*q == '\0') {
/* single command line option (ie, no name=val, just name) */
q[-1] = '\0'; /* kill off newline from fgets() call */
argvlen += (t = q - p) + (sizeof(" --")-1);
if (argvlen >= maxargvlen) {
maxargvlen = (t > maxargvlen) ? t*2 : maxargvlen*2;
argstr = realloc(argstr, maxargvlen);
if (argstr == NULL) return POPT_ERROR_MALLOC;
}
strlcat(argstr, " --", maxargvlen);
strlcat(argstr, p, maxargvlen);
continue;
}
if (*q != '=')
continue; /* XXX for now, silently ignore bogus line */
/* *q is an equal sign. */
*q++ = '\0';
/* find next non-space letter of value */
while (*q != '\0' && isSpace(q))
q++;
if (*q == '\0')
continue; /* XXX silently ignore missing value */
/* now, loop and strip all ending whitespace */
x = p + linelen;
while (isSpace(--x))
*x = 0; /* null out last char if space (including fgets() NL) */
/* rest of line accept */
t = x - p;
argvlen += t + (sizeof("' --='")-1);
if (argvlen >= maxargvlen) {
maxargvlen = (t > maxargvlen) ? t*2 : maxargvlen*2;
argstr = realloc(argstr, maxargvlen);
if (argstr == NULL) return POPT_ERROR_MALLOC;
}
strlcat(argstr, " --", maxargvlen);
strlcat(argstr, p, maxargvlen);
strlcat(argstr, "=\"", maxargvlen);
strlcat(argstr, q, maxargvlen);
strlcat(argstr, "\"", maxargvlen);
}
*argstrp = argstr;
return 0;
}

View File

@@ -2,7 +2,17 @@
#include "config.h"
#endif
#if defined (__GLIBC__) && defined(__LCLINT__)
/*@-declundef@*/
/*@unchecked@*/
extern __const __int32_t *__ctype_tolower;
/*@unchecked@*/
extern __const __int32_t *__ctype_toupper;
/*@=declundef@*/
#endif
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
@@ -12,19 +22,32 @@
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
#ifdef STDC_HEADERS
# include <stdlib.h>
# include <stddef.h>
#else
# ifdef HAVE_STDLIB_H
# include <stdlib.h>
# endif
#endif
#ifdef HAVE_STRING_H
# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
# include <memory.h>
# endif
# include <string.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#ifdef HAVE_UNISTD_H
# 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> */
#ifndef __GNUC__
#define __attribute__(x)
#endif
#ifdef __NeXT
@@ -34,11 +57,12 @@
#endif
#if defined(__LCLINT__)
/*@-declundef -incondefs -redecl@*/ /* LCL: missing annotation */
/*@only@*/ void * alloca (size_t __size)
/*@-declundef -incondefs @*/ /* LCL: missing annotation */
/*@only@*/ /*@out@*/
void * alloca (size_t __size)
/*@ensures MaxSet(result) == (__size - 1) @*/
/*@*/;
/*@=declundef =incondefs =redecl@*/
/*@=declundef =incondefs @*/
#endif
/* AIX requires this to be the first thing in the file. */
@@ -49,9 +73,9 @@
# ifdef _AIX
#pragma alloca
# else
# if HAVE_ALLOCA
# ifdef HAVE_ALLOCA
# ifndef alloca /* predefined by HP cc +Olibcalls */
char *alloca ();
char *alloca(size_t size);
# endif
# else
# ifdef alloca
@@ -65,18 +89,42 @@ char *alloca ();
#define alloca __builtin_alloca
#endif
/*@-redecl -redef@*/
/*@mayexit@*/ /*@only@*/ char * xstrdup (const char *str)
/*@*/;
/*@=redecl =redef@*/
#ifndef HAVE_STRLCPY
size_t strlcpy(char *d, const char *s, size_t bufsize);
#endif
#ifndef HAVE_STRLCAT
size_t strlcat(char *d, const char *s, size_t bufsize);
#endif
#if HAVE_MCHECK_H && defined(__GNUC__)
#define vmefail() (fprintf(stderr, "virtual memory exhausted.\n"), exit(EXIT_FAILURE), NULL)
#define xstrdup(_str) (strcpy((malloc(strlen(_str)+1) ? : vmefail()), (_str)))
static inline char *
xstrdup(const char *s)
{
size_t memsize = strlen(s) + 1;
char *ptr = malloc(memsize);
if (!ptr) {
fprintf(stderr, "virtual memory exhausted.\n");
exit(EXIT_FAILURE);
}
strlcpy(ptr, s, memsize);
return ptr;
}
#else
#define xstrdup(_str) strdup(_str)
#endif /* HAVE_MCHECK_H && defined(__GNUC__) */
#if HAVE___SECURE_GETENV && !defined(__LCLINT__)
#define getenv(_s) __secure_getenv(_s)
#endif
#if !defined HAVE_SNPRINTF || !defined HAVE_C99_VSNPRINTF
#define snprintf rsync_snprintf
int snprintf(char *str,size_t count,const char *fmt,...);
#endif
#define UNUSED(x) x __attribute__((__unused__))
#define PACKAGE "rsync"
#include "popt.h"

View File

@@ -18,8 +18,8 @@ man: rsync.1 rsyncd.conf.5
rsync.1: rsync.yo
yodl2man -o rsync.1 rsync.yo
-./tweak_manpage_dashes rsync.1
-./tweak_manpage rsync.1
rsyncd.conf.5: rsyncd.conf.yo
yodl2man -o rsyncd.conf.5 rsyncd.conf.yo
-./tweak_manpage_dashes rsyncd.conf.5
-./tweak_manpage rsyncd.conf.5

View File

@@ -4,11 +4,11 @@
* Copyright (C) 1996-2000 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
* Copyright (C) 2003, 2004, 2005, 2006 Wayne Davison
* Copyright (C) 2003-2007 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
@@ -17,8 +17,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
* with this program; if not, visit the http://fsf.org website.
*/
#include "rsync.h"
@@ -60,12 +59,11 @@ 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)
{
char eol[256];
char rembuf[64], eol[128];
const char *units;
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. */
@@ -94,9 +92,14 @@ static void rprint_progress(OFF_T ofs, OFF_T size, struct timeval *now,
units = "kB/s";
}
remain_s = (int) remain % 60;
remain_m = (int) (remain / 60.0) % 60;
remain_h = (int) (remain / 3600.0);
if (remain < 0)
strlcpy(rembuf, " ??:??:??", sizeof rembuf);
else {
snprintf(rembuf, sizeof rembuf, "%4d:%02d:%02d",
(int) (remain / 3600.0),
(int) (remain / 60.0) % 60,
(int) remain % 60);
}
if (is_last) {
snprintf(eol, sizeof eol, " (xfer#%d, to-check=%d/%d)\n",
@@ -105,9 +108,8 @@ static void rprint_progress(OFF_T ofs, OFF_T size, struct timeval *now,
stats.num_files);
} else
strlcpy(eol, "\r", sizeof eol);
rprintf(FCLIENT, "%12s %3d%% %7.2f%s %4d:%02d:%02d%s",
human_num(ofs), pct, rate, units,
remain_h, remain_m, remain_s, eol);
rprintf(FCLIENT, "%12s %3d%% %7.2f%s %s%s",
human_num(ofs), pct, rate, units, rembuf, eol);
}
void end_progress(OFF_T size)

View File

@@ -3,11 +3,11 @@
*
* Copyright (C) 1996-2000 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2003, 2004, 2005, 2006 Wayne Davison
* Copyright (C) 2003-2007 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
@@ -16,16 +16,17 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
* with this program; if not, visit the http://fsf.org website.
*/
#include "rsync.h"
extern int verbose;
extern int dry_run;
extern int do_xfers;
extern int am_server;
extern int do_progress;
extern int inc_recurse;
extern int log_before_transfer;
extern int stdout_format_has_i;
extern int logfile_format_has_i;
@@ -37,6 +38,7 @@ extern int protocol_version;
extern int relative_paths;
extern int preserve_hard_links;
extern int preserve_perms;
extern int preserve_xattrs;
extern int basis_dir_cnt;
extern int make_backups;
extern int cleanup_got_literal;
@@ -47,20 +49,19 @@ extern int keep_partial;
extern int checksum_seed;
extern int inplace;
extern int delay_updates;
extern mode_t orig_umask;
extern struct stats stats;
extern char *stdout_format;
extern char *tmpdir;
extern char *partial_dir;
extern char *basis_dir[];
extern struct file_list *the_file_list;
extern struct file_list *cur_flist, *first_flist, *dir_flist;
extern struct filter_list_struct server_filter_list;
static struct bitbag *delayed_bits = NULL;
static int phase = 0;
static int phase = 0, redoing = 0;
/* We're either updating the basis file or an identical copy: */
static int updating_basis;
/*
* get_tmpname() - create a tmp filename for a given filename
*
@@ -82,7 +83,7 @@ static int updating_basis;
* As long as it's unique, rsync will work.
*/
static int get_tmpname(char *fnametmp, char *fname)
int get_tmpname(char *fnametmp, char *fname)
{
int maxname, added, length = 0;
char *f;
@@ -124,13 +125,13 @@ static int get_tmpname(char *fnametmp, char *fname)
static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
char *fname, int fd, OFF_T total_size)
const char *fname, int fd, OFF_T total_size)
{
static char file_sum1[MD4_SUM_LENGTH];
static char file_sum2[MD4_SUM_LENGTH];
static char file_sum1[MAX_DIGEST_LEN];
static char file_sum2[MAX_DIGEST_LEN];
struct map_struct *mapbuf;
struct sum_struct sum;
int32 len;
int32 len, sum_len;
OFF_T offset = 0;
OFF_T offset2;
char *data;
@@ -151,25 +152,27 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
sum_init(checksum_seed);
if (append_mode) {
if (append_mode > 0) {
OFF_T j;
sum.flength = (OFF_T)sum.count * sum.blength;
if (sum.remainder)
sum.flength -= sum.blength - sum.remainder;
for (j = CHUNK_SIZE; j < sum.flength; j += CHUNK_SIZE) {
if (do_progress)
show_progress(offset, total_size);
sum_update(map_ptr(mapbuf, offset, CHUNK_SIZE),
CHUNK_SIZE);
offset = j;
}
if (offset < sum.flength) {
int32 len = sum.flength - offset;
if (do_progress)
show_progress(offset, total_size);
sum_update(map_ptr(mapbuf, offset, len), len);
offset = sum.flength;
if (append_mode == 2) {
for (j = CHUNK_SIZE; j < sum.flength; j += CHUNK_SIZE) {
if (do_progress)
show_progress(offset, total_size);
sum_update(map_ptr(mapbuf, offset, CHUNK_SIZE),
CHUNK_SIZE);
offset = j;
}
if (offset < sum.flength) {
int32 len = (int32)(sum.flength - offset);
if (do_progress)
show_progress(offset, total_size);
sum_update(map_ptr(mapbuf, offset, len), len);
}
}
offset = sum.flength;
if (fd != -1 && (j = do_lseek(fd, offset, SEEK_SET)) != offset) {
rsyserr(FERROR, errno, "lseek of %s returned %.0f, not %.0f",
full_fname(fname), (double)j, (double)offset);
@@ -258,15 +261,15 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
exit_cleanup(RERR_FILEIO);
}
sum_end(file_sum1);
sum_len = sum_end(file_sum1);
if (mapbuf)
unmap_file(mapbuf);
read_buf(f_in,file_sum2,MD4_SUM_LENGTH);
read_buf(f_in, file_sum2, sum_len);
if (verbose > 2)
rprintf(FINFO,"got file_sum\n");
if (fd != -1 && memcmp(file_sum1, file_sum2, MD4_SUM_LENGTH) != 0)
if (fd != -1 && memcmp(file_sum1, file_sum2, sum_len) != 0)
return 0;
return 1;
}
@@ -277,16 +280,16 @@ static void discard_receive_data(int f_in, OFF_T length)
receive_data(f_in, NULL, -1, 0, NULL, -1, length);
}
static void handle_delayed_updates(struct file_list *flist, char *local_name)
static void handle_delayed_updates(char *local_name)
{
char *fname, *partialptr, numbuf[4];
int i;
char *fname, *partialptr;
int ndx;
for (i = -1; (i = bitbag_next_bit(delayed_bits, i)) >= 0; ) {
struct file_struct *file = flist->files[i];
for (ndx = -1; (ndx = bitbag_next_bit(delayed_bits, ndx)) >= 0; ) {
struct file_struct *file = cur_flist->files[ndx];
fname = local_name ? local_name : f_name(file, NULL);
if ((partialptr = partial_dir_fname(fname)) != NULL) {
if (make_backups && !make_backup(fname))
if (make_backups > 0 && !make_backup(fname))
continue;
if (verbose > 2) {
rprintf(FINFO, "renaming %s to %s\n",
@@ -300,111 +303,118 @@ static void handle_delayed_updates(struct file_list *flist, char *local_name)
full_fname(fname), partialptr);
} else {
if (remove_source_files
|| (preserve_hard_links
&& file->link_u.links)) {
SIVAL(numbuf, 0, i);
send_msg(MSG_SUCCESS,numbuf,4);
}
|| (preserve_hard_links && F_IS_HLINKED(file)))
send_msg_int(MSG_SUCCESS, ndx);
handle_partial_dir(partialptr, PDIR_DELETE);
}
}
}
}
static int get_next_gen_i(int batch_gen_fd, int next_gen_i, int desired_i)
static int get_next_gen_ndx(int fd, int next_gen_ndx, int desired_ndx)
{
while (next_gen_i < desired_i) {
if (next_gen_i >= 0) {
while (next_gen_ndx < desired_ndx) {
if (next_gen_ndx >= 0) {
rprintf(FINFO,
"(No batched update for%s \"%s\")\n",
phase ? " resend of" : "",
f_name(the_file_list->files[next_gen_i], NULL));
redoing ? " resend of" : "",
f_name(cur_flist->files[next_gen_ndx], NULL));
}
next_gen_ndx = read_int(fd);
if (next_gen_ndx == -1) {
if (inc_recurse)
next_gen_ndx = first_flist->prev->used + first_flist->prev->ndx_start;
else
next_gen_ndx = cur_flist->used;
}
next_gen_i = read_int(batch_gen_fd);
if (next_gen_i == -1)
next_gen_i = the_file_list->count;
}
return next_gen_i;
return next_gen_ndx;
}
/**
* 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 recv_files(int f_in, char *local_name)
{
int next_gen_i = -1;
int next_gen_ndx = -1;
int fd1,fd2;
STRUCT_STAT st;
int iflags, xlen;
char *fname, fbuf[MAXPATHLEN];
char xname[MAXPATHLEN];
char fnametmp[MAXPATHLEN];
char *fnamecmp, *partialptr, numbuf[4];
char *fnamecmp, *partialptr;
char fnamecmpbuf[MAXPATHLEN];
uchar fnamecmp_type;
struct file_struct *file;
struct stats initial_stats;
int save_make_backups = make_backups;
int itemizing = am_server ? logfile_format_has_i : stdout_format_has_i;
enum logcode log_code = log_before_transfer ? FLOG : FINFO;
int max_phase = protocol_version >= 29 ? 2 : 1;
int i, recv_ok;
int dflt_perms = (ACCESSPERMS & ~orig_umask);
#ifdef SUPPORT_ACLS
const char *parent_dirname = "";
#endif
int ndx, recv_ok;
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;
}
rprintf(FINFO, "recv_files(%d) starting\n", cur_flist->used);
if (delay_updates)
delayed_bits = bitbag_create(flist->count);
delayed_bits = bitbag_create(cur_flist->used + 1);
updating_basis = inplace;
while (1) {
cleanup_disable();
i = read_int(f_in);
if (i == -1) {
if (read_batch) {
get_next_gen_i(batch_gen_fd, next_gen_i,
flist->count);
next_gen_i = -1;
/* This call also sets cur_flist. */
ndx = read_ndx_and_attrs(f_in, &iflags, &fnamecmp_type,
xname, &xlen);
if (ndx == NDX_DONE) {
if (inc_recurse && first_flist) {
flist_free(first_flist);
if (first_flist)
continue;
}
if (read_batch && cur_flist) {
int high = inc_recurse
? first_flist->prev->used + first_flist->prev->ndx_start
: cur_flist->used;
get_next_gen_ndx(batch_gen_fd, next_gen_ndx, high);
next_gen_ndx = -1;
}
if (++phase > max_phase)
break;
csum_length = SUM_LENGTH;
if (verbose > 2)
rprintf(FINFO, "recv_files phase=%d\n", phase);
if (phase == 2 && delay_updates)
handle_delayed_updates(flist, local_name);
send_msg(MSG_DONE, "", 0);
if (keep_partial && !partial_dir)
make_backups = 0; /* prevents double backup */
if (append_mode) {
append_mode = 0;
sparse_files = 0;
}
handle_delayed_updates(local_name);
send_msg(MSG_DONE, "", 0, 0);
continue;
}
iflags = read_item_attrs(f_in, -1, i, &fnamecmp_type,
xname, &xlen);
if (iflags == ITEM_IS_NEW) /* no-op packet */
continue;
file = flist->files[i];
if (ndx - cur_flist->ndx_start >= 0)
file = cur_flist->files[ndx - cur_flist->ndx_start];
else
file = dir_flist->files[cur_flist->parent_ndx];
fname = local_name ? local_name : f_name(file, fbuf);
if (verbose > 2)
rprintf(FINFO, "recv_files(%s)\n", fname);
#ifdef SUPPORT_XATTRS
if (iflags & ITEM_REPORT_XATTR && !dry_run)
recv_xattr_request(file, f_in);
#endif
if (!(iflags & ITEM_TRANSFER)) {
maybe_log_item(file, iflags, itemizing, xname);
#ifdef SUPPORT_XATTRS
if (preserve_xattrs && iflags & ITEM_REPORT_XATTR && !dry_run)
set_file_attrs(fname, file, NULL, fname, 0);
#endif
continue;
}
if (phase == 2) {
@@ -414,9 +424,31 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
exit_cleanup(RERR_PROTOCOL);
}
stats.current_file_index = i;
if (file->flags & FLAG_FILE_SENT) {
if (csum_length == SHORT_SUM_LENGTH) {
if (keep_partial && !partial_dir)
make_backups = -make_backups; /* prevents double backup */
if (append_mode)
sparse_files = -sparse_files;
append_mode = -append_mode;
csum_length = SUM_LENGTH;
redoing = 1;
}
} else {
if (csum_length != SHORT_SUM_LENGTH) {
if (keep_partial && !partial_dir)
make_backups = -make_backups;
if (append_mode)
sparse_files = -sparse_files;
append_mode = -append_mode;
csum_length = SHORT_SUM_LENGTH;
redoing = 0;
}
}
stats.current_file_index = ndx;
stats.num_transferred_files++;
stats.total_transferred_size += file->length;
stats.total_transferred_size += F_LENGTH(file);
cleanup_got_literal = 0;
if (server_filter_list.head
@@ -428,26 +460,28 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
if (!do_xfers) { /* log the transfer */
log_item(FCLIENT, file, &stats, iflags, NULL);
if (read_batch)
discard_receive_data(f_in, file->length);
discard_receive_data(f_in, F_LENGTH(file));
continue;
}
if (write_batch < 0) {
log_item(FINFO, file, &stats, iflags, NULL);
if (!am_server)
discard_receive_data(f_in, file->length);
discard_receive_data(f_in, F_LENGTH(file));
continue;
}
if (read_batch) {
next_gen_i = get_next_gen_i(batch_gen_fd, next_gen_i, i);
if (i < next_gen_i) {
next_gen_ndx = get_next_gen_ndx(batch_gen_fd, next_gen_ndx, ndx);
if (ndx < next_gen_ndx) {
rprintf(FINFO,
"(Skipping batched update for \"%s\")\n",
fname);
discard_receive_data(f_in, file->length);
discard_receive_data(f_in, F_LENGTH(file));
if (inc_recurse)
send_msg_int(MSG_NO_SEND, ndx);
continue;
}
next_gen_i = -1;
next_gen_ndx = -1;
}
partialptr = partial_dir ? partial_dir_fname(fname) : fname;
@@ -491,7 +525,7 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
} else {
/* Reminder: --inplace && --partial-dir are never
* enabled at the same time. */
if (inplace && make_backups) {
if (inplace && make_backups > 0) {
if (!(fnamecmp = get_backup_name(fname)))
fnamecmp = fname;
} else if (partial_dir && partialptr)
@@ -526,8 +560,10 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
} else if (do_fstat(fd1,&st) != 0) {
rsyserr(FERROR, errno, "fstat %s failed",
full_fname(fnamecmp));
discard_receive_data(f_in, file->length);
discard_receive_data(f_in, F_LENGTH(file));
close(fd1);
if (inc_recurse)
send_msg_int(MSG_NO_SEND, ndx);
continue;
}
@@ -539,8 +575,10 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
*/
rprintf(FERROR,"recv_files: %s is a directory\n",
full_fname(fnamecmp));
discard_receive_data(f_in, file->length);
discard_receive_data(f_in, F_LENGTH(file));
close(fd1);
if (inc_recurse)
send_msg_int(MSG_NO_SEND, ndx);
continue;
}
@@ -553,7 +591,16 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
* mode based on the local permissions and some heuristics. */
if (!preserve_perms) {
int exists = fd1 != -1;
file->mode = dest_mode(file->mode, st.st_mode, exists);
#ifdef SUPPORT_ACLS
const char *dn = file->dirname ? file->dirname : ".";
if (parent_dirname != dn
&& strcmp(parent_dirname, dn) != 0) {
dflt_perms = default_perms_for_dir(dn);
parent_dirname = dn;
}
#endif
file->mode = dest_mode(file->mode, st.st_mode,
dflt_perms, exists);
}
/* We now check to see if we are writing the file "inplace" */
@@ -562,16 +609,20 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
if (fd2 == -1) {
rsyserr(FERROR, errno, "open %s failed",
full_fname(fname));
discard_receive_data(f_in, file->length);
discard_receive_data(f_in, F_LENGTH(file));
if (fd1 != -1)
close(fd1);
if (inc_recurse)
send_msg_int(MSG_NO_SEND, ndx);
continue;
}
} else {
if (!get_tmpname(fnametmp,fname)) {
discard_receive_data(f_in, file->length);
discard_receive_data(f_in, F_LENGTH(file));
if (fd1 != -1)
close(fd1);
if (inc_recurse)
send_msg_int(MSG_NO_SEND, ndx);
continue;
}
@@ -595,9 +646,11 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
if (fd2 == -1) {
rsyserr(FERROR, errno, "mkstemp %s failed",
full_fname(fnametmp));
discard_receive_data(f_in, file->length);
discard_receive_data(f_in, F_LENGTH(file));
if (fd1 != -1)
close(fd1);
if (inc_recurse)
send_msg_int(MSG_NO_SEND, ndx);
continue;
}
@@ -612,7 +665,7 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
/* recv file data */
recv_ok = receive_data(f_in, fnamecmp, fd1, st.st_size,
fname, fd2, file->length);
fname, fd2, F_LENGTH(file));
log_item(log_code, file, &initial_stats, iflags, NULL);
@@ -632,18 +685,18 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
temp_copy_name = NULL;
else
temp_copy_name = partialptr;
finish_transfer(fname, fnametmp, temp_copy_name,
file, recv_ok, 1);
finish_transfer(fname, fnametmp, fnamecmp,
temp_copy_name, file, recv_ok, 1);
if (fnamecmp == partialptr) {
do_unlink(partialptr);
handle_partial_dir(partialptr, PDIR_DELETE);
}
} else if (keep_partial && partialptr
&& handle_partial_dir(partialptr, PDIR_CREATE)) {
finish_transfer(partialptr, fnametmp, NULL,
finish_transfer(partialptr, fnametmp, fnamecmp, NULL,
file, recv_ok, !partial_dir);
if (delay_updates && recv_ok) {
bitbag_set_bit(delayed_bits, i);
bitbag_set_bit(delayed_bits, ndx);
recv_ok = -1;
}
} else {
@@ -654,13 +707,11 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
cleanup_disable();
if (recv_ok > 0) {
if (remove_source_files
|| (preserve_hard_links && file->link_u.links)) {
SIVAL(numbuf, 0, i);
send_msg(MSG_SUCCESS, numbuf, 4);
}
if (remove_source_files || inc_recurse
|| (preserve_hard_links && F_IS_HLINKED(file)))
send_msg_int(MSG_SUCCESS, ndx);
} else if (!recv_ok) {
int msgtype = phase || read_batch ? FERROR : FINFO;
enum logcode msgtype = redoing || read_batch ? FERROR : FINFO;
if (msgtype == FERROR || verbose) {
char *errstr, *redostr, *keptstr;
if (!(keep_partial && partialptr) && !inplace)
@@ -680,16 +731,18 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
"%s: %s failed verification -- update %s%s.\n",
errstr, fname, keptstr, redostr);
}
if (!phase) {
SIVAL(numbuf, 0, i);
send_msg(MSG_REDO, numbuf, 4);
}
if (!redoing) {
send_msg_int(MSG_REDO, ndx);
file->flags |= FLAG_FILE_SENT;
} else if (inc_recurse)
send_msg_int(MSG_NO_SEND, ndx);
}
}
make_backups = save_make_backups;
if (make_backups < 0)
make_backups = -make_backups;
if (phase == 2 && delay_updates) /* for protocol_version < 29 */
handle_delayed_updates(flist, local_name);
handle_delayed_updates(local_name);
if (verbose > 2)
rprintf(FINFO,"recv_files finished\n");

404
rsync.c
View File

@@ -3,11 +3,11 @@
*
* Copyright (C) 1996 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2003, 2004, 2005, 2006 Wayne Davison
* Copyright (C) 2003-2007 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
@@ -16,14 +16,11 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
* with this program; if not, visit the http://fsf.org website.
*/
#include "rsync.h"
#if defined HAVE_ICONV_OPEN && defined HAVE_ICONV_H
#include <iconv.h>
#endif
#include "ifuncs.h"
#if defined HAVE_LIBCHARSET_H && defined HAVE_LOCALE_CHARSET
#include <libcharset.h>
#elif defined HAVE_LANGINFO_H && defined HAVE_NL_LANGINFO
@@ -32,43 +29,57 @@
extern int verbose;
extern int dry_run;
extern int preserve_acls;
extern int preserve_xattrs;
extern int preserve_perms;
extern int preserve_executability;
extern int preserve_times;
extern int omit_dir_times;
extern int am_root;
extern int am_server;
extern int am_sender;
extern int am_generator;
extern int am_starting_up;
extern int allow_8bit_chars;
extern int preserve_uid;
extern int preserve_gid;
extern int protocol_version;
extern int uid_ndx;
extern int gid_ndx;
extern int inc_recurse;
extern int inplace;
extern int flist_eof;
extern int keep_dirlinks;
extern int make_backups;
extern mode_t orig_umask;
extern struct stats stats;
extern struct file_list *cur_flist, *first_flist, *dir_flist;
extern struct chmod_mode_struct *daemon_chmod_modes;
#ifdef ICONV_OPTION
extern char *iconv_opt;
#endif
#if defined HAVE_ICONV_OPEN && defined HAVE_ICONV_H
#ifdef ICONV_CONST
iconv_t ic_chck = (iconv_t)-1;
# ifdef ICONV_OPTION
iconv_t ic_send = (iconv_t)-1, ic_recv = (iconv_t)-1;
# endif
static const char *default_charset(void)
{
#if defined HAVE_LIBCHARSET_H && defined HAVE_LOCALE_CHARSET
# if defined HAVE_LIBCHARSET_H && defined HAVE_LOCALE_CHARSET
return locale_charset();
#elif defined HAVE_LANGINFO_H && defined HAVE_NL_LANGINFO
# elif defined HAVE_LANGINFO_H && defined HAVE_NL_LANGINFO
return nl_langinfo(CODESET);
#else
# else
return ""; /* Works with (at the very least) gnu iconv... */
#endif
# endif
}
void setup_iconv()
void setup_iconv(void)
{
const char *defset = default_charset();
# ifdef ICONV_OPTION
const char *charset;
char *cp;
# endif
if (!am_server && !allow_8bit_chars) {
const char *defset = default_charset();
/* It's OK if this fails... */
ic_chck = iconv_open(defset, defset);
@@ -86,9 +97,210 @@ void setup_iconv()
}
}
}
# ifdef ICONV_OPTION
if (!iconv_opt)
return;
if ((cp = strchr(iconv_opt, ',')) != NULL) {
if (am_server) /* A local transfer needs this. */
iconv_opt = cp + 1;
else
*cp = '\0';
}
if (!*iconv_opt || (*iconv_opt == '.' && iconv_opt[1] == '\0'))
charset = defset;
else
charset = iconv_opt;
if ((ic_send = iconv_open(UTF8_CHARSET, charset)) == (iconv_t)-1) {
rprintf(FERROR, "iconv_open(\"%s\", \"%s\") failed\n",
UTF8_CHARSET, charset);
exit_cleanup(RERR_UNSUPPORTED);
}
if ((ic_recv = iconv_open(charset, UTF8_CHARSET)) == (iconv_t)-1) {
rprintf(FERROR, "iconv_open(\"%s\", \"%s\") failed\n",
charset, UTF8_CHARSET);
exit_cleanup(RERR_UNSUPPORTED);
}
if (verbose > 1) {
rprintf(FINFO, "%s charset: %s\n",
am_server ? "server" : "client",
*charset ? charset : "[LOCALE]");
}
# endif
}
# ifdef ICONV_OPTION
/* This function converts the characters in the "in" xbuf into characters
* in the "out" xbuf. The "len" of the "in" xbuf is used starting from its
* "pos". The "size" of the "out" xbuf restricts how many characters can be
* stored, starting at its "pos+len" position. Note that the last byte of
* the buffer is never used, which reserves space for a terminating '\0'.
* We return a 0 on success or a -1 on error. An error also sets errno to
* E2BIG, EILSEQ, or EINVAL (see below); otherwise errno will be set to 0.
* The "in" xbuf is altered to update "pos" and "len". The "out" xbuf has
* data appended, and its "len" incremented. If ICB_EXPAND_OUT is set in
* "flags", the "out" xbuf will also be allocated if empty, and expanded if
* too small (so E2BIG will not be returned). If ICB_INCLUDE_BAD is set in
* "flags", any badly-encoded chars are included verbatim in the "out" xbuf,
* so EILSEQ will not be returned. Likewise for ICB_INCLUDE_INCOMPLETE with
* respect to an incomplete multi-byte char at the end, which ensures that
* EINVAL is not returned. Anytime "in.pos" is 0 we will reset the iconv()
* state prior to processing the characters. */
int iconvbufs(iconv_t ic, xbuf *in, xbuf *out, int flags)
{
ICONV_CONST char *ibuf;
size_t icnt, ocnt;
char *obuf;
if (!out->size && flags & ICB_EXPAND_OUT)
alloc_xbuf(out, 1024);
if (!in->pos)
iconv(ic, NULL, 0, NULL, 0);
ibuf = in->buf + in->pos;
icnt = in->len;
obuf = out->buf + (out->pos + out->len);
ocnt = out->size - (out->pos + out->len) - 1;
while (icnt) {
while (iconv(ic, &ibuf, &icnt, &obuf, &ocnt) == (size_t)-1) {
if (errno == EINTR)
continue;
if (errno == EINVAL) {
if (!(flags & ICB_INCLUDE_INCOMPLETE))
goto finish;
} else if (errno == EILSEQ) {
if (!(flags & ICB_INCLUDE_BAD))
goto finish;
} else {
size_t opos = obuf - out->buf;
if (!(flags & ICB_EXPAND_OUT)) {
errno = E2BIG;
goto finish;
}
realloc_xbuf(out, out->size + 1024);
obuf = out->buf + opos;
ocnt += 1024;
continue;
}
*obuf++ = *ibuf++;
ocnt--, icnt--;
}
}
errno = 0;
finish:
in->len = icnt;
in->pos = ibuf - in->buf;
out->len = obuf - out->buf - out->pos;
return errno ? -1 : 0;
}
# endif
#endif
int read_ndx_and_attrs(int f_in, int *iflag_ptr, uchar *type_ptr,
char *buf, int *len_ptr)
{
int len, iflags = 0;
struct file_list *flist;
uchar fnamecmp_type = FNAMECMP_FNAME;
int ndx;
read_loop:
while (1) {
ndx = read_ndx(f_in);
if (ndx >= 0)
break;
if (ndx == NDX_DONE)
return ndx;
if (!inc_recurse || am_sender)
goto invalid_ndx;
if (ndx == NDX_FLIST_EOF) {
flist_eof = 1;
send_msg(MSG_FLIST_EOF, "", 0, 0);
continue;
}
ndx = NDX_FLIST_OFFSET - ndx;
if (ndx < 0 || ndx >= dir_flist->used) {
ndx = NDX_FLIST_OFFSET - ndx;
rprintf(FERROR,
"[%s] Invalid dir index: %d (%d - %d)\n",
who_am_i(), ndx, NDX_FLIST_OFFSET,
NDX_FLIST_OFFSET - dir_flist->used + 1);
exit_cleanup(RERR_PROTOCOL);
}
/* Send everything read from f_in to msg_fd_out. */
send_msg_int(MSG_FLIST, ndx);
start_flist_forward(f_in);
if (verbose > 3) {
rprintf(FINFO, "[%s] receiving flist for dir %d\n",
who_am_i(), ndx);
}
flist = recv_file_list(f_in);
flist->parent_ndx = ndx;
stop_flist_forward();
}
iflags = protocol_version >= 29 ? read_shortint(f_in)
: ITEM_TRANSFER | ITEM_MISSING_DATA;
/* Honor the old-style keep-alive indicator. */
if (protocol_version < 30
&& ndx == cur_flist->used && iflags == ITEM_IS_NEW) {
if (am_sender)
maybe_send_keepalive();
goto read_loop;
}
if (!(flist = flist_for_ndx(ndx))) {
invalid_ndx:
rprintf(FERROR,
"Invalid file index: %d (%d - %d) with iflags %x [%s]\n",
ndx, first_flist->ndx_start - 1, first_flist->prev->ndx_end,
iflags, who_am_i());
exit_cleanup(RERR_PROTOCOL);
}
cur_flist = flist;
if (iflags & ITEM_BASIS_TYPE_FOLLOWS)
fnamecmp_type = read_byte(f_in);
*type_ptr = fnamecmp_type;
if (iflags & ITEM_XNAME_FOLLOWS) {
if ((len = read_vstring(f_in, buf, MAXPATHLEN)) < 0)
exit_cleanup(RERR_PROTOCOL);
} else {
*buf = '\0';
len = -1;
}
*len_ptr = len;
if (iflags & ITEM_TRANSFER) {
int i = ndx - cur_flist->ndx_start;
if (i < 0 || !S_ISREG(cur_flist->files[i]->mode)) {
rprintf(FERROR,
"received request to transfer non-regular file: %d [%s]\n",
ndx, who_am_i());
exit_cleanup(RERR_PROTOCOL);
}
}
*iflag_ptr = iflags;
return ndx;
}
/*
free a sums struct
*/
@@ -100,7 +312,8 @@ void free_sums(struct sum_struct *s)
/* This is only called when we aren't preserving permissions. Figure out what
* the permissions should be and return them merged back into the mode. */
mode_t dest_mode(mode_t flist_mode, mode_t stat_mode, int exists)
mode_t dest_mode(mode_t flist_mode, mode_t stat_mode, int dflt_perms,
int exists)
{
int new_mode;
/* If the file already exists, we'll return the local permissions,
@@ -117,56 +330,78 @@ mode_t dest_mode(mode_t flist_mode, mode_t stat_mode, int exists)
new_mode |= (new_mode & 0444) >> 2;
}
} else {
/* Apply the umask and turn off special permissions. */
new_mode = flist_mode & (~CHMOD_BITS | (ACCESSPERMS & ~orig_umask));
/* Apply destination default permissions and turn
* off special permissions. */
new_mode = flist_mode & (~CHMOD_BITS | dflt_perms);
}
return new_mode;
}
int set_file_attrs(char *fname, struct file_struct *file, STRUCT_STAT *st,
int flags)
int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
const char *fnamecmp, int flags)
{
int updated = 0;
STRUCT_STAT st2;
stat_x sx2;
int change_uid, change_gid;
mode_t new_mode = file->mode;
int inherit;
if (!st) {
if (!sxp) {
if (dry_run)
return 1;
if (link_stat(fname, &st2, 0) < 0) {
if (link_stat(fname, &sx2.st, 0) < 0) {
rsyserr(FERROR, errno, "stat %s failed",
full_fname(fname));
return 0;
}
st = &st2;
if (!preserve_perms && S_ISDIR(new_mode)
&& st->st_mode & S_ISGID) {
/* We just created this directory and its setgid
* bit is on, so make sure it stays on. */
new_mode |= S_ISGID;
}
#ifdef SUPPORT_ACLS
sx2.acc_acl = sx2.def_acl = NULL;
#endif
#ifdef SUPPORT_XATTRS
sx2.xattr = NULL;
#endif
sxp = &sx2;
inherit = !preserve_perms;
} else
inherit = !preserve_perms && file->flags & FLAG_DIR_CREATED;
if (inherit && S_ISDIR(new_mode) && sxp->st.st_mode & S_ISGID) {
/* We just created this directory and its setgid
* bit is on, so make sure it stays on. */
new_mode |= S_ISGID;
}
if (!preserve_times || (S_ISDIR(st->st_mode) && omit_dir_times))
#ifdef SUPPORT_ACLS
if (preserve_acls && !S_ISLNK(file->mode) && !ACL_READY(*sxp))
get_acl(fname, sxp);
#endif
#ifdef SUPPORT_XATTRS
if (preserve_xattrs && fnamecmp)
set_xattr(fname, file, fnamecmp, sxp);
if (am_root < 0)
set_stat_xattr(fname, file);
#endif
if (!preserve_times || (S_ISDIR(sxp->st.st_mode) && preserve_times == 1))
flags |= ATTRS_SKIP_MTIME;
if (!(flags & ATTRS_SKIP_MTIME)
&& cmp_time(st->st_mtime, file->modtime) != 0) {
int ret = set_modtime(fname, file->modtime, st->st_mode);
&& cmp_time(sxp->st.st_mtime, file->modtime) != 0) {
int ret = set_modtime(fname, file->modtime, sxp->st.st_mode);
if (ret < 0) {
rsyserr(FERROR, errno, "failed to set times on %s",
full_fname(fname));
return 0;
goto cleanup;
}
if (ret == 0) /* ret == 1 if symlink could not be set */
updated = 1;
}
change_uid = am_root && preserve_uid && st->st_uid != file->uid;
change_gid = preserve_gid && file->gid != GID_NONE
&& st->st_gid != file->gid;
change_uid = am_root && uid_ndx && sxp->st.st_uid != (uid_t)F_OWNER(file);
change_gid = gid_ndx && !(file->flags & FLAG_SKIP_GROUP)
&& sxp->st.st_gid != (gid_t)F_GROUP(file);
#if !defined HAVE_LCHOWN && !defined CHOWN_MODIFIES_SYMLINK
if (S_ISLNK(st->st_mode))
if (S_ISLNK(sxp->st.st_mode))
;
else
#endif
@@ -174,47 +409,59 @@ int set_file_attrs(char *fname, struct file_struct *file, STRUCT_STAT *st,
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);
"set uid of %s from %u to %u\n",
fname, (unsigned)sxp->st.st_uid, F_OWNER(file));
}
if (change_gid) {
rprintf(FINFO,
"set gid of %s from %ld to %ld\n",
fname,
(long)st->st_gid, (long)file->gid);
"set gid of %s from %u to %u\n",
fname, (unsigned)sxp->st.st_gid, F_GROUP(file));
}
}
if (do_lchown(fname,
change_uid ? file->uid : st->st_uid,
change_gid ? file->gid : st->st_gid) != 0) {
if (am_root < 0) {
;
} else if (do_lchown(fname,
change_uid ? (uid_t)F_OWNER(file) : sxp->st.st_uid,
change_gid ? (gid_t)F_GROUP(file) : sxp->st.st_gid) != 0) {
/* shouldn't have attempted to change uid or gid
* unless have the privilege */
rsyserr(FERROR, errno, "%s %s failed",
change_uid ? "chown" : "chgrp",
full_fname(fname));
return 0;
}
goto cleanup;
} else
/* 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 */
if (st->st_mode & (S_ISUID | S_ISGID)) {
link_stat(fname, st,
keep_dirlinks && S_ISDIR(st->st_mode));
if (sxp->st.st_mode & (S_ISUID | S_ISGID)) {
link_stat(fname, &sxp->st,
keep_dirlinks && S_ISDIR(sxp->st.st_mode));
}
updated = 1;
}
if (daemon_chmod_modes && !S_ISLNK(new_mode))
new_mode = tweak_mode(new_mode, daemon_chmod_modes);
#ifdef SUPPORT_ACLS
/* It's OK to call set_acl() now, even for a dir, as the generator
* will enable owner-writability using chmod, if necessary.
*
* If set_acl() changes permission bits in the process of setting
* an access ACL, it changes sxp->st.st_mode so we know whether we
* need to chmod(). */
if (preserve_acls && !S_ISLNK(new_mode) && set_acl(fname, file, sxp) == 0)
updated = 1;
#endif
#ifdef HAVE_CHMOD
if ((st->st_mode & CHMOD_BITS) != (new_mode & CHMOD_BITS)) {
int ret = do_chmod(fname, new_mode);
if (!BITS_EQUAL(sxp->st.st_mode, new_mode, CHMOD_BITS)) {
int ret = am_root < 0 ? 0 : do_chmod(fname, new_mode);
if (ret < 0) {
rsyserr(FERROR, errno,
"failed to set permissions on %s",
full_fname(fname));
return 0;
goto cleanup;
}
if (ret == 0) /* ret == 1 if symlink could not be set */
updated = 1;
@@ -227,6 +474,17 @@ int set_file_attrs(char *fname, struct file_struct *file, STRUCT_STAT *st,
else
rprintf(FCLIENT, "%s is uptodate\n", fname);
}
cleanup:
if (sxp == &sx2) {
#ifdef SUPPORT_ACLS
if (preserve_acls)
free_acl(&sx2);
#endif
#ifdef SUPPORT_XATTRS
if (preserve_xattrs)
free_xattr(&sx2);
#endif
}
return updated;
}
@@ -248,7 +506,8 @@ RETSIGTYPE sig_int(UNUSED(int val))
* attributes (e.g. permissions, ownership, etc.). If partialptr is not
* NULL and the robust_rename() call is forced to copy the temp file, we
* stage the file into the partial-dir and then rename it into place. */
void finish_transfer(char *fname, char *fnametmp, char *partialptr,
void finish_transfer(const char *fname, const char *fnametmp,
const char *fnamecmp, const char *partialptr,
struct file_struct *file, int ok_to_set_time,
int overwriting_basis)
{
@@ -261,11 +520,11 @@ void finish_transfer(char *fname, char *fnametmp, char *partialptr,
goto do_set_file_attrs;
}
if (make_backups && overwriting_basis && !make_backup(fname))
if (make_backups > 0 && overwriting_basis && !make_backup(fname))
return;
/* Change permissions before putting the file into place. */
set_file_attrs(fnametmp, file, NULL,
set_file_attrs(fnametmp, file, NULL, fnamecmp,
ok_to_set_time ? 0 : ATTRS_SKIP_MTIME);
/* move tmp file over real file */
@@ -289,7 +548,7 @@ void finish_transfer(char *fname, char *fnametmp, char *partialptr,
fnametmp = partialptr ? partialptr : fname;
do_set_file_attrs:
set_file_attrs(fnametmp, file, NULL,
set_file_attrs(fnametmp, file, NULL, fnamecmp,
ok_to_set_time ? 0 : ATTRS_SKIP_MTIME);
if (partialptr) {
@@ -301,6 +560,25 @@ void finish_transfer(char *fname, char *fnametmp, char *partialptr,
}
}
struct file_list *flist_for_ndx(int ndx)
{
struct file_list *flist = cur_flist;
if (!flist && !(flist = first_flist))
return NULL;
while (ndx < flist->ndx_start-1) {
if (flist == first_flist)
return NULL;
flist = flist->prev;
}
while (ndx > flist->ndx_end) {
if (!(flist = flist->next))
return NULL;
}
return flist;
}
const char *who_am_i(void)
{
if (am_starting_up)

419
rsync.h
View File

@@ -2,11 +2,11 @@
* Copyright (C) 1996, 2000 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
* Copyright (C) 2003, 2004, 2005, 2006 Wayne Davison
* Copyright (C) 2003-2007 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
@@ -15,8 +15,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
* with this program; if not, visit the http://fsf.org website.
*/
#define False 0
@@ -43,31 +42,55 @@
#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_RDEV_pre28 (1<<2) /* protocols 20 - 27 */
#define XMIT_EXTENDED_FLAGS (1<<2) /* protocols 28 - now */
#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)
#define XMIT_SAME_RDEV_MAJOR (1<<8) /* protocols 28 - now (devices only) */
#define XMIT_NO_CONTENT_DIR (1<<8) /* protocols 30 - now (dirs only) */
#define XMIT_HLINKED (1<<9) /* protocols 28 - now */
#define XMIT_SAME_DEV_pre30 (1<<10) /* protocols 28 - 29 */
#define XMIT_USER_NAME_FOLLOWS (1<<10) /* protocols 30 - now */
#define XMIT_RDEV_MINOR_8_pre30 (1<<11) /* protocols 28 - 29 */
#define XMIT_GROUP_NAME_FOLLOWS (1<<11) /* protocols 30 - now */
#define XMIT_HLINK_FIRST (1<<12) /* protocols 30 - now (HLINKED files only) */
/* These flags are used in the live flist data. */
#define FLAG_TOP_DIR (1<<0)
#define FLAG_SENT (1<<1) /* sender */
#define FLAG_HLINK_EOL (1<<1) /* receiver/generator */
#define FLAG_MOUNT_POINT (1<<2) /* sender/generator */
#define FLAG_DEL_HERE (1<<3) /* receiver/generator */
#define FLAG_HLINK_TOL (1<<4) /* receiver/generator */
#define FLAG_NO_FUZZY (1<<5) /* generator */
#define FLAG_MISSING (1<<6) /* generator */
#define FLAG_TOP_DIR (1<<0) /* sender/receiver/generator */
#define FLAG_FILE_SENT (1<<1) /* sender/receiver/generator */
#define FLAG_DIR_CREATED (1<<1) /* generator */
#define FLAG_CONTENT_DIR (1<<2) /* sender/receiver/generator */
#define FLAG_MOUNT_DIR (1<<3) /* sender/generator */
#define FLAG_DUPLICATE (1<<4) /* sender */
#define FLAG_MISSING_DIR (1<<4) /* generator */
#define FLAG_HLINKED (1<<5) /* receiver/generator (checked on all types) */
#define FLAG_HLINK_FIRST (1<<6) /* receiver/generator (w/FLAG_HLINKED) */
#define FLAG_IMPLIED_DIR (1<<6) /* sender/receiver/generator (dirs only) */
#define FLAG_HLINK_LAST (1<<7) /* receiver/generator */
#define FLAG_HLINK_DONE (1<<8) /* receiver/generator (checked on all types) */
#define FLAG_LENGTH64 (1<<9) /* sender/receiver/generator */
#define FLAG_SKIP_GROUP (1<<10) /* receiver/generator */
/* These flags are passed to functions but not stored. */
#define FLAG_DIVERT_DIRS (1<<16)/* sender */
#define BITS_SET(val,bits) (((val) & (bits)) == (bits))
#define BITS_SETnUNSET(val,onbits,offbits) (((val) & ((onbits)|(offbits))) == (onbits))
#define BITS_EQUAL(b1,b2,mask) (((unsigned)(b1) & (unsigned)(mask)) \
== ((unsigned)(b2) & (unsigned)(mask)))
/* update this if you make incompatible changes */
#define PROTOCOL_VERSION 29
#define PROTOCOL_VERSION 30
/* This is used when working on a new protocol version in CVS, and should
* be a new non-zero value for each CVS change that affects the protocol.
* It must ALWAYS be 0 when the protocol goes final! */
#define SUBPROTOCOL_VERSION 10
/* 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
@@ -90,6 +113,8 @@
#define OLD_PROTOCOL_VERSION 25
#define MAX_PROTOCOL_VERSION 40
#define FILECNT_LOOKAHEAD 1000
#define RSYNC_PORT 873
#define SPARSE_WRITE_SIZE (1024)
@@ -153,6 +178,7 @@
/* These are outside the range of the transmitted flags. */
#define ITEM_MISSING_DATA (1<<16) /* used by log_formatted() */
#define ITEM_DELETED (1<<17) /* used by log_formatted() */
#define ITEM_MATCHED (1<<18) /* used by itemize() */
#define SIGNIFICANT_ITEM_FLAGS (~(\
ITEM_BASIS_TYPE_FOLLOWS | ITEM_XNAME_FOLLOWS | ITEM_LOCAL_CHANGE))
@@ -168,13 +194,22 @@ enum logcode { FNONE=0, FERROR=1, FINFO=2, FLOG=3, FCLIENT=4, FSOCKERR=5 };
enum msgcode {
MSG_DATA=0, /* raw data on the multiplexed stream */
MSG_ERROR=FERROR, MSG_INFO=FINFO, /* remote logging */
MSG_LOG=FLOG, MSG_SOCKERR=FSOCKERR, /* sibling logging */
MSG_LOG=FLOG, MSG_CLIENT=FCLIENT, MSG_SOCKERR=FSOCKERR, /* sibling logging */
MSG_REDO=9, /* reprocess indicated flist index */
MSG_FLIST=20, /* extra file list over sibling socket */
MSG_FLIST_EOF=21,/* we've transmitted all the file lists */
MSG_IO_ERROR=22,/* the sending side had an I/O error */
MSG_NOOP=42, /* a do-nothing message */
MSG_SUCCESS=100,/* successfully updated indicated flist index */
MSG_DELETED=101,/* successfully deleted a file on receiving side */
MSG_NO_SEND=102,/* sender failed to open a file we wanted */
MSG_DONE=86 /* current phase is done */
};
#define NDX_DONE -1
#define NDX_FLIST_EOF -2
#define NDX_FLIST_OFFSET -101
#include "errcode.h"
#include "config.h"
@@ -205,6 +240,12 @@ enum msgcode {
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#ifdef HAVE_INTTYPES_H
# include <inttypes.h>
#endif
#ifdef HAVE_STDINT_H
# include <stdint.h>
#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
@@ -328,6 +369,24 @@ enum msgcode {
# include <limits.h>
#endif
#if defined HAVE_ICONV_OPEN && defined HAVE_ICONV_H
#include <iconv.h>
#ifndef ICONV_CONST
#define ICONV_CONST
#endif
#else
#ifdef ICONV_CONST
#undef ICONV_CONST
#endif
#ifdef ICONV_OPTION
#undef ICONV_OPTION
#endif
#ifdef iconv_t
#undef iconv_t
#endif
#define iconv_t int
#endif
#include <assert.h>
#include "lib/pool_alloc.h"
@@ -344,11 +403,30 @@ enum msgcode {
#define schar char
#endif
#ifndef int16
#if SIZEOF_INT16_T == 2
# define int16 int16_t
#else
# define int16 short
#endif
#endif
#ifndef uint16
#if SIZEOF_UINT16_T == 2
# define uint16 uint16_t
#else
# define uint16 unsigned int16
#endif
#endif
/* Find a variable that is either exactly 32-bits or longer.
* If some code depends on 32-bit truncation, it will need to
* take special action in a "#if SIZEOF_INT32 > 4" section. */
#ifndef int32
#if SIZEOF_INT == 4
#if SIZEOF_INT32_T == 4
# define int32 int32_t
# define SIZEOF_INT32 4
#elif SIZEOF_INT == 4
# define int32 int
# define SIZEOF_INT32 4
#elif SIZEOF_LONG == 4
@@ -371,7 +449,11 @@ enum msgcode {
#endif
#ifndef uint32
#define uint32 unsigned int32
#if SIZEOF_UINT32_T == 4
# define uint32 uint32_t
#else
# define uint32 unsigned int32
#endif
#endif
#if SIZEOF_OFF_T == 8 || !SIZEOF_OFF64_T || !defined HAVE_STRUCT_STAT64
@@ -389,7 +471,10 @@ enum msgcode {
* to ensure that any code that really requires a 64-bit integer has
* it (e.g. the checksum code uses two 32-bit integers for its 64-bit
* counter). */
#if SIZEOF_LONG == 8
#if SIZEOF_INT64_T == 8
# define int64 int64_t
# define SIZEOF_INT64 8
#elif SIZEOF_LONG == 8
# define int64 long
# define SIZEOF_INT64 8
#elif SIZEOF_INT == 8
@@ -419,37 +504,26 @@ enum msgcode {
# define SIZEOF_INT64 SIZEOF_OFF_T
#endif
/* Starting from protocol version 26, we always use 64-bit
* ino_t and dev_t internally, even if this platform does not
* allow files to have 64-bit inums. That's because the
* receiver needs to find duplicate (dev,ino) tuples to detect
* hardlinks, and it might have files coming from a platform
* that has 64-bit inums.
*
* The only exception is if we're on a platform with no 64-bit type at
* all.
*
* Because we use read_longint() to get these off the wire, if you
* transfer devices or hardlinks with dev or inum > 2**32 to a machine
* with no 64-bit types then you will get an overflow error. Probably
* not many people have that combination of machines, and you can
* avoid it by not preserving hardlinks or not transferring device
* nodes. It's not clear that any other behaviour is better.
*
* Note that if you transfer devices from a 64-bit-devt machine (say,
* Solaris) to a 32-bit-devt machine (say, Linux-2.2/x86) then the
* device numbers will be truncated. But it's a kind of silly thing
* to do anyhow.
*
* FIXME: I don't think the code in flist.c has ever worked on a system
* where dev_t is a struct.
*/
struct idev {
int64 inode;
int64 dev;
struct hashtable {
void *nodes;
int32 size, entries;
uint32 node_size;
};
struct ht_int32_node {
void *data;
int32 key;
};
struct ht_int64_node {
void *data;
int64 key;
};
#define HT_NODE(tbl, bkts, i) ((void*)((char*)(bkts) + (i)*(tbl)->node_size))
#define HT_KEY(node, k64) ((k64)? ((struct ht_int64_node*)(node))->key \
: (int64)((struct ht_int32_node*)(node))->key)
#ifndef MIN
#define MIN(a,b) ((a)<(b)?(a):(b))
#endif
@@ -462,8 +536,6 @@ struct idev {
#define MAXHOSTNAMELEN 256
#endif
/* the length of the md4 checksum */
#define MD4_SUM_LENGTH 16
#define SUM_LENGTH 16
#define SHORT_SUM_LENGTH 2
#define BLOCKSUM_BIAS 10
@@ -492,47 +564,104 @@ struct idev {
#define IN_LOOPBACKNET 127
#endif
#define GID_NONE ((gid_t)-1)
#if HAVE_UNIXWARE_ACLS|HAVE_SOLARIS_ACLS|HAVE_HPUX_ACLS
#define ACLS_NEED_MASK 1
#endif
#define HL_CHECK_MASTER 0
#define HL_SKIP 1
struct hlink {
int32 next;
int32 hlindex;
unsigned short link_dest_used;
union file_extras {
int32 num;
uint32 unum;
};
#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 {
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;
char *basename; /* The current item's name (AKA filename) */
char *dirname; /* The directory info inside the transfer */
union {
char *root; /* Sender-side dir info outside transfer */
int depth; /* Receiver-side directory depth info */
} dir;
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 */
const char *dirname; /* The dir info inside the transfer */
time_t modtime; /* When the item was last modified */
uint32 len32; /* Lowest 32 bits of the file's length */
uint16 mode; /* The item's type and permissions */
uint16 flags; /* The FLAG_* bits for this item */
const char basename[1]; /* The basename (AKA filename) follows */
};
extern int file_extra_cnt;
extern int inc_recurse;
extern int uid_ndx;
extern int gid_ndx;
extern int acls_ndx;
extern int xattrs_ndx;
#define FILE_STRUCT_LEN (offsetof(struct file_struct, basename))
#define EXTRA_LEN (sizeof (union file_extras))
#define PTR_EXTRA_CNT ((sizeof (char *) + EXTRA_LEN - 1) / EXTRA_LEN)
#define DEV_EXTRA_CNT 2
#define DIRNODE_EXTRA_CNT 3
#define SUM_EXTRA_CNT ((MAX_DIGEST_LEN + EXTRA_LEN - 1) / EXTRA_LEN)
#define REQ_EXTRA(f,ndx) ((union file_extras*)(f) - (ndx))
#define OPT_EXTRA(f,bump) ((union file_extras*)(f) - file_extra_cnt - 1 - (bump))
#define LEN64_BUMP(f) ((f)->flags & FLAG_LENGTH64 ? 1 : 0)
#define HLINK_BUMP(f) ((f)->flags & (FLAG_HLINKED|FLAG_HLINK_DONE) ? inc_recurse+1 : 0)
#define ACL_BUMP(f) (acls_ndx ? 1 : 0)
/* The length applies to all items. */
#if SIZEOF_INT64 < 8
#define F_LENGTH(f) ((int64)(f)->len32)
#else
#define F_LENGTH(f) ((int64)(f)->len32 + ((f)->flags & FLAG_LENGTH64 \
? (int64)OPT_EXTRA(f, 0)->unum << 32 : 0))
#endif
/* If there is a symlink string, it is always right after the basename */
#define F_SYMLINK(f) ((f)->basename + strlen((f)->basename) + 1)
/* The sending side always has this available: */
#define F_PATHNAME(f) (*(const char**)REQ_EXTRA(f, PTR_EXTRA_CNT))
/* The receiving side always has this available: */
#define F_DEPTH(f) REQ_EXTRA(f, 1)->num
/* When the associated option is on, all entries will have these present: */
#define F_OWNER(f) REQ_EXTRA(f, uid_ndx)->unum
#define F_GROUP(f) REQ_EXTRA(f, gid_ndx)->unum
#define F_ACL(f) REQ_EXTRA(f, acls_ndx)->num
#define F_XATTR(f) REQ_EXTRA(f, xattrs_ndx)->num
#define F_NDX(f) REQ_EXTRA(f, ic_ndx)->num
/* These items are per-entry optional: */
#define F_HL_GNUM(f) OPT_EXTRA(f, LEN64_BUMP(f))->num /* non-dirs */
#define F_HL_PREV(f) OPT_EXTRA(f, LEN64_BUMP(f)+inc_recurse)->num /* non-dirs */
#define F_DIR_NODE_P(f) (&OPT_EXTRA(f, LEN64_BUMP(f) \
+ DIRNODE_EXTRA_CNT - 1)->num) /* sender dirs */
#define F_DIR_RELNAMES_P(f) (&OPT_EXTRA(f, LEN64_BUMP(f) + DIRNODE_EXTRA_CNT \
+ PTR_EXTRA_CNT - 1)->num) /* sender dirs */
#define F_DIR_DEFACL(f) OPT_EXTRA(f, LEN64_BUMP(f))->unum /* receiver dirs */
#define F_DIR_DEV_P(f) (&OPT_EXTRA(f, LEN64_BUMP(f) + ACL_BUMP(f) \
+ DEV_EXTRA_CNT - 1)->unum) /* receiver dirs */
/* This optional item might follow an F_HL_*() item.
* (Note: a device doesn't need to check LEN64_BUMP(f).) */
#define F_RDEV_P(f) (&OPT_EXTRA(f, HLINK_BUMP(f) + 2 - 1)->unum)
/* The sum is only present on regular files. */
#define F_SUM(f) ((char*)OPT_EXTRA(f, LEN64_BUMP(f) + HLINK_BUMP(f) \
+ SUM_EXTRA_CNT - 1))
/* Some utility defines: */
#define F_IS_ACTIVE(f) (f)->basename[0]
#define F_IS_HLINKED(f) ((f)->flags & FLAG_HLINKED)
#define F_HLINK_NOT_FIRST(f) BITS_SETnUNSET((f)->flags, FLAG_HLINKED, FLAG_HLINK_FIRST)
#define F_HLINK_NOT_LAST(f) BITS_SETnUNSET((f)->flags, FLAG_HLINKED, FLAG_HLINK_LAST)
/* These access the F_DIR_DEV_P() and F_RDEV_P() values: */
#define DEV_MAJOR(a) (a)[0]
#define DEV_MINOR(a) (a)[1]
/* These access the F_DIRS_NODE_P() values: */
#define DIR_PARENT(a) (a)[0]
#define DIR_FIRST_CHILD(a) (a)[1]
#define DIR_NEXT_SIBLING(a) (a)[2]
/*
* Start the flist array at FLIST_START entries and grow it
* by doubling until FLIST_LINEAR then grow by FLIST_LINEAR
@@ -541,27 +670,30 @@ struct file_struct {
#define FLIST_LINEAR (FLIST_START * 512)
/*
* Extent size for allocation pools A minimum size of 128KB
* 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
* (when they happen). Smaller sizes increase the chance of
* freed allocations freeing whole extents.
*/
#define FILE_EXTENT (256 * 1024)
#define HLINK_EXTENT (128 * 1024)
#define NORMAL_EXTENT (256 * 1024)
#define SMALL_EXTENT (128 * 1024)
#define WITH_HLINK 1
#define WITHOUT_HLINK 0
#define FLIST_TEMP (1<<1)
struct file_list {
struct file_struct **files;
struct file_list *next, *prev;
struct file_struct **files, **sorted;
alloc_pool_t file_pool;
alloc_pool_t hlink_pool;
int count;
int malloced;
int low, high;
void *pool_boundary;
int used, malloced;
int low, high; /* 0-relative index values excluding empties */
int ndx_start; /* the start offset for inc_recurse mode */
int ndx_end; /* the end offset for inc_recurse mode */
int parent_ndx; /* dir_flist index of parent directory */
int in_progress, to_redo;
};
#define SUMFLG_SAME_OFFSET (1<<0)
@@ -615,10 +747,12 @@ struct map_struct {
#define MATCHFLG_SENDER_SIDE (1<<16)/* rule applies to the sending side */
#define MATCHFLG_RECEIVER_SIDE (1<<17)/* rule applies to the receiving side */
#define MATCHFLG_CLEAR_LIST (1<<18)/* this item is the "!" token */
#define MATCHFLG_PERISHABLE (1<<19)/* perishable if parent dir goes away */
#define MATCHFLGS_FROM_CONTAINER (MATCHFLG_ABS_PATH | MATCHFLG_INCLUDE \
| MATCHFLG_DIRECTORY | MATCHFLG_SENDER_SIDE \
| MATCHFLG_NEGATE | MATCHFLG_RECEIVER_SIDE)
| MATCHFLG_NEGATE | MATCHFLG_RECEIVER_SIDE \
| MATCHFLG_PERISHABLE)
struct filter_struct {
struct filter_struct *next;
@@ -645,7 +779,7 @@ struct stats {
int64 matched_data;
int64 flist_buildtime;
int64 flist_xfertime;
int flist_size;
int64 flist_size;
int num_files;
int num_transferred_files;
int current_file_index;
@@ -653,24 +787,85 @@ struct stats {
struct chmod_mode_struct;
#define EMPTY_ITEM_LIST {NULL, 0, 0}
typedef struct {
void *items;
size_t count;
size_t malloced;
} item_list;
#define EXPAND_ITEM_LIST(lp, type, incr) \
(type*)expand_item_list(lp, sizeof (type), #type, incr)
#define EMPTY_XBUF {NULL, 0, 0, 0}
typedef struct {
char *buf;
size_t pos; /* pos = read pos in the buf */
size_t len; /* len = chars following pos */
size_t size; /* size = total space in buf */
} xbuf;
#define INIT_XBUF(xb, str, ln, sz) (xb).buf = (str), (xb).len = (ln), (xb).size = (sz), (xb).pos = 0
#define INIT_XBUF_STRLEN(xb, str) (xb).buf = (str), (xb).len = strlen((xb).buf), (xb).size = (-1), (xb).pos = 0
/* This one is used to make an output xbuf based on a char[] buffer: */
#define INIT_CONST_XBUF(xb, bf) (xb).buf = (bf), (xb).size = sizeof (bf), (xb).len = (xb).pos = 0
#define ICB_EXPAND_OUT (1<<0)
#define ICB_INCLUDE_BAD (1<<1)
#define ICB_INCLUDE_INCOMPLETE (1<<2)
#define RL_EOL_NULLS (1<<0)
#define RL_DUMP_COMMENTS (1<<1)
#define RL_CONVERT (1<<2)
typedef struct {
char is_dot_dir;
char fname[1]; /* has variable size */
} relnamecache;
#include "byteorder.h"
#include "lib/mdfour.h"
#include "lib/mdigest.h"
#include "lib/wildmatch.h"
#include "lib/permstring.h"
#include "lib/addrinfo.h"
#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> */
#ifndef __GNUC__
#define __attribute__(x)
#else
# if __GNUC__ <= 2
# define NORETURN
# endif
#endif
#define UNUSED(x) x __attribute__((__unused__))
#ifndef NORETURN
#define NORETURN __attribute__((__noreturn__))
#endif
typedef struct {
STRUCT_STAT st;
#ifdef SUPPORT_ACLS
struct rsync_acl *acc_acl; /* access ACL */
struct rsync_acl *def_acl; /* default ACL */
#endif
#ifdef SUPPORT_XATTRS
item_list *xattr;
#endif
} stat_x;
#define ACL_READY(sx) ((sx).acc_acl != NULL)
#define XATTR_READY(sx) ((sx).xattr != NULL)
#include "proto.h"
#ifndef SUPPORT_XATTRS
#define x_stat(fn,fst,xst) do_stat(fn,fst)
#define x_lstat(fn,fst,xst) do_lstat(fn,fst)
#define x_fstat(fd,fst,xst) do_fstat(fd,fst)
#endif
/* We have replacement versions of these if they're missing. */
#ifndef HAVE_ASPRINTF
int asprintf(char **ptr, const char *format, ...);
@@ -687,7 +882,7 @@ int vsnprintf(char *str, size_t count, const char *fmt, va_list args);
#if !defined HAVE_SNPRINTF || !defined HAVE_C99_VSNPRINTF
#define snprintf rsync_snprintf
int snprintf(char *str,size_t count,const char *fmt,...);
int snprintf(char *str, size_t count, const char *fmt,...);
#endif
@@ -826,9 +1021,11 @@ extern int errno;
#define NS(s) ((s)?(s):"<NULL>")
/* Convenient wrappers for malloc and realloc. Use them. */
#define new(type) ((type *)malloc(sizeof(type)))
#define new_array(type, num) ((type *)_new_array(sizeof(type), (num)))
#define realloc_array(ptr, type, num) ((type *)_realloc_array((ptr), sizeof(type), (num)))
#define new(type) ((type*)malloc(sizeof (type)))
#define new0(type) ((type*)calloc(1, sizeof (type)))
#define new_array(type, num) ((type*)_new_array((num), sizeof (type), 0))
#define new_array0(type, num) ((type*)_new_array((num), sizeof (type), 1))
#define realloc_array(ptr, type, num) ((type*)_realloc_array((ptr), sizeof(type), (num)))
/* use magic gcc attributes to catch format errors */
void rprintf(enum logcode , const char *, ...)

525
rsync.yo
View File

@@ -1,5 +1,5 @@
mailto(rsync-bugs@samba.org)
manpage(rsync)(1)(6 Nov 2006)()()
manpage(rsync)(1)(11 Oct 2007)()()
manpagename(rsync)(faster, flexible replacement for rcp)
manpagesynopsis()
@@ -21,7 +21,7 @@ rsync [OPTION]... rsync://[USER@]HOST[:PORT]/SRC [DEST]
manpagedescription()
rsync is a program that behaves in much the same way that rcp does,
Rsync is a program that behaves in much the same way that rcp does,
but has many more options and uses the rsync remote-update protocol to
greatly speed up file transfers when the destination file is being
updated.
@@ -31,6 +31,12 @@ differences between two sets of files across the network connection, using
an efficient checksum-search algorithm described in the technical
report that accompanies this package.
Rsync finds files that need to be transferred using a "quick check" algorithm
that looks for files that have changed in size or in last-modified time (by
default). Any changes in the other preserved attributes (as requested by
options) are made on the destination file directly when the quick check
indicates that the file's data does not need to be updated.
Some of the additional features of rsync are:
itemization(
@@ -143,33 +149,29 @@ See the following section for more details.
manpagesection(ADVANCED USAGE)
The syntax for requesting multiple files from a remote host involves using
quoted spaces in the SRC. Some examples:
The syntax for requesting multiple files from a remote host is done by
specifying additional remote-host args in the same style as the first,
or with the hostname omitted. For instance, all these work:
quote(tt(rsync host::'modname/dir1/file1 modname/dir2/file2' /dest))
quote(tt(rsync -av host:file1 :file2 host:file{3,4} /dest/)nl()
tt(rsync -av host::modname/file{1,2} host::modname/file3 /dest/)nl()
tt(rsync -av host::modname/file1 ::modname/file{3,4}))
This would copy file1 and file2 into /dest from an rsync daemon. Each
additional arg must include the same "modname/" prefix as the first one,
and must be preceded by a single space. All other spaces are assumed
to be a part of the filenames.
Older versions of rsync required using quoted spaces in the SRC, like these
examples:
quote(tt(rsync -av host:'dir1/file1 dir2/file2' /dest))
quote(tt(rsync -av host:'dir1/file1 dir2/file2' /dest)nl()
tt(rsync host::'modname/dir1/file1 modname/dir2/file2' /dest))
This would copy file1 and file2 into /dest using a remote shell. This
word-splitting is done by the remote shell, so if it doesn't work it means
that the remote shell isn't configured to split its args based on
whitespace (a very rare setting, but not unknown). If you need to transfer
a filename that contains whitespace, you'll need to either escape the
whitespace in a way that the remote shell will understand, or use wildcards
in place of the spaces. Two examples of this are:
This word-splitting still works (by default) in the latest rsync, but is
not as easy to use as the first method.
quote(
tt(rsync -av host:'file\ name\ with\ spaces' /dest)nl()
tt(rsync -av host:file?name?with?spaces /dest)nl()
)
If you need to transfer a filename that contains whitespace, you can either
specify the bf(--protect-args) (bf(-s)) option, or you'll need to escape
the whitespace in a way that the remote shell will understand. For
instance:
This latter example assumes that your shell passes through unmatched
wildcards. If it complains about "no match", put the name in quotes.
quote(tt(rsync -av host:'file\ name\ with\ spaces' /dest))
manpagesection(CONNECTING TO AN RSYNC DAEMON)
@@ -213,6 +215,21 @@ environment variable RSYNC_PROXY to a hostname:port pair pointing to
your web proxy. Note that your web proxy's configuration must support
proxy connections to port 873.
You may also establish a daemon connection using a program as a proxy by
setting the environment variable RSYNC_CONNECT_PROG to the commands you
wish to run in place of making a direct socket connection. The string may
contain the escape "%H" to represent the hostname specified in the rsync
command (so use "%%" if you need a single "%" in your string). For
example:
verb( export RSYNC_CONNECT_PROG='ssh proxyhost nc %H 873'
rsync -av targethost1::module/src/ /dest/
rsync -av rsync:://targethost2/module/src/ /dest/ )
The command specifed above uses ssh to run nc (netcat) on a proxyhost,
which forwards all data to port 873 (the rsync daemon) on the targethost
(%H).
manpagesection(USING RSYNC-DAEMON FEATURES VIA A REMOTE-SHELL CONNECTION)
It is sometimes useful to use various features of an rsync daemon (such as
@@ -301,7 +318,7 @@ to the detailed description below for a complete description. verb(
-q, --quiet suppress non-error messages
--no-motd suppress daemon-mode MOTD (see caveat)
-c, --checksum skip based on checksum, not mod-time & size
-a, --archive archive mode; same as -rlptgoD (no -H)
-a, --archive archive mode; equals -rlptgoD (no -H,-A,-X)
--no-OPTION turn off an implied OPTION (e.g. --no-D)
-r, --recursive recurse into directories
-R, --relative use relative path names
@@ -312,6 +329,7 @@ to the detailed description below for a complete description. verb(
-u, --update skip files that are newer on the receiver
--inplace update destination files in-place
--append append data onto shorter files
--append-verify --append w/old data in file cheksum
-d, --dirs transfer directories without recursing
-l, --links copy symlinks as symlinks
-L, --copy-links transform symlink into referent file/dir
@@ -323,14 +341,17 @@ to the detailed description below for a complete description. verb(
-p, --perms preserve permissions
-E, --executability preserve executability
--chmod=CHMOD affect file and/or directory permissions
-A, --acls preserve ACLs (implies -p)
-X, --xattrs preserve extended attributes
-o, --owner preserve owner (super-user only)
-g, --group preserve group
--devices preserve device files (super-user only)
--specials preserve special files
-D same as --devices --specials
-t, --times preserve times
-O, --omit-dir-times omit directories when preserving times
-t, --times preserve modification times
-O, --omit-dir-times omit directories from --times
--super receiver attempts super-user activities
--fake-super store/recover privileged attrs using xattrs
-S, --sparse handle sparse files efficiently
-n, --dry-run show what would have been transferred
-W, --whole-file copy files whole (without rsync algorithm)
@@ -345,6 +366,7 @@ to the detailed description below for a complete description. verb(
--delete delete extraneous files from dest dirs
--delete-before receiver deletes before transfer (default)
--delete-during receiver deletes during xfer, not before
--delete-delay find deletions during, delete after
--delete-after receiver deletes after transfer, not before
--delete-excluded also delete excluded files from dest dirs
--ignore-errors delete even if there are I/O errors
@@ -368,6 +390,7 @@ to the detailed description below for a complete description. verb(
--link-dest=DIR hardlink to files in DIR when unchanged
-z, --compress compress file data during the transfer
--compress-level=NUM explicitly set compression level
--skip-compress=LIST skip compressing files with suffix in LIST
-C, --cvs-exclude auto-ignore files in the same way CVS does
-f, --filter=RULE add a file-filtering RULE
-F same as --filter='dir-merge /.rsync-filter'
@@ -378,6 +401,7 @@ to the detailed description below for a complete description. verb(
--include-from=FILE read include patterns from FILE
--files-from=FILE read list of source-file names from FILE
-0, --from0 all *from/filter files are delimited by 0s
-s, --protect-args no space-splitting; wildcard chars only
--address=ADDRESS bind address for outgoing socket to daemon
--port=PORT specify double-colon alternate port number
--sockopts=OPTIONS specify custom TCP options
@@ -391,13 +415,14 @@ to the detailed description below for a complete description. verb(
--out-format=FORMAT output updates using the specified FORMAT
--log-file=FILE log what we're doing to the specified FILE
--log-file-format=FMT log updates using the specified FMT
--password-file=FILE read password from FILE
--password-file=FILE read daemon-access password from FILE
--list-only list the files instead of copying them
--bwlimit=KBPS limit I/O bandwidth; KBytes per second
--write-batch=FILE write a batched update to FILE
--only-write-batch=FILE like --write-batch but w/o updating dest
--read-batch=FILE read a batched update from FILE
--protocol=NUM force an older protocol version to be used
--iconv=CONVERT_SPEC request charset conversion of filesnames
--checksum-seed=NUM set block/file checksum seed (advanced)
-4, --ipv4 prefer IPv4
-6, --ipv6 prefer IPv6
@@ -463,19 +488,19 @@ by the client at the start of a daemon transfer. This suppresses the
message-of-the-day (MOTD) text, but it also affects the list of modules
that the daemon sends in response to the "rsync host::" request (due to
a limitation in the rsync protocol), so omit this option if you want to
request the list of modules from the deamon.
request the list of modules from the daemon.
dit(bf(-I, --ignore-times)) Normally rsync will skip any files that are
already the same size and have the same modification time-stamp.
already the same size and have the same modification timestamp.
This option turns off this "quick check" behavior, causing all files to
be updated.
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
bf(--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.
dit(bf(--size-only)) This modifies rsync's "quick check" algorithm for
finding files that need to be transferred, changing it from the default of
transferring files with either a changed size or a changed last-modified
time to just looking for files that have changed in size. This is useful
when starting to use rsync after using another mirroring system which may
not preserve timestamps exactly.
dit(bf(--modify-window)) When comparing two timestamps, rsync treats the
timestamps as being equal if they differ by no more than the modify-window
@@ -485,20 +510,26 @@ transferring to or from an MS Windows FAT filesystem (which represents
times with a 2-second resolution), bf(--modify-window=1) is useful
(allowing times to differ by up to 1 second).
dit(bf(-c, --checksum)) This forces the sender to checksum em(every)
regular file using a 128-bit MD4 checksum. It does this during the initial
file-system scan as it builds the list of all available files. The receiver
then checksums its version of each file (if it exists and it has the same
size as its sender-side counterpart) in order to decide which files need to
be updated: files with either a changed size or a changed checksum are
selected for transfer. Since this whole-file checksumming of all files on
both sides of the connection occurs in addition to the automatic checksum
verifications that occur during a file's transfer, this option can be quite
slow.
dit(bf(-c, --checksum)) This changes the way rsync checks if the files have
been changed and are in need of a transfer. Without this option, rsync
uses a "quick check" that (by default) checks if each file's size and time
of last modification match between the sender and receiver. This option
changes this to compare a 128-bit MD4 checksum for each file that has a
matching size. Generating the checksums means that both sides will expend
a lot of disk I/O reading all the data in the files in the transfer (and
this is prior to any reading that will be done to transfer changed files),
so this can slow things down significantly.
Note that rsync always verifies that each em(transferred) file was correctly
reconstructed on the receiving side by checking its whole-file checksum, but
that automatic after-the-transfer verification has nothing to do with this
The sending side generates its checksums while it is doing the file-system
scan that builds the list of the available files. The receiver generates
its checksums when it is scanning for changed files, and will checksum any
file that has the same size as the corresponding sender's file: files with
either a changed size or a changed checksum are selected for transfer.
Note that rsync always verifies that each em(transferred) file was
correctly reconstructed on the receiving side by checking a whole-file
checksum that is generated when as the file is transferred, but that
automatic after-the-transfer verification has nothing to do with this
option's before-the-transfer "Does this file need to be updated?" check.
dit(bf(-a, --archive)) This is equivalent to bf(-rlptgoD). It is a quick
@@ -533,6 +564,25 @@ details).
dit(bf(-r, --recursive)) This tells rsync to copy directories
recursively. See also bf(--dirs) (bf(-d)).
Beginning with rsync 3.0.0, the recursive algorithm used is now an
incremental scan that uses much less memory than before and begins the
transfer after the scanning of the first few directories have been
completed. This incremental scan only affects our recursion algorithm, and
does not change a non-recursive transfer. It is also only possible when
both ends of the transfer are at least version 3.0.0.
Some options require rsync to know the full file list, so these options
disable the incremental recursion mode. These include: bf(--delete-before),
bf(--delete-after), bf(--prune-empty-dirs), and bf(--delay-updates).
Because of this, the default delete mode when you specify bf(--delete) is now
bf(--delete-during) when both ends of the connection are at least 3.0.0
(use bf(--del) or bf(--delete-during) to request this improved deletion mode
explicitly). See also the bf(--delete-delay) option that is a better choice
than using bf(--delete-after).
Incremental recursion can be disabled using the bf(--no-inc-recursive)
option or its shorter bf(--no-i-r) alias.
dit(bf(-R, --relative)) Use relative paths. This means that the full path
names specified on the command line are sent to the server rather than
just the last parts of the filenames. This is particularly useful when
@@ -547,10 +597,23 @@ machine. If instead you used
quote(tt( rsync -avR /foo/bar/baz.c remote:/tmp/))
then a file named /tmp/foo/bar/baz.c would be created on the remote
machine -- the full path name is preserved. To limit the amount of
path information that is sent, you have a couple options: (1) With
a modern rsync on the sending side (beginning with 2.6.7), you can
insert a dot and a slash into the source path, like this:
machine, preserving its full path. These extra path elements are called
"implied directories" (i.e. the "foo" and the "foo/bar" directories in the
above example).
Beginning with rsync 3.0.0, rsync always sends these implied directories as
real directories in the file list, even if a path element is really a
symlink on the sending side. This prevents some really unexpected
behaviors when copying the full path of a file that you didn't realize had
a symlink in its path. If you want to duplicate a server-side symlink,
include both the symlink via its path, and referent directory via its real
path. If you're dealing with an older rsync on the sending side, you may
need to use the bf(--no-implied-dirs) option.
It is also possible to limit the amount of path information that is sent as
implied directories for each path you specify. With a modern rsync on the
sending side (beginning with 2.6.7), you can insert a dot and a slash into
the source path, like this:
quote(tt( rsync -avR /foo/./bar/baz.c remote:/tmp/))
@@ -563,8 +626,8 @@ quote(tt( (cd /foo; rsync -avR bar/baz.c remote:/tmp/) ))
(Note that the parens put the two commands into a sub-shell, so that the
"cd" command doesn't remain in effect for future commands.)
If you're pulling files, use this idiom (which doesn't work with an
rsync daemon):
If you're pulling files from an older rsync, use this idiom (but only
for a non-daemon transfer):
quote(
tt( rsync -avR --rsync-path="cd /foo; rsync" \ )nl()
@@ -578,7 +641,7 @@ means that the corresponding path elements on the destination system are
left unchanged if they exist, and any missing implied directories are
created with default attributes. This even allows these implied path
elements to have big differences, such as being a symlink to a directory on
one side of the transfer, and a real directory on the other side.
the receiving side.
For instance, if a command-line arg or a files-from entry told rsync to
transfer the file "path/foo/file", the directories "path" and "path/foo"
@@ -591,15 +654,9 @@ ends up being created in "path/bar". Another way to accomplish this link
preservation is to use the bf(--keep-dirlinks) option (which will also
affect symlinks to directories in the rest of the transfer).
In a similar but opposite scenario, if the transfer of "path/foo/file" is
requested and "path/foo" is a symlink on the sending side, running without
bf(--no-implied-dirs) would cause rsync to transform "path/foo" on the
receiving side into an identical symlink, and then attempt to transfer
"path/foo/file", which might fail if the duplicated symlink did not point
to a directory on the receiving side. Another way to avoid this sending of
a symlink as an implied directory is to use bf(--copy-unsafe-links), or
bf(--copy-dirlinks) (both of which also affect symlinks in the rest of the
transfer -- see their descriptions for full details).
When pulling files from an rsync older than 3.0.0, you may need to use this
option if the sending side has a symlink in the path you request and you
wish the implied directories to be transferred as normal directories.
dit(bf(-b, --backup)) With this option, preexisting destination files are
renamed as each file is transferred or deleted. You can control where the
@@ -610,7 +667,7 @@ Note that if you don't specify bf(--backup-dir), (1) the
bf(--omit-dir-times) option will be implied, and (2) if bf(--delete) is
also in effect (without bf(--delete-excluded)), rsync will add a "protect"
filter-rule for the backup suffix to the end of all your existing excludes
(e.g. -f "P *~"). This will prevent previously backed-up files from being
(e.g. bf(-f "Pp *~")). This will prevent previously backed-up files from being
deleted. Note that if you are supplying your own filter rules, you may
need to manually insert your own exclude/protect rule somewhere higher up
in the list so that it has a high enough priority to be effective (e.g., if
@@ -630,16 +687,15 @@ if no -bf(-backup-dir) was specified, otherwise it is an empty string.
dit(bf(-u, --update)) This forces rsync to skip any files which exist on
the destination and have a modified time that is newer than the source
file. (If an existing destination file has a modify time equal to the
file. (If an existing destination file has a modification time equal to the
source file's, it will be updated if the sizes are different.)
In the current implementation of bf(--update), a difference of file format
between the sender and receiver 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).
Note that this does not affect the copying of symlinks or other special
files. Also, a difference of file format between the sender and receiver
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
where the destination has a file, the transfer would occur regardless of
the timestamps.
dit(bf(--inplace)) This causes rsync not to create a new copy of the file
and then move it into place. Instead rsync will overwrite the existing
@@ -667,13 +723,22 @@ receiving user.
dit(bf(--append)) This causes rsync to update a file by appending data onto
the end of the file, which presumes that the data that already exists on
the receiving side is identical with the start of the file on the sending
side. If that is not true, the file will fail the checksum test, and the
resend will do a normal bf(--inplace) update to correct the mismatched data.
Only files on the receiving side that are shorter than the corresponding
file on the sending side (as well as new files) are sent.
Implies bf(--inplace), but does not conflict with bf(--sparse) (though the
bf(--sparse) option will be auto-disabled if a resend of the already-existing
data is required).
side. Any files that are the same size or shorter on the receiving size
are skipped. Files that do not yet exist on the receiving side are also
sent, since they are considered to have 0 length. Implies bf(--inplace),
but does not conflict with bf(--sparse) (since it is always extending a
file's length).
dit(bf(--append-verify)) This works just like the bf(--append) option, but
the existing data on the receiving side is included in the full-file
checksum verification step, which will cause a file to be resent if the
final verification step fails (rsync uses a normal, non-appending
bf(--inplace) transfer for the resend).
Note: prior to rsync 3.0.0, the bf(--append) option worked like
bf(--append-verify), so if you are interacting with an older rsync (or the
transfer is using a protocol prior to 30), specifying either append option
will initiate an bf(--append-verify) transfer.
dit(bf(-d, --dirs)) Tell the sending side to include any directories that
are encountered. Unlike bf(--recursive), a directory's contents are not copied
@@ -706,7 +771,7 @@ which point outside the copied tree. All absolute symlinks are
also ignored. Using this option in conjunction with bf(--relative) may
give unexpected results.
dit(bf(-K, --copy-dirlinks)) This option causes the sending side to treat
dit(bf(-k, --copy-dirlinks)) This option causes the sending side to treat
a symlink to a directory as though it were a real directory. This is
useful if you don't want symlinks to non-directories to be affected, as
they would be using bf(--copy-links).
@@ -741,6 +806,12 @@ as though they were separate files.
Note that rsync can only detect hard links if both parts of the link
are in the list of files being sent.
If incremental recursion is active (see bf(--recursive)), rsync may transfer
a missing hard-linked file before it finds that another link for the file
exists elsewhere in the hierarchy. This does not affect the accuracy of
the transfer, just its efficiency. One way to avoid this is to disable
incremental recursion using the bf(--no-inc-recursive) option.
dit(bf(-p, --perms)) This option causes the receiving rsync to set the
destination permissions to be the same as the source permissions. (See
also the bf(--chmod) option for a way to modify what rsync considers to
@@ -753,7 +824,9 @@ quote(itemization(
permissions, though the bf(--executability) option might change just
the execute permission for the file.
it() New files get their "normal" permission bits set to the source
file's permissions masked with the receiving end's umask setting, and
file's permissions masked with the receiving directory's default
permissions (either the receiving process's umask, or the permissions
specified via the destination directory's default ACL), and
their special permission bits disabled except in the case where a new
directory inherits a setgid bit from its parent directory.
))
@@ -784,9 +857,11 @@ The preservation of the destination's setgid bit on newly-created
directories when bf(--perms) is off was added in rsync 2.6.7. Older rsync
versions erroneously preserved the three special permission bits for
newly-created files when bf(--perms) was off, while overriding the
destination's setgid bit setting on a newly-created directory. (Keep in
mind that it is the version of the receiving rsync that affects this
behavior.)
destination's setgid bit setting on a newly-created directory. Default ACL
observance was added to the ACL patch for rsync 2.6.7, so older (or
non-ACL-enabled) rsyncs use the umask even if default ACLs are present.
(Keep in mind that it is the version of the receiving rsync that affects
these behaviors.)
dit(bf(-E, --executability)) This option causes rsync to preserve the
executability (or non-executability) of regular files when bf(--perms) is
@@ -804,6 +879,22 @@ quote(itemization(
If bf(--perms) is enabled, this option is ignored.
dit(bf(-A, --acls)) This option causes rsync to update the destination
ACLs to be the same as the source ACLs.
The option also implies bf(--perms).
The source and destination systems must have compatible ACL entries for this
option to work properly. See the bf(--fake-super) option for a way to backup
and restore ACLs that are not compatible.
dit(bf(-X, --xattrs)) This option causes rsync to update the remote
extended attributes to be the same as the local ones.
For systems that support extended-attribute namespaces, a copy being done by a
super-user copies all namespaces except system.*. A normal user only copies
the user.* namespace. To be able to backup and restore non-user namespaces as
a normal user, see the bf(--fake-super) option.
dit(bf(--chmod)) This option tells rsync to apply one or more
comma-separated "chmod" strings to the permission of the files in the
transfer. The resulting value is treated as though it was the permissions
@@ -826,9 +917,9 @@ permission value can be applied to the files in the transfer.
dit(bf(-o, --owner)) This option causes rsync to set the owner of the
destination file to be the same as the source file, but only if the
receiving rsync is being run as the super-user (see also the bf(--super)
option to force rsync to attempt super-user activities).
Without this option, the owner is set to the invoking user on the
receiving side.
and bf(--fake-super) options).
Without this option, the owner of new and/or transferred files are set to
the invoking user on the receiving side.
The preservation of ownership will associate matching names by default, but
may fall back to using the ID number in some circumstances (see also the
@@ -849,7 +940,7 @@ default, but may fall back to using the ID number in some circumstances
dit(bf(--devices)) This option causes rsync to transfer character and
block device files to the remote system to recreate these devices.
This option has no effect if the receiving rsync is not run as the
super-user and bf(--super) is not specified.
super-user (see also the bf(--super) and bf(--fake-super) options).
dit(bf(--specials)) This option causes rsync to transfer special files
such as named sockets and fifos.
@@ -879,6 +970,37 @@ also for ensuring that you will get errors if the receiving side isn't
being running as the super-user. To turn off super-user activities, the
super-user can use bf(--no-super).
dit(bf(--fake-super)) When this option is enabled, rsync simulates
super-user activities by saving/restoring the privileged attributes via
special extended attributes that are attached to each file (as needed). This
includes the file's owner and group (if it is not the default), the file's
device info (device & special files are created as empty text files), and
any permission bits that we won't allow to be set on the real file (e.g.
the real file gets u-s,g-s,o-t for safety) or that would limit the owner's
access (since the real super-user can always access/change a file, the
files we create can always be accessed/changed by the creating user).
This option also handles ACLs (if bf(--acls) was specified) and non-user
extended attributes (if bf(--xattrs) was specified).
This is a good way to backup data withou using a super-user, and to store
ACLs from incompatible systems.
The bf(--fake-super) option only affects the side where the option is used.
To affect the remote side of a remote-shell connection, specify an rsync
path:
quote(tt( rsync -av --rsync-path="rsync --fake-super" /src/ host:/dest/))
Since there is only one "side" in a local copy, this option affects both
the sending and recieving of files. You'll need to specify a copy using
"localhost" if you need to avoid this, possibly using the "lsh" shell
script (from the support directory) as a substitute for an actual remote
shell (see bf(--rsh)).
This option is overridden by both bf(--super) and bf(--no-super).
See also the "fake super" setting in the daemon's rsyncd.conf file.
dit(bf(-S, --sparse)) Try to handle sparse files efficiently so they take
up less space on the destination. Conflicts with bf(--inplace) because it's
not possible to overwrite data in a sparse fashion.
@@ -890,7 +1012,7 @@ correctly and ends up corrupting the files.
dit(bf(-n, --dry-run)) This tells rsync to not do any file transfers,
instead it will just report the actions it would have taken.
dit(bf(-W, --whole-file)) With this option the incremental rsync algorithm
dit(bf(-W, --whole-file)) With this option the delta transfer 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
destination machines is higher than the bandwidth to disk (especially when the
@@ -919,11 +1041,19 @@ dit(bf(--existing, --ignore-non-existing)) This tells rsync to skip
creating files (including directories) that do not exist
yet on the destination. If this option is
combined with the bf(--ignore-existing) option, no files will be updated
(which can be useful if all you want to do is to delete extraneous files).
(which can be useful if all you want to do is delete extraneous files).
dit(bf(--ignore-existing)) This tells rsync to skip updating files that
already exist on the destination (this does em(not) ignore existing
directores, or nothing would get done). See also bf(--existing).
directories, or nothing would get done). See also bf(--existing).
This option can be useful for those doing backups using the bf(--link-dest)
option when they need to continue a backup run that got interrupted. Since
a bf(--link-dest) run is copied into a new directory hierarchy (when it is
used properly), using bf(--ignore existing) will ensure that the
already-handled files don't get tweaked (which avoids a change in
permissions on the hard-linked files). This does mean that this option
is only looking at the existing files in the destination hierarchy itself.
dit(bf(--remove-source-files)) This tells rsync to remove from the sending
side the files (meaning non-directories) that are a part of the transfer
@@ -941,8 +1071,8 @@ option or mark the rules as only matching on the sending side (see the
include/exclude modifiers in the FILTER RULES section).
Prior to rsync 2.6.7, this option would have no effect unless bf(--recursive)
was in effect. Beginning with 2.6.7, deletions will also occur when bf(--dirs)
(bf(-d)) is in effect, but only for directories whose contents are being copied.
was enabled. Beginning with 2.6.7, deletions will also occur when bf(--dirs)
(bf(-d)) is enabled, but only for directories whose contents are being copied.
This option can be dangerous if used incorrectly! It is a very good idea
to run first using the bf(--dry-run) option (bf(-n)) to see what files would be
@@ -956,20 +1086,22 @@ destination. You can override this with the bf(--ignore-errors) option.
The bf(--delete) option may be combined with one of the --delete-WHEN options
without conflict, as well as bf(--delete-excluded). However, if none of the
--delete-WHEN options are specified, rsync will currently choose the
bf(--delete-before) algorithm. A future version may change this to choose the
bf(--delete-during) algorithm. See also bf(--delete-after).
--delete-WHEN options are specified, rsync will choose the
bf(--delete-during) algorithm when talking to an rsync 3.0.0 or newer, and
the bf(--delete-before) algorithm when talking to an older rsync. See also
bf(--delete-delay) and bf(--delete-after).
dit(bf(--delete-before)) Request that the file-deletions on the receiving
side be done before the transfer starts. This is the default if bf(--delete)
or bf(--delete-excluded) is specified without one of the --delete-WHEN options.
side be done before the transfer starts.
See bf(--delete) (which is implied) for more details on file-deletion.
Deleting before the transfer is helpful if the filesystem is tight for space
and removing extraneous files would help to make the transfer possible.
However, it does introduce a delay before the start of the transfer,
and this delay might cause the transfer to timeout (if bf(--timeout) was
specified).
specified). It also forces rsync to use the old, non-incremental recursion
algorithm that requires rsync to scan all the files in the transfer into
memory at once (see bf(--recursive)).
dit(bf(--delete-during, --del)) Request that the file-deletions on the
receiving side be done incrementally as the transfer happens. This is
@@ -977,11 +1109,22 @@ a faster method than choosing the before- or after-transfer algorithm,
but it is only supported beginning with rsync version 2.6.4.
See bf(--delete) (which is implied) for more details on file-deletion.
dit(bf(--delete-delay)) Request that the file-deletions on the receiving
side be computed during the transfer, and then removed after the transfer
completes. If the number of removed files overflows an internal buffer, a
temporary file will be created on the receiving side to hold the names (it
is removed while open, so you shouldn't see it during the transfer). If
the creation of the temporary file fails, rsync will try to fall back to
using bf(--delete-after) (which it cannot do if bf(--recursive) is doing an
incremental scan).
dit(bf(--delete-after)) Request that the file-deletions on the receiving
side be done after the transfer has completed. This is useful if you
are sending new per-directory merge files as a part of the transfer and
you want their exclusions to take effect for the delete phase of the
current transfer.
current transfer. It also forces rsync to use the old, non-incremental
recursion algorithm that requires rsync to scan all the files in the
transfer into memory at once (see bf(--recursive)).
See bf(--delete) (which is implied) for more details on file-deletion.
dit(bf(--delete-excluded)) In addition to deleting the files on the
@@ -1004,8 +1147,15 @@ using bf(--delete-after), and it used to be non-functional unless the
bf(--recursive) option was also enabled.
dit(bf(--max-delete=NUM)) This tells rsync not to delete more than NUM
files or directories (NUM must be non-zero).
This is useful when mirroring very large trees to prevent disasters.
files or directories. If that limit is exceeded, a warning is output
and rsync exits with an error code of 25 (new for 3.0.0).
Also new for version 3.0.0, you may specify bf(--max-delete=0) to be warned
about any extraneous files in the destination without removing any of them.
Older clients interpreted this as "unlimited", so if you don't know what
version the client is, you can use the less obvious bf(--max-delete=-1) as
a backward-compatible way to specify that no deletions be allowed (though
older versions didn't warn when the limit was exceeded).
dit(bf(--max-size=SIZE)) This tells rsync to avoid transferring any
file that is larger than the specified SIZE. The SIZE value can be
@@ -1077,20 +1227,21 @@ communicate.
One tricky example is to set a different default directory on the remote
machine for use with the bf(--relative) option. For instance:
quote(tt( rsync -avR --rsync-path="cd /a/b && rsync" hst:c/d /e/))
quote(tt( rsync -avR --rsync-path="cd /a/b && rsync" host:c/d /e/))
dit(bf(-C, --cvs-exclude)) This is a useful shorthand for excluding a
broad range of files that you often don't want to transfer between
systems. It uses the same algorithm that CVS uses to determine if
systems. It uses a similar algorithm to CVS to determine if
a file should be ignored.
The exclude list is initialized to:
The exclude list is initialized to exclude the following items (these
initial items are marked as perishable -- see the FILTER RULES section):
quote(quote(tt(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/)))
.del-* *.a *.olb *.o *.obj *.so *.exe *.Z *.elc *.ln core .svn/ .bzr/)))
then files listed in a $HOME/.cvsignore are added to the list and any
then, files listed in a $HOME/.cvsignore are added to the list and any
files listed in the CVSIGNORE environment variable (all cvsignore names
are delimited by whitespace).
@@ -1179,7 +1330,7 @@ quote(itemization(
bf(--files-from), as does bf(--no-R) and all other options).
))
The file names that are read from the FILE are all relative to the
The filenames that are read from the FILE are all relative to the
source dir -- any leading slashes are removed and no ".." references are
allowed to go higher than the source dir. For example, take this
command:
@@ -1217,6 +1368,21 @@ merged files specified in a bf(--filter) rule.
It does not affect bf(--cvs-exclude) (since all names read from a .cvsignore
file are split on whitespace).
If the bf(--iconv) and bf(--protect-args) options are specified and the
bf(--files-from) filenames are being sent from one host to another, the
filenames will be translated from the sending host's charset to the
receiving host's charset.
dit(bf(-s, --protect-args)) This option sends all filenames and some options to
the remote rsync without allowing the remote shell to interpret them. This
means that spaces are not split in names, and any non-wildcard special
characters are not translated (such as ~, $, ;, &, etc.). Wildcards are
expanded on the remote host by rsync (instead of the shell doing it).
If you use this option with bf(--iconv), the args will also be translated
from the local to the remote character set. The translation happens before
wild-cards are expanded. See also the bf(--files-from) option.
dit(bf(-T, --temp-dir=DIR)) This option instructs rsync to use DIR as a
scratch directory when creating temporary copies of the files transferred
on the receiving side. The default behavior is to create each temporary
@@ -1309,6 +1475,12 @@ and the attributes updated.
If a match is not found, a basis file from one of the em(DIR)s will be
selected to try to speed up the transfer.
This option works best when copying into an empty destination hierarchy, as
rsync treats existing files as definitive (so it never looks in the link-dest
dirs when a destination file already exists), and as malleable (so it might
change the attributes of a destination file, which affects all the hard-linked
versions).
Note that if you combine this option with bf(--ignore-times), rsync will not
link any files together because it only links identical files together as a
substitute for transferring the file, never as an additional check after the
@@ -1331,10 +1503,40 @@ be achieved by using a compressing remote shell or a compressing transport
because it takes advantage of the implicit information in the matching data
blocks that are not explicitly sent over the connection.
See the bf(--skip-compress) option for the default list of file suffixes
that will not be compressed.
dit(bf(--compress-level=NUM)) Explicitly set the compression level to use
(see bf(--compress)) instead of letting it default. If NUM is non-zero,
the bf(--compress) option is implied.
dit(bf(--skip-compress=LIST)) Override the list of file suffixes that will
not be compressed. The bf(LIST) should be one or more file suffixes
(without the dot) separated by slashes (/).
You may specify an empty string to indicate that no file should be skipped.
Simple character-class matching is supported: each must consist of a list
of letters inside the square brackets (e.g. no special classes, such as
"[:alpha:]", are supported).
The characters asterisk (*) and question-mark (?) have no special meaning.
Here's an example that specifies 6 suffixes to skip (since 1 of the 5 rules
matches 2 suffixes):
verb( --skip-compress=gz/jpg/mp[34]/7z/bz2)
The default list of suffixes that will not be compressed is this (several
of these are newly added for 3.0.0):
verb( gz/zip/z/rpm/deb/iso/bz2/t[gb]z/7z/mp[34]/mov/avi/ogg/jpg/jpeg)
This list will be replaced by your bf(--skip-compress) list in all but one
situation: a copy from a daemon rsync will add your skipped suffixes to
its list of non-compressing files (and its list may be configured to a
different default).
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
at both ends.
@@ -1389,8 +1591,8 @@ if the receiving rsync is at least version 2.6.7 (you can use bf(-vv)
with older versions of rsync, but that also turns on the output of other
verbose messages).
The "%i" escape has a cryptic output that is 9 letters long. The general
format is like the string bf(YXcstpogz), where bf(Y) is replaced by the
The "%i" escape has a cryptic output that is 11 letters long. The general
format is like the string bf(YXcstpoguax), where bf(Y) is replaced by the
type of update being done, bf(X) is replaced by the file-type, and the
other letters represent attributes that may be output if they are being
modified.
@@ -1430,16 +1632,20 @@ quote(itemization(
by the file transfer.
it() A bf(t) means the modification time is different and is being updated
to the sender's value (requires bf(--times)). An alternate value of bf(T)
means that the time will be set to the transfer time, which happens
anytime a symlink is transferred, or when a file or device is transferred
without bf(--times).
means that the modification time will be set to the transfer time, which happens
anytime a symlink is transferred, or when a regular file or device is
transferred without bf(--times).
it() A bf(p) means the permissions are different and are being updated to
the sender's value (requires bf(--perms)).
it() An bf(o) means the owner is different and is being updated to the
sender's value (requires bf(--owner) and super-user privileges).
it() A bf(g) means the group is different and is being updated to the
sender's value (requires bf(--group) and the authority to set the group).
it() The bf(z) slot is reserved for future use.
it() The bf(u) slot is reserved for reporting update (access) time changes
(a feature that is not yet released).
it() The bf(a) means that the ACL information changed.
it() The bf(x) slot is reserved for reporting extended attribute changes
(a feature that is not yet released).
))
One other output is possible: when deleting files, the "%i" will output
@@ -1563,7 +1769,7 @@ after it has served its purpose.
Note that if bf(--whole-file) is specified (or implied), any partial-dir
file that is found for a file that is being updated will simply be removed
(since
rsync is sending files without using the incremental rsync algorithm).
rsync is sending files without using the delta transfer algorithm).
Rsync will create the em(DIR) if it is missing (just the last dir -- not
the whole path). This makes it easy to use a relative path (such as
@@ -1576,7 +1782,7 @@ rule at the end of all your existing excludes. This will prevent the
sending of any partial-dir files that may exist on the sending side, and
will also prevent the untimely deletion of partial-dir items on the
receiving side. An example: the above bf(--partial-dir) option would add
the equivalent of "bf(--exclude=.rsync-partial/)" at the end of any other
the equivalent of "bf(-f '-p .rsync-partial/')" at the end of any other
filter rules.
If you are supplying your own exclude rules, you may need to add your own
@@ -1618,7 +1824,7 @@ each file's destination directory, but if you've specified the
bf(--partial-dir) option, that directory will be used instead. See the
comments in the bf(--partial-dir) section for a discussion of how this
".~tmp~" dir will be excluded from the transfer, and what you can do if
you wnat rsync to cleanup old ".~tmp~" dirs that might be lying around.
you want rsync to cleanup old ".~tmp~" dirs that might be lying around.
Conflicts with bf(--inplace) and bf(--append).
This option uses more memory on the receiving side (one bit per file
@@ -1663,7 +1869,7 @@ that any superfluous files and directories in the destination are removed
quote( rsync -avm --del --include='*.pdf' -f 'hide,! */' src/ dest)
If you didn't want to remove superfluous destination files, the more
time-honored options of "--include='*/' --exclude='*'" would work fine
time-honored options of "bf(--include='*/' --exclude='*')" would work fine
in place of the hide-filter (if that is more natural to you).
dit(bf(--progress)) This option tells rsync to print information
@@ -1681,7 +1887,7 @@ sender's file, which is being reconstructed at a rate of 110.64 kilobytes
per second, and the transfer will finish in 4 seconds if the current rate
is maintained until the end.
These statistics can be misleading if the incremental transfer algorithm is
These statistics can be misleading if the delta transfer algorithm is
in use. For example, if the sender's file consists of the basis file
followed by additional data, the reported rate will probably drop
dramatically when the receiver gets to the literal data, and the transfer
@@ -1704,12 +1910,14 @@ dit(bf(-P)) The bf(-P) option is equivalent to bf(--partial) bf(--progress). It
purpose is to make it much easier to specify these two options for a long
transfer that may be interrupted.
dit(bf(--password-file)) This option allows you to provide a password
in a file for accessing a remote rsync daemon. Note that this option
is only useful when accessing an rsync daemon 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.
dit(bf(--password-file)) This option allows you to provide a password in a
file for accessing an rsync daemon. The file must not be world readable.
It should contain just the password as a single line.
When accessing an rsync daemon using a remote shell as the transport, this
option only comes into effect after the remote shell finishes its
authentication (i.e. if you have also specified a password in the daemon's
config file).
dit(bf(--list-only)) This option will cause the source files to be listed
instead of transferred. This option is inferred if there is a single source
@@ -1767,11 +1975,34 @@ bf(--read-batch) option, you should use "--protocol=28" when creating the
batch file to force the older protocol version to be used in the batch
file (assuming you can't upgrade the rsync on the reading system).
dit(bf(--iconv=CONVERT_SPEC)) Rsync can convert filenames between character
sets using this option. Using a CONVERT_SPEC of "." tells rsync to look up
the default character-set via the locale setting. Alternately, you can
fully specify what conversion to do by giving a local and a remote charset
separated by a comma (local first), e.g. bf(--iconv=utf8,iso88591).
Finally, you can specify a CONVERT_SPEC of "-" to turn off any conversion.
The default setting of this option is site-specific, and can also be
affected via the RSYNC_ICONV environment variable.
If you specify the bf(--protect-args) option (bf(-s)), rsync will translate
the filenames you specify on the command-line that are being sent to the
remote host. See also the bf(--files-from) option.
Note that rsync does not do any conversion of names in filter files
(including include/exclude files). It is up to you to ensure that you're
specifying matching rules that can match on both sides of the transfer.
For instance, you can specify extra include/exclude rules if there are
filename differences on the two sides that need to be accounted for.
dit(bf(-4, --ipv4) or bf(-6, --ipv6)) Tells rsync to prefer IPv4/IPv6
when creating sockets. This only affects sockets that rsync has direct
control over, such as the outgoing socket when directly contacting an
rsync daemon. See also these options in the bf(--daemon) mode section.
If rsync was complied without support for IPv6, the bf(--ipv6) option
will have no effect. The bf(--version) output will tell you if this
is the case.
dit(bf(--checksum-seed=NUM)) Set the MD4 checksum seed to the integer
NUM. This 4 byte checksum seed is included in each block and file
MD4 checksum calculation. By default the checksum seed is generated
@@ -1854,6 +2085,10 @@ versions of Linux to work around an IPv6 bug in the kernel (if you see
an "address already in use" error when nothing else is using the port,
try specifying bf(--ipv6) or bf(--ipv4) when starting the daemon).
If rsync was complied without support for IPv6, the bf(--ipv6) option
will have no effect. The bf(--version) output will tell you if this
is the case.
dit(bf(-h, --help)) When specified after bf(--daemon), print a short help
page describing the options available for starting an rsync daemon.
enddit()
@@ -1930,20 +2165,19 @@ itemization(
particular spot in the hierarchy of files, otherwise it is matched
against the end of the pathname. This is similar to a leading ^ in
regular expressions.
Thus "/foo" would match a file named "foo" at either the "root of the
Thus "/foo" would match a name of "foo" at either the "root of the
transfer" (for a global rule) or in the merge-file's directory (for a
per-directory rule).
An unqualified "foo" would match any file or directory named "foo"
anywhere in the tree because the algorithm is applied recursively from
the
An unqualified "foo" would match a name of "foo" anywhere in the
tree because the algorithm is applied recursively from the
top down; it behaves as if each path component gets a turn at being the
end of the file name. Even the unanchored "sub/foo" would match at
end of the filename. Even the unanchored "sub/foo" would match at
any point in the hierarchy where a "foo" was found within a directory
named "sub". See the section on ANCHORING INCLUDE/EXCLUDE PATTERNS for
a full discussion of how to specify a pattern that matches at the root
of the transfer.
it() if the pattern ends with a / then it will only match a
directory, not a file, link, or device.
directory, not a regular file, symlink, or device.
it() rsync chooses between doing a simple string match and wildcard
matching by checking if the pattern contains one of these three wildcard
characters: '*', '?', and '[' .
@@ -1961,9 +2195,9 @@ itemization(
can actually be any portion of a path from the starting directory on
down.)
it() a trailing "dir_name/***" will match both the directory (as if
"dir_name/" had been specified) and all the files in the directory
(as if "dir_name/**" had been specified). (This behavior is new for
version 2.6.7.)
"dir_name/" had been specified) and everything in the directory
(as if "dir_name/**" had been specified). This behavior was added in
version 2.6.7.
)
Note that, when using the bf(--recursive) (bf(-r)) option (which is implied by
@@ -2004,7 +2238,7 @@ tt(- *)nl()
Here are some examples of exclude/include matching:
itemization(
it() "- *.o" would exclude all filenames matching *.o
it() "- *.o" would exclude all names matching *.o
it() "- /foo" would exclude a file (or directory) named foo in the
transfer-root directory
it() "- foo/" would exclude any directory named foo
@@ -2078,13 +2312,13 @@ itemization(
The following modifiers are accepted after a "+" or "-":
itemization(
it() A "/" specifies that the include/exclude rule should be matched
it() A bf(/) specifies that the include/exclude rule should be matched
against the absolute pathname of the current item. For example,
"-/ /etc/passwd" would exclude the passwd file any time the transfer
was sending files from the "/etc" directory, and "-/ subdir/foo"
would always exclude "foo" when it is in a dir named "subdir", even
if "foo" is at the root of the current transfer.
it() A "!" specifies that the include/exclude should take effect if
it() A bf(!) specifies that the include/exclude should take effect if
the pattern fails to match. For instance, "-! */" would exclude all
non-directories.
it() A bf(C) is used to indicate that all the global CVS-exclude rules
@@ -2101,6 +2335,11 @@ itemization(
being deleted. See the bf(s) modifier for more info. See also the
protect (P) and risk (R) rules, which are an alternate way to
specify receiver-side includes/excludes.
it() A bf(p) indicates that a rule is perishable, meaning that it is
ignored in directories that are being deleted. For instance, the bf(-C)
option's default rules that exclude things like "CVS" and "*.o" are
marked as perishable, and will not prevent a directory that was removed
on the source from being deleted on the destination.
)
Per-directory rules are inherited in all subdirectories of the directory
@@ -2188,7 +2427,7 @@ that follow the :C instead of being subservient to all your rules. To
affect the other CVS exclude rules (i.e. the default list of exclusions,
the contents of $HOME/.cvsignore, and the value of $CVSIGNORE) you should
omit the bf(-C) command-line option and instead insert a "-C" rule into
your filter rules; e.g. "--filter=-C".
your filter rules; e.g. "bf(--filter=-C)".
manpagesection(LIST-CLEARING FILTER RULE)
@@ -2434,7 +2673,7 @@ unsafe links to be omitted altogether. (Note that you must specify
bf(--links) for bf(--safe-links) to have any effect.)
Symbolic links are considered unsafe if they are absolute symlinks
(start with bf(/)), empty, or if they contain enough bf("..")
(start with bf(/)), empty, or if they contain enough ".."
components to ascend from the directory being copied.
Here's a summary of how the symlink options are interpreted. The list is
@@ -2513,6 +2752,8 @@ startdit()
dit(bf(CVSIGNORE)) The CVSIGNORE environment variable supplements any
ignore patterns in .cvsignore files. See the bf(--cvs-exclude) option for
more details.
dit(bf(RSYNC_ICONV)) Specify a default bf(--iconv) setting using this
environment variable.
dit(bf(RSYNC_RSH)) The RSYNC_RSH environment variable allows you to
override the default shell used as the transport for rsync. Command line
options are permitted after the command name, just as in the bf(-e) option.
@@ -2551,12 +2792,12 @@ values
see also the comments on the bf(--delete) option
Please report bugs! See the website at
Please report bugs! See the web site at
url(http://rsync.samba.org/)(http://rsync.samba.org/)
manpagesection(VERSION)
This man page is current for version 2.6.9 of rsync.
This man page is current for version 3.0.0pre2 of rsync.
manpagesection(INTERNAL OPTIONS)

View File

@@ -1,5 +1,5 @@
mailto(rsync-bugs@samba.org)
manpage(rsyncd.conf)(5)(6 Nov 2006)()()
manpage(rsyncd.conf)(5)(11 Oct 2007)()()
manpagename(rsyncd.conf)(configuration file for rsync in daemon mode)
manpagesynopsis()
@@ -17,7 +17,7 @@ manpagesection(FILE FORMAT)
The file consists of modules and parameters. A module begins with the
name of the module in square brackets and continues until the next
module begins. Modules contain parameters of the form 'name = value'.
module begins. Modules contain parameters of the form "name = value".
The file is line-based -- that is, each newline-terminated line represents
either a comment, a module name or a parameter.
@@ -85,7 +85,8 @@ usually contains site information and any legal notices. The default
is no motd file.
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. If the file already exists, the rsync
daemon will abort rather than overwrite the file.
dit(bf(port)) You can override the default port the daemon will listen on
by specifying this value (defaults to 873). This is ignored if the daemon
@@ -149,7 +150,7 @@ 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/uploaded by adding an exclude rule to the rsyncd.conf file
(e.g. "exclude = /etc/**"). Note that having the exclusion affect uploads
(e.g. "bf(exclude = /etc/**)"). Note that having the exclusion affect uploads
is a relatively new feature in rsync, so make sure your daemon is
at least 2.6.3 to effect this. Also note that it is safest to exclude a
directory and all its contents combining the rule "/some/dir/" with the
@@ -161,7 +162,8 @@ sure).
dit(bf(max connections)) The "max connections" option allows you to
specify the maximum number of simultaneous connections you will allow.
Any clients connecting when the maximum has been reached will receive a
message telling them to try later. The default is 0 which means no limit.
message telling them to try later. The default is 0, which means no limit.
A negative value disables the module.
See also the "lock file" option.
dit(bf(log file)) When the "log file" option is set to a non-empty
@@ -226,6 +228,11 @@ 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".
dit(bf(fake super)) Setting "fake super = yes" for a module causes the
daemon side to behave as if the bf(--fake-user) command-line option had
been specified. This allows the full attributes of a file to be stored
without having to have the daemon actually running as root.
dit(bf(filter)) The "filter" option allows you to specify a space-separated
list of filter rules that the daemon will not allow to be read or written.
This is only superficially equivalent to the client specifying these
@@ -402,7 +409,7 @@ format used for logging file transfers when transfer logging is enabled.
The format is a text string containing embedded single-character escape
sequences prefixed with a percent (%) character. An optional numeric
field width may also be specified between the percent and the escape
letter (e.g. "%-50n %8l %07p").
letter (e.g. "bf(%-50n %8l %07p)").
The default log format is "%o %h [%a] %m (%u) %f %l", and a "%t [%p] "
is always prefixed when using the "log file" option.
@@ -483,7 +490,10 @@ The "dont compress" option takes a space-separated list of
case-insensitive wildcard patterns. Any source filename matching one
of the patterns will not be compressed during transfer.
The default setting is tt(*.gz *.tgz *.zip *.z *.rpm *.deb *.iso *.bz2 *.tbz)
See the bf(--skip-compress) option in the bf(rsync)(1) manpage for the list
of file suffixes that are not compressed by default. Specifying a value
for the bf(dont compress) option changes the default when the daemon is
the sender.
dit(bf(pre-xfer exec), bf(post-xfer exec)) You may specify a command to be run
before and/or after the transfer. If the bf(pre-xfer exec) command fails, the
@@ -604,7 +614,7 @@ url(http://rsync.samba.org/)(http://rsync.samba.org/)
manpagesection(VERSION)
This man page is current for version 2.6.9 of rsync.
This man page is current for version 3.0.0pre2 of rsync.
manpagesection(CREDITS)

View File

@@ -49,8 +49,8 @@
# This script must be invoked from the build directory.
# A scratch directory, 'testtmp', is created in the build directory to
# hold working files.
# A scratch directory, 'testtmp', is used in the build directory to
# hold per-test subdirectories.
# This script also uses the $loglevel environment variable. 1 is the
# default value, and 10 the most verbose. You can set this from the
@@ -181,12 +181,15 @@ else
echo " preserve_scratch=no"
fi
# Check if setfacl is around and if it supports the -k or -s option.
if setfacl --help 2>&1 | grep ' -k,\|\[-[a-z]*k' >/dev/null; then
# Check if setacl/setfacl is around and if it supports the -k or -s option.
if setacl -k u::7,g::5,o:5 testsuite 2>/dev/null; then
setfacl_nodef='setacl -k'
elif setfacl --help 2>&1 | grep ' -k,\|\[-[a-z]*k' >/dev/null; then
setfacl_nodef='setfacl -k'
elif setfacl -s u::7,g::5,o:5 testsuite 2>/dev/null; then
setfacl_nodef='setfacl -s u::7,g::5,o:5'
else
# The "true" command runs successfully, but does nothing.
setfacl_nodef=true
fi
@@ -207,22 +210,26 @@ missing=0
passed=0
failed=0
# Prefix for scratch directory. We create separate directories for
# each test case, so that they can be left behind in case of failure
# to aid investigation.
# Directory that holds the other test subdirs. We create separate dirs
# inside for each test case, so that they can be left behind in case of
# failure to aid investigation. We don't remove the testtmp subdir at
# the end so that it can be configured as a symlink to a filesystem that
# has ACLs and xattr support enabled (if desired).
scratchbase="$TOOLDIR"/testtmp
echo " scratchbase=$scratchbase"
[ -d "$scratchbase" ] || mkdir "$scratchbase"
suitedir="$srcdir/testsuite"
export scratchdir suitedir
prep_scratch() {
[ -d "$scratchdir" ] && rm -rf "$scratchdir"
[ -d "$scratchdir" ] && chmod -R u+rwX "$scratchdir" && rm -rf "$scratchdir"
mkdir "$scratchdir"
# Get rid of default ACLs and dir-setgid to avoid confusing some tests.
$setfacl_nodef "$scratchdir" || true
chmod g-s "$scratchdir"
ln -s "$srcdir" "$scratchdir/src"
return 0
}
@@ -238,7 +245,7 @@ fi
for testscript in $suitedir/$whichtests
do
testbase=`echo $testscript | sed -e 's!.*/!!' -e 's/.test\$//'`
scratchdir="$scratchbase.$testbase"
scratchdir="$scratchbase/$testbase"
prep_scratch

230
sender.c
View File

@@ -3,11 +3,11 @@
*
* Copyright (C) 1996 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2003, 2004, 2005, 2006 Wayne Davison
* Copyright (C) 2003-2007 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
@@ -16,16 +16,17 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
* with this program; if not, visit the http://fsf.org website.
*/
#include "rsync.h"
extern int verbose;
extern int dry_run;
extern int do_xfers;
extern int am_server;
extern int am_daemon;
extern int inc_recurse;
extern int log_before_transfer;
extern int stdout_format_has_i;
extern int logfile_format_has_i;
@@ -33,6 +34,7 @@ extern int csum_length;
extern int append_mode;
extern int io_error;
extern int allowed_lull;
extern int preserve_xattrs;
extern int protocol_version;
extern int remove_source_files;
extern int updating_basis_file;
@@ -42,9 +44,7 @@ extern int inplace;
extern int batch_fd;
extern int write_batch;
extern struct stats stats;
extern struct file_list *the_file_list;
extern char *stdout_format;
extern struct file_list *cur_flist, *first_flist, *dir_flist;
/**
* @file
@@ -76,7 +76,7 @@ static struct sum_struct *receive_sums(int f)
(double)s->count, (long)s->blength, (long)s->remainder);
}
if (append_mode) {
if (append_mode > 0) {
s->flength = (OFF_T)s->count * s->blength;
if (s->remainder)
s->flength -= s->blength - s->remainder;
@@ -122,31 +122,35 @@ void successful_send(int ndx)
{
char fname[MAXPATHLEN];
struct file_struct *file;
unsigned int offset;
struct file_list *flist;
if (ndx < 0 || ndx >= the_file_list->count)
if (!remove_source_files)
return;
file = the_file_list->files[ndx];
if (file->dir.root) {
offset = stringjoin(fname, sizeof fname,
file->dir.root, "/", NULL);
} else
offset = 0;
f_name(file, fname + offset);
if (remove_source_files) {
if (do_unlink(fname) == 0) {
if (verbose > 1)
rprintf(FINFO, "sender removed %s\n", fname + offset);
} else
rsyserr(FERROR, errno, "sender failed to remove %s", fname + offset);
if (!(flist = flist_for_ndx(ndx))) {
rprintf(FERROR,
"INTERNAL ERROR: unable to find flist for item %d\n",
ndx);
return;
}
file = flist->files[ndx - flist->ndx_start];
if (!push_pathname(F_PATHNAME(file), -1))
return;
f_name(file, fname);
if (do_unlink(fname) == 0) {
if (verbose > 1)
rprintf(FINFO, "sender removed %s\n", fname);
} else
rsyserr(FERROR, errno, "sender failed to remove %s", fname);
}
static void write_ndx_and_attrs(int f_out, int ndx, int iflags,
const char *fname, struct file_struct *file,
uchar fnamecmp_type, char *buf, int len)
{
write_int(f_out, ndx);
write_ndx(f_out, ndx);
if (protocol_version < 29)
return;
write_shortint(f_out, iflags);
@@ -154,118 +158,85 @@ static void write_ndx_and_attrs(int f_out, int ndx, int iflags,
write_byte(f_out, fnamecmp_type);
if (iflags & ITEM_XNAME_FOLLOWS)
write_vstring(f_out, buf, len);
#ifdef SUPPORT_XATTRS
if (preserve_xattrs && iflags & ITEM_REPORT_XATTR && !dry_run)
send_xattr_request(fname, file, f_out);
#endif
}
/* This is also used by receive.c with f_out = -1. */
int read_item_attrs(int f_in, int f_out, int ndx, uchar *type_ptr,
char *buf, int *len_ptr)
{
int len;
uchar fnamecmp_type = FNAMECMP_FNAME;
int iflags = protocol_version >= 29 ? read_shortint(f_in)
: ITEM_TRANSFER | ITEM_MISSING_DATA;
/* Handle the new keep-alive (no-op) packet. */
if (ndx == the_file_list->count && iflags == ITEM_IS_NEW)
;
else if (ndx < 0 || ndx >= the_file_list->count) {
rprintf(FERROR, "Invalid file index: %d (count=%d) [%s]\n",
ndx, the_file_list->count, who_am_i());
exit_cleanup(RERR_PROTOCOL);
} else if (iflags == ITEM_IS_NEW) {
rprintf(FERROR, "Invalid itemized flag word: %x [%s]\n",
iflags, who_am_i());
exit_cleanup(RERR_PROTOCOL);
}
if (iflags & ITEM_BASIS_TYPE_FOLLOWS)
fnamecmp_type = read_byte(f_in);
*type_ptr = fnamecmp_type;
if (iflags & ITEM_XNAME_FOLLOWS) {
if ((len = read_vstring(f_in, buf, MAXPATHLEN)) < 0)
exit_cleanup(RERR_PROTOCOL);
} else {
*buf = '\0';
len = -1;
}
*len_ptr = len;
if (iflags & ITEM_TRANSFER) {
if (!S_ISREG(the_file_list->files[ndx]->mode)) {
rprintf(FERROR,
"received request to transfer non-regular file: %d [%s]\n",
ndx, who_am_i());
exit_cleanup(RERR_PROTOCOL);
}
} else if (f_out >= 0) {
write_ndx_and_attrs(f_out, ndx, iflags,
fnamecmp_type, buf, len);
}
return iflags;
}
void send_files(struct file_list *flist, int f_out, int f_in)
void send_files(int f_in, int f_out)
{
int fd = -1;
struct sum_struct *s;
struct map_struct *mbuf = NULL;
STRUCT_STAT st;
char *fname2, fname[MAXPATHLEN];
char xname[MAXPATHLEN];
char fname[MAXPATHLEN], xname[MAXPATHLEN];
const char *path, *slash;
uchar fnamecmp_type;
int iflags, xlen;
struct file_struct *file;
int phase = 0, max_phase = protocol_version >= 29 ? 2 : 1;
struct stats initial_stats;
int save_make_backups = make_backups;
int itemizing = am_server ? logfile_format_has_i : stdout_format_has_i;
enum logcode log_code = log_before_transfer ? FLOG : FINFO;
int f_xfer = write_batch < 0 ? batch_fd : f_out;
int i, j;
int ndx, j;
if (verbose > 2)
rprintf(FINFO, "send_files starting\n");
while (1) {
unsigned int offset;
if (inc_recurse)
send_extra_file_list(f_out, FILECNT_LOOKAHEAD);
i = read_int(f_in);
if (i == -1) {
/* This call also sets cur_flist. */
ndx = read_ndx_and_attrs(f_in, &iflags, &fnamecmp_type,
xname, &xlen);
if (ndx == NDX_DONE) {
if (inc_recurse && first_flist) {
flist_free(first_flist);
if (first_flist) {
write_ndx(f_out, NDX_DONE);
continue;
}
}
if (++phase > max_phase)
break;
csum_length = SUM_LENGTH;
if (verbose > 2)
rprintf(FINFO, "send_files phase=%d\n", phase);
write_int(f_out, -1);
/* For inplace: redo phase turns off the backup
* flag so that we do a regular inplace send. */
make_backups = 0;
append_mode = 0;
write_ndx(f_out, NDX_DONE);
continue;
}
iflags = read_item_attrs(f_in, f_out, i, &fnamecmp_type,
xname, &xlen);
if (iflags == ITEM_IS_NEW) /* no-op packet */
continue;
if (inc_recurse)
send_extra_file_list(f_out, FILECNT_LOOKAHEAD);
file = flist->files[i];
if (file->dir.root) {
/* N.B. We're sure that this fits, so offset is OK. */
offset = strlcpy(fname, file->dir.root, sizeof fname);
if (!offset || fname[offset-1] != '/')
fname[offset++] = '/';
} else
offset = 0;
fname2 = f_name(file, fname + offset);
if (ndx - cur_flist->ndx_start >= 0)
file = cur_flist->files[ndx - cur_flist->ndx_start];
else
file = dir_flist->files[cur_flist->parent_ndx];
if (F_PATHNAME(file)) {
path = F_PATHNAME(file);
slash = "/";
} else {
path = slash = "";
}
if (!push_pathname(F_PATHNAME(file), -1))
continue;
f_name(file, fname);
if (verbose > 2)
rprintf(FINFO, "send_files(%d, %s)\n", i, fname);
rprintf(FINFO, "send_files(%d, %s%s%s)\n", ndx, path,slash,fname);
#ifdef SUPPORT_XATTRS
if (preserve_xattrs && iflags & ITEM_REPORT_XATTR)
recv_xattr_request(file, f_in);
#endif
if (!(iflags & ITEM_TRANSFER)) {
maybe_log_item(file, iflags, itemizing, xname);
write_ndx_and_attrs(f_out, ndx, iflags, fname, file,
fnamecmp_type, xname, xlen);
continue;
}
if (phase == 2) {
@@ -275,17 +246,33 @@ void send_files(struct file_list *flist, int f_out, int f_in)
exit_cleanup(RERR_PROTOCOL);
}
updating_basis_file = inplace && (protocol_version >= 29
? fnamecmp_type == FNAMECMP_FNAME : !make_backups);
if (file->flags & FLAG_FILE_SENT) {
if (csum_length == SHORT_SUM_LENGTH) {
/* For inplace: redo phase turns off the backup
* flag so that we do a regular inplace send. */
make_backups = -make_backups;
append_mode = -append_mode;
csum_length = SUM_LENGTH;
}
} else {
if (csum_length != SHORT_SUM_LENGTH) {
make_backups = -make_backups;
append_mode = -append_mode;
csum_length = SHORT_SUM_LENGTH;
}
}
stats.current_file_index = i;
updating_basis_file = inplace && (protocol_version >= 29
? fnamecmp_type == FNAMECMP_FNAME : make_backups <= 0);
stats.current_file_index = ndx;
stats.num_transferred_files++;
stats.total_transferred_size += file->length;
stats.total_transferred_size += F_LENGTH(file);
if (!do_xfers) { /* log the transfer */
log_item(FCLIENT, file, &stats, iflags, NULL);
write_ndx_and_attrs(f_out, i, iflags, fnamecmp_type,
xname, xlen);
write_ndx_and_attrs(f_out, ndx, iflags, fname, file,
fnamecmp_type, xname, xlen);
continue;
}
@@ -294,7 +281,7 @@ void send_files(struct file_list *flist, int f_out, int f_in)
if (!(s = receive_sums(f_in))) {
io_error |= IOERR_GENERAL;
rprintf(FERROR, "receive_sums failed\n");
return;
exit_cleanup(RERR_PROTOCOL);
}
fd = do_open(fname, O_RDONLY, 0);
@@ -313,6 +300,8 @@ void send_files(struct file_list *flist, int f_out, int f_in)
full_fname(fname));
}
free_sums(s);
if (protocol_version >= 30)
send_msg_int(MSG_NO_SEND, ndx);
continue;
}
@@ -322,7 +311,7 @@ void send_files(struct file_list *flist, int f_out, int f_in)
rsyserr(FERROR, errno, "fstat failed");
free_sums(s);
close(fd);
return;
exit_cleanup(RERR_PROTOCOL);
}
if (st.st_size) {
@@ -332,21 +321,21 @@ void send_files(struct file_list *flist, int f_out, int f_in)
mbuf = NULL;
if (verbose > 2) {
rprintf(FINFO, "send_files mapped %s of size %.0f\n",
fname, (double)st.st_size);
rprintf(FINFO, "send_files mapped %s%s%s of size %.0f\n",
path,slash,fname, (double)st.st_size);
}
write_ndx_and_attrs(f_out, i, iflags, fnamecmp_type,
xname, xlen);
write_ndx_and_attrs(f_out, ndx, iflags, fname, file,
fnamecmp_type, xname, xlen);
write_sum_head(f_xfer, s);
if (verbose > 2)
rprintf(FINFO, "calling match_sums %s\n", fname);
rprintf(FINFO, "calling match_sums %s%s%s\n", path,slash,fname);
if (log_before_transfer)
log_item(FCLIENT, file, &initial_stats, iflags, NULL);
else if (!am_server && verbose && do_progress)
rprintf(FCLIENT, "%s\n", fname2);
rprintf(FCLIENT, "%s\n", fname);
set_compression(fname);
@@ -370,17 +359,18 @@ void send_files(struct file_list *flist, int f_out, int f_in)
free_sums(s);
if (verbose > 2)
rprintf(FINFO, "sender finished %s\n", fname);
rprintf(FINFO, "sender finished %s%s%s\n", path,slash,fname);
/* Flag that we actually sent this entry. */
file->flags |= FLAG_SENT;
file->flags |= FLAG_FILE_SENT;
}
make_backups = save_make_backups;
if (make_backups < 0)
make_backups = -make_backups;
if (verbose > 2)
rprintf(FINFO, "send files finished\n");
match_report();
write_int(f_out, -1);
write_ndx(f_out, NDX_DONE);
}

View File

@@ -3,11 +3,11 @@
*
* Copyright (C) 1992-2001 Andrew Tridgell <tridge@samba.org>
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
* Copyright (C) 2003, 2004, 2005, 2006 Wayne Davison
* Copyright (C) 2003-2007 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
@@ -16,8 +16,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
* with this program; if not, visit the http://fsf.org website.
*/
/* This file is now converted to use the new-style getaddrinfo()
@@ -26,6 +25,7 @@
* emulate it using the KAME implementation. */
#include "rsync.h"
#include "ifuncs.h"
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
@@ -95,7 +95,7 @@ static int establish_proxy_connection(int fd, char *host, int port,
buffer);
return -1;
}
for (cp = &buffer[5]; isdigit(*(uchar*)cp) || *cp == '.'; cp++) {}
for (cp = &buffer[5]; isDigit(cp) || *cp == '.'; cp++) {}
while (*cp == ' ')
cp++;
if (*cp != '2') {
@@ -301,6 +301,42 @@ int open_socket_out_wrapped(char *host, int port, const char *bind_addr,
{
char *prog = getenv("RSYNC_CONNECT_PROG");
if (prog && strchr(prog, '%')) {
int hlen = strlen(host);
int len = strlen(prog) + 1;
char *f, *t;
for (f = prog; *f; f++) {
if (*f != '%')
continue;
/* Compute more than enough room. */
if (f[1] == '%')
f++;
else
len += hlen;
}
f = prog;
if (!(prog = new_array(char, len)))
out_of_memory("open_socket_out_wrapped");
for (t = prog; *f; f++) {
if (*f == '%') {
switch (*++f) {
case '%':
/* Just skips the extra '%'. */
break;
case 'H':
memcpy(t, host, hlen);
t += hlen;
continue;
default:
f--; /* pass % through */
break;
}
}
*t++ = *f;
}
*t = '\0';
}
if (verbose >= 2) {
rprintf(FINFO, "%sopening tcp connection to %s port %d\n",
prog ? "Using RSYNC_CONNECT_PROG instead of " : "",
@@ -410,7 +446,7 @@ static int *open_socket_in(int type, int port, const char *bind_addr,
* unsuccessful, or if the daemon is being run with -vv. */
for (s = 0; s < ecnt; s++) {
if (!i || verbose > 1)
rwrite(FLOG, errmsgs[s], strlen(errmsgs[s]));
rwrite(FLOG, errmsgs[s], strlen(errmsgs[s]), 0);
free(errmsgs[s]);
}
free(errmsgs);
@@ -667,35 +703,6 @@ void set_socket_options(int fd, char *options)
free(options);
}
/**
* Become a daemon, discarding the controlling terminal
**/
void become_daemon(void)
{
int i;
if (fork()) {
_exit(0);
}
/* detach from the terminal */
#ifdef HAVE_SETSID
setsid();
#elif defined TIOCNOTTY
i = open("/dev/tty", O_RDWR);
if (i >= 0) {
ioctl(i, (int)TIOCNOTTY, (char *)0);
close(i);
}
#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);
open("/dev/null", O_RDWR);
}
}
/**
* This is like socketpair but uses tcp. It is used by the Samba

View File

@@ -42,7 +42,7 @@ print <<EOT;
# and only in the option format that the stock rsync produces.
# To disable a short-named option, add its letter to this string:
our \$short_disabled = '';
our \$short_disabled = 's';
our \$short_no_arg = '$short_no_arg'; # DO NOT REMOVE ANY
our \$short_with_num = '$short_with_num'; # DO NOT REMOVE ANY

View File

@@ -11,7 +11,7 @@
# use the -F option, which is easier to type.)
#
# The downside is that you need to remember to re-run cvs2includes whenever
# You add a new file to the project.
# you add a new file to the project.
use strict;
open(FIND, 'find . -name CVS -type d |') or die $!;
@@ -31,7 +31,7 @@ while (<FIND>) {
close ENTRIES;
if (@includes) {
open(FILTER, ">$filter") or die "Unable to write $filter: $!\n";
print FILTER '+ /', join("\n+ /", @includes), "\n";
print FILTER map "+ /$_\n", @includes;
close FILTER;
print "Updated $filter\n";
} elsif (-f $filter) {

View File

@@ -32,15 +32,15 @@ my $detail_line = qr{
\d+ \s+ # ignore size
([-bcdlps]) # 1. File type
( [-r][-w][-xsS] # 2. user-permissions
[-r][-w][-xsS] # 3. group-permissions
[-r][-w][-xtT] ) \s+ # 4. other-permissions
[-r][-w][-xsS] # group-permissions
[-r][-w][-xtT] ) \s+ # other-permissions
\d+ \s+ # ignore number of links
(\S+) \s+ # 5. owner
(\S+) \s+ # 6. group
(\S+) \s+ # 3. owner
(\S+) \s+ # 4. group
(?: \d+ \s+ )? # ignore size (when present)
\w+ \s+ \d+ \s+ # ignore month and date
\d+ (?: : \d+ )? \s+ # ignore time or year
([^\r\n]+) $ # 7. name
([^\r\n]+) $ # 5. name
}x;
while (<>) {

23
support/lsh Executable file
View File

@@ -0,0 +1,23 @@
#!/bin/sh
# This script can be used as a "remote shell" command that is only
# capable of pretending to connect to "localhost". This is useful
# for testing or for running a local copy where the sender and the
# receiver needs to use different options (e.g. --fake-super). If
# we get a -l USER option, we try to use "sudo -u USER" to run the
# command.
prefix=''
cd # Default path is home dir, just like ssh.
while : ; do
case "$1" in
-l) shift ; prefix="sudo -u $1"; shift ;;
-l*) prefix=`echo $1 | sed 's/-l/sudo -u /'`; shift ;;
-*) shift ;;
localhost) shift; break ;;
*) exit 1 ;;
esac
done
eval $prefix "${@}"

View File

@@ -48,9 +48,9 @@ die "$0 -ro: sending to read-only server not allowed\n" if $ro && !$am_sender;
# and only in the option format that the stock rsync produces.
# To disable a short-named option, add its letter to this string:
our $short_disabled = '';
our $short_disabled = 's';
our $short_no_arg = 'CDEHIKLORSWbcdgklmnoprtuvxz'; # DO NOT REMOVE ANY
our $short_no_arg = 'ACDEHIKLORSWXbcdgklmnoprstuvxz'; # DO NOT REMOVE ANY
our $short_with_num = 'B'; # DO NOT REMOVE ANY
# To disable a long-named option, change its value to a -1. The values mean:
@@ -70,6 +70,7 @@ our %long_opt = (
'delete' => 0,
'delete-after' => 0,
'delete-before' => 0,
'delete-delay' => 0,
'delete-during' => 0,
'delete-excluded' => 0,
'existing' => 0,
@@ -77,6 +78,7 @@ our %long_opt = (
'force' => 0,
'from0' => 0,
'fuzzy' => 0,
'iconv' => 1,
'ignore-errors' => 0,
'ignore-existing' => 0,
'inplace' => 0,
@@ -87,6 +89,7 @@ our %long_opt = (
'max-size' => 1,
'min-size' => 1,
'modify-window' => 1,
'no-i-r' => 0,
'no-implied-dirs' => 0,
'no-r' => 0,
'no-relative' => 0,
@@ -101,6 +104,7 @@ our %long_opt = (
'sender' => 0,
'server' => 0,
'size-only' => 0,
'skip-compress' => 1,
'specials' => 0,
'suffix' => 1,
'super' => 0,
@@ -135,7 +139,7 @@ while ($command =~ /((?:[^\s\\]+|\\.[^\s\\]*)+)/g) {
if ($_ eq '.') {
$in_options = 0;
} else {
next if /^-$short_no_arg+$/o || /^-$short_with_num\d+$/o;
next if /^-$short_no_arg+(e\d+\.\d+)?$/o || /^-$short_with_num\d+$/o;
my($opt,$arg) = /^--([^=]+)(?:=(.*))?$/;
my $disabled;

View File

@@ -27,6 +27,10 @@
#define TIMEOUT_SECONDS 30
#ifdef HAVE_SIGACTION
static struct sigaction sigact;
#endif
void run_program(char **command);
char buf[4096];
@@ -64,7 +68,7 @@ main(int argc, char *argv[])
}
set_blocking(fd_file);
signal(SIGPIPE, SIG_IGN);
SIGACTION(SIGPIPE, SIG_IGN);
run_program(argv + 1);

View File

@@ -4,11 +4,11 @@
*
* Copyright (C) 1998 Andrew Tridgell
* Copyright (C) 2002 Martin Pool
* Copyright (C) 2003, 2004, 2005, 2006 Wayne Davison
* Copyright (C) 2003-2007 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
@@ -17,8 +17,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
* with this program; if not, visit the http://fsf.org website.
*/
#include "rsync.h"
@@ -28,6 +27,7 @@
#endif
extern int dry_run;
extern int am_root;
extern int read_only;
extern int list_only;
extern int preserve_perms;
@@ -75,10 +75,19 @@ int do_lchown(const char *path, uid_t owner, gid_t group)
return lchown(path, owner, group);
}
int do_mknod(char *pathname, mode_t mode, dev_t dev)
int do_mknod(const char *pathname, mode_t mode, dev_t dev)
{
if (dry_run) return 0;
RETURN_ERROR_IF_RO_OR_LO;
/* For --fake-super, we create a normal file with mode 0600. */
if (am_root < 0) {
int fd = open(pathname, O_WRONLY|O_CREAT|O_TRUNC, S_IWUSR|S_IRUSR);
if (fd < 0 || close(fd) < 0)
return -1;
return 0;
}
#if !defined MKNOD_CREATES_FIFOS && defined HAVE_MKFIFO
if (S_ISFIFO(mode))
return mkfifo(pathname, mode);
@@ -87,14 +96,15 @@ int do_mknod(char *pathname, mode_t mode, dev_t dev)
if (S_ISSOCK(mode)) {
int sock;
struct sockaddr_un saddr;
unsigned int len;
saddr.sun_family = AF_UNIX;
len = strlcpy(saddr.sun_path, pathname, sizeof saddr.sun_path);
#ifdef HAVE_SOCKADDR_UN_LEN
unsigned int len =
#endif
strlcpy(saddr.sun_path, pathname, sizeof saddr.sun_path);
#ifdef HAVE_SOCKADDR_UN_LEN
saddr.sun_len = len >= sizeof saddr.sun_path
? sizeof saddr.sun_path : len + 1;
#endif
saddr.sun_family = AF_UNIX;
if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0
|| (unlink(pathname) < 0 && errno != ENOENT)

View File

@@ -3,11 +3,11 @@
* functions, so that module test harnesses can run standalone.
*
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
* Copyright (C) 2003, 2004, 2005, 2006 Wayne Davison
* Copyright (C) 2003-2007 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
@@ -16,8 +16,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
* with this program; if not, visit the http://fsf.org website.
*/
#include "rsync.h"
@@ -29,6 +28,7 @@ int human_readable = 0;
int module_dirlen = 0;
mode_t orig_umask = 002;
char *partial_dir;
char *module_dir;
struct filter_list_struct server_filter_list;
void rprintf(UNUSED(enum logcode code), const char *format, ...)
@@ -64,6 +64,11 @@ struct filter_list_struct server_filter_list;
return 0;
}
int make_bak_dir(UNUSED(const char *fullpath))
{
return -1;
}
char *lp_name(UNUSED(int mod))
{
return NULL;
@@ -74,11 +79,6 @@ struct filter_list_struct server_filter_list;
return 0;
}
char *lp_path(UNUSED(int mod))
{
return NULL;
}
const char *who_am_i(void)
{
return "tester";

View File

@@ -2,11 +2,11 @@
* Test harness for unsafe_symlink(). Not linked into rsync itself.
*
* Copyright (C) 2002 Martin Pool
* Copyright (C) 2003 Wayne Davison
* Copyright (C) 2003-2007 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
@@ -15,8 +15,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
* with this program; if not, visit the http://fsf.org website.
*/
/* Prints either "safe" or "unsafe" depending on the two arguments.
@@ -24,7 +23,11 @@
#include "rsync.h"
int dry_run, read_only, list_only, verbose;
int dry_run = 0;
int am_root = 0;
int read_only = 0;
int list_only = 0;
int verbose = 0;
int preserve_perms = 0;
int

62
testsuite/acls.test Normal file
View File

@@ -0,0 +1,62 @@
#! /bin/sh
# This program is distributable under the terms of the GNU GPL (see
# COPYING).
# Test that rsync handles basic ACL preservation.
. $srcdir/testsuite/rsync.fns
$RSYNC --version | grep ", ACLs" >/dev/null || test_skipped "Rsync is configured without ACL support"
makepath "$fromdir/foo"
echo something >"$fromdir/file1"
echo else >"$fromdir/file2"
files='foo file1 file2'
case "$setfacl_nodef" in
true)
if ! chmod --help 2>&1 | fgrep +a >/dev/null; then
test_skipped "I don't know how to use setfacl or chmod for ACLs"
fi
chmod +a "root allow read,write,execute" "$fromdir/foo" || test_skipped "Your filesystem has ACLs disabled"
chmod +a "root allow read,execute" "$fromdir/file1"
chmod +a "admin allow read" "$fromdir/file1"
chmod +a "daemon allow read,write" "$fromdir/file1"
chmod +a "root allow read,execute" "$fromdir/file2"
see_acls() {
ls -le "${@}"
}
;;
*)
setfacl -m u:0:7 "$fromdir/foo" || test_skipped "Your filesystem has ACLs disabled"
setfacl -m g:1:5 "$fromdir/foo"
setfacl -m g:2:1 "$fromdir/foo"
setfacl -m g:0:7 "$fromdir/foo"
setfacl -m u:2:1 "$fromdir/foo"
setfacl -m u:1:5 "$fromdir/foo"
setfacl -m u:0:5 "$fromdir/file1"
setfacl -m g:0:4 "$fromdir/file1"
setfacl -m u:1:6 "$fromdir/file1"
setfacl -m u:0:5 "$fromdir/file2"
see_acls() {
getfacl "${@}"
}
;;
esac
cd "$fromdir"
$RSYNC -avvA $files "$todir/"
see_acls $files >"$scratchdir/acls.txt"
cd "$todir"
see_acls $files | diff $diffopt "$scratchdir/acls.txt" -
# The script would have aborted on error, so getting here means we've won.
exit 0

View File

@@ -11,26 +11,26 @@
bakdir="$tmpdir/bak"
mkdir "$fromdir" "$bakdir"
name1="$fromdir/name1"
name2="$fromdir/name2"
makepath "$fromdir/deep" "$bakdir"
name1="$fromdir/deep/name1"
name2="$fromdir/deep/name2"
outfile="$scratchdir/rsync.out"
cat "$srcdir"/[gr]*.[ch] > "$name1"
cat "$srcdir"/[et]*.[ch] > "$name2"
checkit "$RSYNC -avv \"$fromdir/\" \"$todir/\"" "$fromdir" "$todir"
checkit "$RSYNC -avv '$fromdir/' '$todir/'" "$fromdir" "$todir"
checkit "$RSYNC -avv \"$fromdir/\" \"$chkdir/\"" "$fromdir" "$chkdir"
checkit "$RSYNC -avv '$fromdir/' '$chkdir/'" "$fromdir" "$chkdir"
cat "$srcdir"/[fgpr]*.[ch] > "$name1"
cat "$srcdir"/[etw]*.[ch] > "$name2"
$RSYNC -avv --no-whole-file --backup "$fromdir/" "$todir/" \
| tee "$outfile"
for fn in name1 name2; do
for fn in deep/name1 deep/name2; do
grep "backed up $fn to $fn~" "$outfile" >/dev/null || test_fail "no backup message output for $fn"
diff $diffopt "$fromdir/$fn" "$todir" || test_fail "copy of $fn failed"
diff $diffopt "$fromdir/$fn" "$todir/$fn" || test_fail "copy of $fn failed"
diff $diffopt "$chkdir/$fn" "$todir/$fn~" || test_fail "backup of $fn to $fn~ failed"
mv "$todir/$fn~" "$todir/$fn"
done
@@ -38,29 +38,29 @@ done
echo deleted-file >"$todir/dname"
cp -p "$todir/dname" "$chkdir"
checkit "$RSYNC -avv --no-whole-file --delete-after \
--backup --backup-dir=\"$bakdir\" \"$fromdir/\" \"$todir/\"" "$fromdir" "$todir" \
checkit "$RSYNC -avv --no-whole-file --delete-delay \
--backup --backup-dir='$bakdir' '$fromdir/' '$todir/'" "$fromdir" "$todir" \
| tee "$outfile"
for fn in name1 name2; do
for fn in deep/name1 deep/name2; do
grep "backed up $fn to .*/$fn$" "$outfile" >/dev/null || test_fail "no backup message output for $fn"
done
diff -r $diffopt "$chkdir" "$bakdir" || test_fail "backup dir contents are bogus"
rm "$bakdir/dname"
checkit "$RSYNC -avv --del \"$fromdir/\" \"$chkdir/\"" "$fromdir" "$chkdir"
checkit "$RSYNC -avv --del '$fromdir/' '$chkdir/'" "$fromdir" "$chkdir"
cat "$srcdir"/[efgr]*.[ch] > "$name1"
cat "$srcdir"/[ew]*.[ch] > "$name2"
checkit "$RSYNC -avv --inplace --no-whole-file --backup --backup-dir=\"$bakdir\" \"$fromdir/\" \"$todir/\"" "$fromdir" "$todir" \
checkit "$RSYNC -avv --inplace --no-whole-file --backup --backup-dir='$bakdir' '$fromdir/' '$todir/'" "$fromdir" "$todir" \
| tee "$outfile"
for fn in name1 name2; do
for fn in deep/name1 deep/name2; do
grep "backed up $fn to .*/$fn$" "$outfile" >/dev/null || test_fail "no backup message output for $fn"
done
diff -r $diffopt "$chkdir" "$bakdir" || test_fail "backup dir contents are bogus"
checkit "$RSYNC -avv --inplace --no-whole-file \"$fromdir/\" \"$bakdir/\"" "$fromdir" "$bakdir"
checkit "$RSYNC -avv --inplace --no-whole-file '$fromdir/' '$bakdir/'" "$fromdir" "$bakdir"
# The script would have aborted on error, so getting here means we've won.
exit 0

View File

@@ -16,6 +16,12 @@ cd "$tmpdir"
# Build chkdir for the daemon tests using a normal rsync and an --exclude.
$RSYNC -av --exclude=foobar.baz "$fromdir/" "$chkdir/"
$RSYNC -av --only-write-batch=BATCH --exclude=foobar.baz "$fromdir/" "$todir/missing/"
test -d "$todir/missing" && test_fail "--only-write-batch should not have created destination dir"
runtest "--read-batch (only)" 'checkit "$RSYNC -av --read-batch=BATCH \"$todir\"" "$chkdir" "$todir"'
rm -rf "$todir" BATCH*
runtest "local --write-batch" 'checkit "$RSYNC -av --write-batch=BATCH \"$fromdir/\" \"$todir\"" "$fromdir" "$todir"'
rm -rf "$todir"

View File

@@ -24,7 +24,7 @@ do
done
sleep 2
checkit "$RSYNC -rtgpvvv \"$fromdir/\" \"$todir/\"" "$fromdir" "$todir"
checkit "$RSYNC -rtgpvvv '$fromdir/' '$todir/'" "$fromdir" "$todir"
# The script would have aborted on error, so getting here means we've won.
exit 0

View File

@@ -29,24 +29,23 @@ chmod 700 "$dir1"
chmod 770 "$dir2"
# Copy the files we've created over to another directory
checkit "$RSYNC -avv \"$fromdir/\" \"$checkdir/\"" "$fromdir" "$checkdir"
checkit "$RSYNC -avv '$fromdir/' '$checkdir/'" "$fromdir" "$checkdir"
# And then manually make the changes which should occur
umask 002
chmod ug-s,a+rX "$checkdir"/*
chmod +w "$checkdir" "$checkdir"/dir*
checkit "$RSYNC -avv --chmod ug-s,a+rX,D+w \"$fromdir/\" \"$todir/\"" "$checkdir" "$todir"
checkit "$RSYNC -avv --chmod ug-s,a+rX,D+w '$fromdir/' '$todir/'" "$checkdir" "$todir"
rm -r "$fromdir" "$checkdir" "$todir"
makepath "$todir"
makepath "$fromdir/foo"
makepath "$todir" "$fromdir/foo"
touch "$fromdir/bar"
checkit "$RSYNC -avv \"$fromdir/\" \"$checkdir/\"" "$fromdir" "$checkdir"
checkit "$RSYNC -avv '$fromdir/' '$checkdir/'" "$fromdir" "$checkdir"
chmod o+x "$fromdir"/bar
checkit "$RSYNC -avv --chmod=Fo-x \"$fromdir/\" \"$todir/\"" "$checkdir" "$todir"
checkit "$RSYNC -avv --chmod=Fo-x '$fromdir/' '$todir/'" "$checkdir" "$todir"
# Tickle a bug in rsync 2.6.8: if you push a new directory with --perms off to
# a daemon with an incoming chmod, the daemon pretends the directory is a file
@@ -66,7 +65,7 @@ export RSYNC_CONNECT_PROG
rm -r "$todir"
makepath "$todir"
checkit "$RSYNC -rtvv \"$fromdir/\" localhost::test-incoming-chmod/" "$checkdir" "$todir"
checkit "$RSYNC -avv --no-perms '$fromdir/' localhost::test-incoming-chmod/" "$checkdir" "$todir"
# The script would have aborted on error, so getting here means we've won.
exit 0

View File

@@ -13,13 +13,39 @@
. "$suitedir/rsync.fns"
case `id -u` in
'') ;; # If "id" failed, try to continue...
0) ;;
*) if [ -f /usr/bin/fakeroot ]; then
echo "Let's try re-running the script under fakeroot..."
exec /usr/bin/fakeroot /bin/sh "$0"
fi
case $0 in
*fake*)
$RSYNC --version | grep ", xattrs" >/dev/null || test_skipped "Rsync needs xattrs for fake device tests"
RSYNC="$RSYNC --fake-super"
TLS_ARGS=--fake-super
case "`xattr 2>&1`" in
*--list:*)
chown() {
own=$1
shift
xattr -s 'rsync.%stat' "100644 0,0 $own" "${@}"
}
;;
*)
chown() {
own=$1
shift
setfattr -n 'user.rsync.%stat' -v "100644 0,0 $own" "${@}"
}
;;
esac
;;
*)
RSYNC="$RSYNC --super"
case `id -u` in
'') ;; # If "id" failed, try to continue...
0) ;;
*) if [ -f /usr/bin/fakeroot ]; then
echo "Let's try re-running the script under fakeroot..."
exec /usr/bin/fakeroot /bin/sh "$0"
fi
;;
esac
;;
esac
@@ -31,12 +57,11 @@ name2="$fromdir/name2"
echo "This is the file" > "$name1"
echo "This is the other file" > "$name2"
chown 5000 "$name1" || test_skipped "Can't chown (probably need root)"
chown 5001 "$name2" || test_skipped "Can't chown (probably need root)"
chgrp 5002 "$name1" || test_skipped "Can't chgrp (probably need root)"
chgrp 5003 "$name2" || test_skipped "Can't chgrp (probably need root)"
chown 5000:5002 "$name1" || test_skipped "Can't chown (probably need root)"
chown 5001:5003 "$name2" || test_skipped "Can't chown (probably need root)"
checkit "$RSYNC -aHvv \"$fromdir/\" \"$todir/\"" "$fromdir" "$todir"
cd "$fromdir/.."
checkit "$RSYNC -aHvv from/ to/" "$fromdir" "$todir"
# The script would have aborted on error, so getting here means we've won.
exit 0

View File

@@ -27,11 +27,11 @@ $RSYNC -av --exclude=/text --exclude=etc-ltr-list "$fromdir/" "$chkdir/"
# Let's do it!
checkit "$RSYNC -avv --no-whole-file \
--compare-dest=\"$alt1dir\" --compare-dest=\"$alt2dir\" \
\"$fromdir/\" \"$todir/\"" "$chkdir" "$todir"
--compare-dest='$alt1dir' --compare-dest='$alt2dir' \
'$fromdir/' '$todir/'" "$chkdir" "$todir"
checkit "$RSYNC -avv --no-whole-file \
--copy-dest=\"$alt1dir\" --copy-dest=\"$alt2dir\" \
\"$fromdir/\" \"$todir/\"" "$fromdir" "$todir"
--copy-dest='$alt1dir' --copy-dest='$alt2dir' \
'$fromdir/' '$todir/'" "$fromdir" "$todir"
# The script would have aborted on error, so getting here means we've won.
exit 0

View File

@@ -31,7 +31,7 @@ hands_setup
# Build chkdir with a normal rsync and an --exclude.
$RSYNC -av --exclude=foobar.baz "$fromdir/" "$chkdir/"
checkit "$RSYNC -avvvvz localhost::test-from/ \"$todir/\"" "$chkdir" "$todir"
checkit "$RSYNC -avvvvz localhost::test-from/ '$todir/'" "$chkdir" "$todir"
# The script would have aborted on error, so getting here means we've won.
exit 0

View File

@@ -25,7 +25,7 @@ hands_setup
# Build chkdir with a normal rsync and an --exclude.
$RSYNC -av --exclude=foobar.baz "$fromdir/" "$chkdir/"
checkit "$RSYNC -avvvvz \"$fromdir/\" localhost::test-to/" "$chkdir" "$todir"
checkit "$RSYNC -avvvvz '$fromdir/' localhost::test-to/" "$chkdir" "$todir"
# The script would have aborted on error, so getting here means we've won.
exit 0

View File

@@ -0,0 +1,66 @@
#! /bin/sh
# This program is distributable under the terms of the GNU GPL (see
# COPYING).
# Test that rsync obeys default ACLs. -- Matt McCutchen
. $srcdir/testsuite/rsync.fns
$RSYNC --version | grep ", ACLs" >/dev/null || test_skipped "Rsync is configured without ACL support"
case "$setfacl_nodef" in
true) test_skipped "I don't know how to use your setfacl command" ;;
*-k*) opts='-dm u::7,g::5,o:5' ;;
*) opts='-m d:u::7,d:g::5,d:o:5' ;;
esac
setfacl $opts "$scratchdir" || test_skipped "Your filesystem has ACLs disabled"
# Call as: testit <dirname> <default-acl> <file-expected> <program-expected>
testit() {
todir="$scratchdir/$1"
mkdir "$todir"
$setfacl_nodef "$todir"
if [ "$2" ]; then
case "$setfacl_nodef" in
*-k*) opts="-dm $2" ;;
*) opts="-m `echo $2 | sed 's/\([ugom]:\)/d:\1/g'`"
esac
setfacl $opts "$todir"
fi
# Make sure we obey ACLs when creating a directory to hold multiple transferred files,
# even though the directory itself is outside the transfer
$RSYNC -rvv "$scratchdir/dir" "$scratchdir/file" "$scratchdir/program" "$todir/to/"
check_perms "$todir/to" $4 "Target $1"
check_perms "$todir/to/dir" $4 "Target $1"
check_perms "$todir/to/file" $3 "Target $1"
check_perms "$todir/to/program" $4 "Target $1"
# Make sure get_local_name doesn't mess us up when transferring only one file
$RSYNC -rvv "$scratchdir/file" "$todir/to/anotherfile"
check_perms "$todir/to/anotherfile" $3 "Target $1"
# Make sure we obey default ACLs when not transferring a regular file
$RSYNC -rvv "$scratchdir/dir/" "$todir/to/anotherdir/"
check_perms "$todir/to/anotherdir" $4 "Target $1"
}
mkdir "$scratchdir/dir"
echo "File!" >"$scratchdir/file"
echo "#!/bin/sh" >"$scratchdir/program"
chmod 777 "$scratchdir/dir"
chmod 666 "$scratchdir/file"
chmod 777 "$scratchdir/program"
# Test some target directories
umask 0077
testit da777 u::7,g::7,o:7 rw-rw-rw- rwxrwxrwx
testit da775 u::7,g::7,o:5 rw-rw-r-- rwxrwxr-x
testit da750 u::7,g::5,o:0 rw-r----- rwxr-x---
testit da750mask u::7,u:0:7,g::7,m:5,o:0 rw-r----- rwxr-x---
testit noda1 '' rw------- rwx------
umask 0000
testit noda2 '' rw-rw-rw- rwxrwxrwx
umask 0022
testit noda3 '' rw-r--r-- rwxr-xr-x
# Hooray
exit 0

View File

@@ -11,15 +11,31 @@
hands_setup
makepath "$chkdir"
makepath "$chkdir" "$todir/extradir" "$todir/emptydir/subdir"
echo extra >"$todir"/remove1
echo extra >"$todir"/remove2
echo extra >"$todir"/extradir/remove3
echo extra >"$todir"/emptydir/subdir/remove4
# Create two chk dirs, one with a copy of the source files, and one with
# what we expect to be left behind by the copy using --remove-sent-files.
$RSYNC -av "$fromdir/" "$chkdir/copy/"
# what we expect to be left behind by the copy using --remove-source-files.
# Also, make sure that --dry-run --del doesn't output anything extraneous.
$RSYNC -av "$fromdir/" "$chkdir/copy/" >"$tmpdir/copy.out" 2>&1
cat "$tmpdir/copy.out"
egrep -v '^(created directory|sent|total size) ' "$tmpdir/copy.out" >"$tmpdir/copy.new"
mv "$tmpdir/copy.new" "$tmpdir/copy.out"
$RSYNC -avn --del "$fromdir/" "$chkdir/copy2/" >"$tmpdir/copy2.out" 2>&1 || true
cat "$tmpdir/copy2.out"
egrep -v '^(created directory|sent|total size) ' "$tmpdir/copy2.out" >"$tmpdir/copy2.new"
mv "$tmpdir/copy2.new" "$tmpdir/copy2.out"
diff $diffopt "$tmpdir/copy.out" "$tmpdir/copy2.out"
$RSYNC -av -f 'exclude,! */' "$fromdir/" "$chkdir/empty/"
checkit "$RSYNC -avv --remove-sent-files \
\"$fromdir/\" \"$todir/\"" "$chkdir/copy" "$todir"
checkit "$RSYNC -avv --del --remove-source-files '$fromdir/' '$todir/'" "$chkdir/copy" "$todir"
diff -r "$chkdir/empty" "$fromdir"
@@ -33,9 +49,9 @@ touch "$todir/foo" "$todir/bar" "$todir/baz"
$RSYNC -r --exclude=baz --filter=': filters' --delete-excluded "$fromdir/" "$todir/"
test -f "$todir/foo" || test_fail "rsync deleted $todir/foo"
test -f "$todir/bar" && test_fail "rsync did not delete $todir/bar"
test -f "$todir/baz" && test_fail "rsync did not delete $todir/baz"
test -f "$todir/foo" || test_fail "rsync should NOT have deleted $todir/foo"
test -f "$todir/bar" && test_fail "rsync SHOULD have deleted $todir/bar"
test -f "$todir/baz" && test_fail "rsync SHOULD have deleted $todir/baz"
# The script would have aborted on error, so getting here means we've won.
exit 0

View File

@@ -14,14 +14,53 @@ outfile="$scratchdir/rsync.out"
# Build some hardlinks
case `id -u` in
'') ;; # If "id" failed, try to continue...
0) ;;
*) if [ -f /usr/bin/fakeroot ]; then
echo "Let's try re-running the script under fakeroot..."
exec /usr/bin/fakeroot /bin/sh $RUNSHFLAGS "$0"
fi
test_skipped "Rsync won't copy devices unless we're root"
case $0 in
*fake*)
$RSYNC --version | grep ", xattrs" >/dev/null || test_skipped "Rsync needs xattrs for fake device tests"
RSYNC="$RSYNC --fake-super"
TLS_ARGS=--fake-super
case "`xattr 2>&1`" in
*--list:*)
mknod() {
fn="$1"
case "$2" in
p) mode=10644 ;;
c) mode=20644 ;;
b) mode=60644 ;;
esac
maj="${3:-0}"
min="${4:-0}"
touch "$fn"
xattr -s 'rsync.%stat' "$mode $maj,$min 0:0" "$fn"
}
;;
*)
mknod() {
fn="$1"
case "$2" in
p) mode=10644 ;;
c) mode=20644 ;;
b) mode=60644 ;;
esac
maj="${3:-0}"
min="${4:-0}"
touch "$fn"
setfattr -n 'user.rsync.%stat' -v "$mode $maj,$min 0:0" "$fn"
}
;;
esac
;;
*)
case `id -u` in
'') ;; # If "id" failed, try to continue...
0) ;;
*) if [ -f /usr/bin/fakeroot ]; then
echo "Let's try re-running the script under fakeroot..."
exec /usr/bin/fakeroot /bin/sh $RUNSHFLAGS "$0"
fi
test_skipped "Rsync needs root/fakeroot for device tests"
;;
esac
;;
esac
@@ -29,27 +68,27 @@ esac
mkdir "$fromdir"
mkdir "$todir"
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"
mknod "$fromdir/char" c 41 67 || test_skipped "Can't create char device node"
mknod "$fromdir/char2" c 42 68 || test_skipped "Can't create char device node"
mknod "$fromdir/char3" c 42 69 || test_skipped "Can't create char device node"
mknod "$fromdir/block" b 42 69 || test_skipped "Can't create block device node"
mknod "$fromdir/block2" b 42 73 || test_skipped "Can't create block device node"
mknod "$fromdir/block3" b 105 73 || test_skipped "Can't create block device node"
ln "$fromdir/block3" "$fromdir/block2.5" || echo "Skipping hard-linked device test..."
mkfifo "$fromdir/fifo" || test_skipped "Can't run mkfifo"
mkfifo "$fromdir/fifo" || mknod "$fromdir/fifo" p || test_skipped "Can't run mkfifo"
touch -r "$fromdir/block" "$fromdir/block2"
$RSYNC -ai "$fromdir/block" "$todir/block2" \
| tee "$outfile"
cat <<EOT >"$chkfile"
cD+++++++ block
cD+++++++++ block
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 1 failed"
$RSYNC -ai "$fromdir/block2" "$todir/block" \
| tee "$outfile"
cat <<EOT >"$chkfile"
cD+++++++ block2
cD+++++++++ block2
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 2 failed"
@@ -58,7 +97,7 @@ sleep 1
$RSYNC -Di "$fromdir/block3" "$todir/block" \
| tee "$outfile"
cat <<EOT >"$chkfile"
cD..T.... block3
cD..T...... block3
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 3 failed"
@@ -66,19 +105,18 @@ $RSYNC -aiHvv "$fromdir/" "$todir/" \
| tee "$outfile"
filter_outfile
cat <<EOT >"$chkfile"
.d..t.... ./
cD..t.... block
cD....... block2
cD+++++++ block3
hD+++++++ block2.5 => block3
cD+++++++ char
cD+++++++ char2
cD+++++++ char3
cS+++++++ fifo
.d..t...... ./
cD..t...... block
cD block2
cD+++++++++ block3
hD+++++++++ block2.5 => block3
cD+++++++++ char
cD+++++++++ char2
cD+++++++++ char3
cS+++++++++ fifo
EOT
if test ! -b "$fromdir/block2.5"; then
sed -e '/block2\.5/d' \
<"$chkfile" >"$chkfile.new"
if test ! -r "$fromdir/block2.5"; then
sed -e '/block2\.5/d' <"$chkfile" >"$chkfile.new"
mv "$chkfile.new" "$chkfile"
fi
diff $diffopt "$chkfile" "$outfile" || test_fail "test 4 failed"
@@ -89,5 +127,23 @@ echo ""
( cd "$todir" && rsync_ls_lR . ) > "$tmpdir/ls-to"
diff $diffopt "$tmpdir/ls-from" "$tmpdir/ls-to"
if test -b "$fromdir/block2.5"; then
set -x
$RSYNC -aii --link-dest="$todir" "$fromdir/" "$chkdir/" \
| tee "$outfile"
cat <<EOT >"$chkfile"
cd ./
hD block
hD block2
hD block2.5
hD block3
hD char
hD char2
hD char3
hS fifo
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 4 failed"
fi
# The script would have aborted on error, so getting here means we've won.
exit 0

View File

@@ -31,7 +31,7 @@ ln -s "$name1" "$name2" || fail "can't create symlink"
outfile="$scratchdir/rsync.out"
checkit "$RSYNC -avv \"$fromdir/\" \"$fromdir/\" \"$fromdir/\" \"$fromdir/\" \"$fromdir/\" \"$fromdir/\" \"$fromdir/\" \"$fromdir/\" \"$fromdir/\" \"$fromdir/\" \"$todir/\"" "$fromdir" "$todir" \
checkit "$RSYNC -avv '$fromdir/' '$fromdir/' '$fromdir/' '$fromdir/' '$fromdir/' '$fromdir/' '$fromdir/' '$fromdir/' '$fromdir/' '$fromdir/' '$todir/'" "$fromdir" "$todir" \
| tee "$outfile"
# Make sure each file was only copied once...

View File

@@ -5,7 +5,7 @@
# This program is distributable under the terms of the GNU GPL (see
# COPYING).
# Test rsync handling of exclude/include directives.
# Test rsync handling of exclude/include directives.
# Test some of the more obscure wildcard handling of exclude/include
# processing.
@@ -76,7 +76,6 @@ EOF
echo cvsin >"$fromdir/mid/for/one-in-one-out"
echo expunged >"$fromdir/mid/for/foo/extra"
echo retained >"$fromdir/mid/for/foo/keep"
ln -s too "$fromdir/bar/down/to/foo/sym"
# Setup our test exclude/include files.
@@ -106,12 +105,17 @@ cat >"$scratchdir/.cvsignore" <<EOF
home-cvs-exclude
EOF
# Create the chk dir with what we expect to be excluded
# Start with a check of --prune-empty-dirs:
$RSYNC -av -f -_foo/too/ -f -_foo/down/ -f -_foo/and/ -f -_new/ "$fromdir/" "$chkdir/"
checkit "$RSYNC -av --prune-empty-dirs '$fromdir/' '$todir/'" "$chkdir" "$todir"
rm -rf "$todir"
checkit "$RSYNC -avv \"$fromdir/\" \"$chkdir/\"" "$fromdir" "$chkdir"
# Add a directory symlink.
ln -s too "$fromdir/bar/down/to/foo/sym"
# Create chkdir with what we expect to be excluded.
checkit "$RSYNC -avv '$fromdir/' '$chkdir/'" "$fromdir" "$chkdir"
sleep 1 # Ensures that the rm commands will tweak the directory times.
rm -r "$chkdir"/foo/down
rm -r "$chkdir"/mid/for/foo/and
rm -r "$chkdir"/new/keep/this
@@ -126,8 +130,8 @@ $RSYNC -av --existing --include='*/' --exclude='*' "$fromdir/" "$chkdir/"
# Now, test if rsync excludes the same files.
checkit "$RSYNC -avv --exclude-from=\"$excl\" \
--delete-during \"$fromdir/\" \"$todir/\"" "$chkdir" "$todir"
checkit "$RSYNC -avv --exclude-from='$excl' \
--delete-during '$fromdir/' '$todir/'" "$chkdir" "$todir"
# Modify the chk dir by removing cvs-ignored files and then tweaking the dir times.
@@ -142,8 +146,8 @@ $RSYNC -av --existing --filter='exclude,! */' "$fromdir/" "$chkdir/"
# Now, test if rsync excludes the same files, this time with --cvs-exclude
# and --delete-excluded.
checkit "$RSYNC -avvC --filter=\"merge $excl\" --delete-excluded \
--delete-during \"$fromdir/\" \"$todir/\"" "$chkdir" "$todir"
checkit "$RSYNC -avvC --filter='merge $excl' --delete-excluded \
--delete-during '$fromdir/' '$todir/'" "$chkdir" "$todir"
# Modify the chk dir for our merge-exclude test and then tweak the dir times.
@@ -162,9 +166,9 @@ $RSYNC -av --existing --filter='-! */' "$fromdir/" "$chkdir/"
# Now, test if rsync excludes the same files, this time with a merge-exclude
# file.
checkit "sed '/!/d' \"$excl\" |
checkit "sed '/!/d' '$excl' |
$RSYNC -avv -f dir-merge_.filt -f merge_- \
--delete-during \"$fromdir/\" \"$todir/\"" "$chkdir" "$todir"
--delete-during '$fromdir/' '$todir/'" "$chkdir" "$todir"
# Remove the files that will be deleted.
@@ -180,9 +184,9 @@ $RSYNC -av --protocol=28 --existing --include='*/' --exclude='*' "$fromdir/" "$c
# Now, try the prior command with --delete-before and some side-specific
# rules.
checkit "sed '/!/d' \"$excl\" |
checkit "sed '/!/d' '$excl' |
$RSYNC -avv -f :s_.filt -f .s_- -f P_nodel.deep \
--delete-before \"$fromdir/\" \"$todir/\"" "$chkdir" "$todir"
--delete-before '$fromdir/' '$todir/'" "$chkdir" "$todir"
# Next, we'll test some rule-restricted filter files.
@@ -201,15 +205,15 @@ $RSYNC -av --existing --filter='-! */' "$fromdir/" "$chkdir/"
$RSYNC -av --delete-excluded --exclude='*' "$fromdir/" "$todir/"
checkit "$RSYNC -avv -f dir-merge,-_.excl \
\"$fromdir/\" \"$todir/\"" "$chkdir" "$todir"
'$fromdir/' '$todir/'" "$chkdir" "$todir"
relative_opts='--relative --chmod=Du+w --copy-unsafe-links'
$RSYNC -av $relative_opts "$fromdir/foo" "$chkdir/"
rm -rf "$chkdir$fromdir/foo/down"
$RSYNC -av $relative_opts --existing --filter='-! */' "$fromdir/foo" "$chkdir/"
checkit "$RSYNC -avv $relative_opts --exclude=\"$fromdir/foo/down\" \
\"$fromdir/foo\" \"$todir\"" "$chkdir$fromdir/foo" "$todir$fromdir/foo"
checkit "$RSYNC -avv $relative_opts --exclude='$fromdir/foo/down' \
'$fromdir/foo' '$todir'" "$chkdir$fromdir/foo" "$todir$fromdir/foo"
# The script would have aborted on error, so getting here means we've won.
exit 0

View File

@@ -14,10 +14,11 @@ mkdir "$todir"
cp -p "$srcdir"/rsync.c "$fromdir"/rsync.c
cp -p "$fromdir"/rsync.c "$todir"/rsync2.c
sleep 1
# Let's do it!
checkit "$RSYNC -avvi --no-whole-file --fuzzy --delete-after \
\"$fromdir/\" \"$todir/\"" "$fromdir" "$todir"
checkit "$RSYNC -avvi --no-whole-file --fuzzy --delete-delay \
'$fromdir/' '$todir/'" "$fromdir" "$todir"
# The script would have aborted on error, so getting here means we've won.
exit 0

Some files were not shown because too many files have changed in this diff Show More