Compare commits

...

983 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
Wayne Davison
0c6d79528a Preparing for release of 2.6.9 2006-11-07 04:41:35 +00:00
Wayne Davison
556e03a3c9 Modified to recognize FreeBSD's setfacl command. 2006-11-04 00:18:49 +00:00
Wayne Davison
e4887738bb Updated to the version dated 2006-07-02. 2006-11-02 02:01:25 +00:00
Wayne Davison
0f5c1c193a Need to include netinet/tcp.h to get TCP_NODELAY defined. 2006-10-31 19:21:57 +00:00
Wayne Davison
ab6dcad61c Mention the addition of the fake-super.diff patch. 2006-10-28 21:22:26 +00:00
Wayne Davison
b6855ddc9c Don't put backslashes before the dashes in " -- ". 2006-10-27 17:51:21 +00:00
Wayne Davison
0cbb958f34 Mention the fix for bug #4079. 2006-10-27 17:29:09 +00:00
Wayne Davison
418da6d952 Mention WIFEXITED() change. 2006-10-26 19:19:23 +00:00
Wayne Davison
51d133d686 Mention Mac OS X xattr work. 2006-10-26 17:22:15 +00:00
Wayne Davison
cbb95d3d24 Preparing for release of 2.6.9pre3 2006-10-26 17:06:41 +00:00
Wayne Davison
d9126a861f Run tweak_manpage_dashes on the man pages we generate. 2006-10-24 16:17:31 +00:00
Wayne Davison
b4768a1397 Undo temporary changes used for build-farm testing of ACL patch. 2006-10-24 15:09:57 +00:00
Wayne Davison
47b032e97f Added a define for WIFEXITED() that is used if one is missing. 2006-10-24 03:31:30 +00:00
Wayne Davison
50dfd5b4fe Document the --no-motd option. 2006-10-24 00:56:46 +00:00
Wayne Davison
1de02c273d Document the --no-motd option, with a caveat on how it can also
hide the module listing.
2006-10-24 00:36:46 +00:00
Wayne Davison
9ce7fc3887 Obey the new --no-motd option. 2006-10-24 00:36:42 +00:00
Wayne Davison
dc1f7b9ea3 Added the --no-motd option to silence just the text output at the
start of a daemon transfer.
2006-10-24 00:36:38 +00:00
Wayne Davison
ee7cf95b13 Post-process manpages with the tweak_manpage_dashes perl script. 2006-10-24 00:33:32 +00:00
Wayne Davison
492fc3536d Run patch with -t so that it doesn't ask any questions. 2006-10-24 00:24:56 +00:00
Wayne Davison
5e61bdb4d5 A perl script that does appropriate backslash escaping of '-' chars
in manpages.
2006-10-24 00:09:18 +00:00
Wayne Davison
f964ac5eee - Fixed an error-handling path in try_dests_reg().
- Added a comment.
2006-10-22 22:36:36 +00:00
Wayne Davison
c55b39afad Use "test" instead of "[ ... ]" for better portability. 2006-10-22 07:29:21 +00:00
Wayne Davison
a27463a9a2 Added missing cleanup of empty ACL files. 2006-10-22 07:18:21 +00:00
Wayne Davison
590eb6c02d Change the unpatch code for NetBSD. 2006-10-22 04:26:59 +00:00
Wayne Davison
0d7a6b4906 Temporary changes to have the build-farm configure and build
the ACL version of rsync (patched in via patches/acls.diff).
2006-10-22 03:17:45 +00:00
Wayne Davison
b4f0287197 Mention the fix that lets a push now override the partial-dir exclude. 2006-10-18 05:20:05 +00:00
Wayne Davison
8d6386809e The server should not be adding an assumed filter rule based on the
partial-dir setting (since the client is sending us the rules).
2006-10-18 05:15:35 +00:00
Wayne Davison
230328a30a Added a risk filter for the partial-dir since we use --delete-after. 2006-10-18 05:14:10 +00:00
Wayne Davison
5819d6b14a Stop disabling the RSYNC_PARTIAL_DIR environment variable now that
there is a newer rsync on samba.org.
2006-10-18 04:46:26 +00:00
Wayne Davison
7b4a40ed70 Make sure the new link_dest_used value gets zeroed on init. 2006-10-17 18:49:04 +00:00
Wayne Davison
f210dcadf4 - Fixed a compile problem ("len" not defined) in inet_ntop4().
- Replaced sprintf() with snprintf() in inet_ntop6().
2006-10-16 18:11:24 +00:00
Wayne Davison
178a1d2048 - Die if we can't edit the release date into NEWS or OLDNEWS.
- Don't remove any *pre*diff* files until the final release.
2006-10-15 21:44:15 +00:00
Wayne Davison
a4b4e0770b Improved a comment. 2006-10-15 15:57:27 +00:00
Wayne Davison
2a6e35db31 Improved a couple existing items. 2006-10-15 15:49:31 +00:00
Wayne Davison
e3794138d8 Use the new case_N.h file to make sure that our cleanup_step case
statements never get out of sequence when the code changes.
2006-10-15 15:43:26 +00:00
Wayne Davison
fdd10da6f7 A helper file for cleanup.c. 2006-10-15 15:42:01 +00:00
Wayne Davison
5f12a07bff Now that samba.org has a modern rsync, we can go back to using
hard-links on the moved files and use rsync to effect the hard-
links on the remote system (which will make a future transfer
more efficient in the absense of --detect-renamed).
2006-10-15 05:04:59 +00:00
Wayne Davison
6a4a1d0cb0 Preparing for release of 2.6.9pre2 2006-10-14 20:35:17 +00:00
Wayne Davison
434c40986d Use the MAX_RENAMES_DIGITS define in the relevant snprintf(). 2006-10-14 20:31:33 +00:00
Wayne Davison
8ee6857702 Improved the description of the code-checker work.. 2006-10-14 20:30:43 +00:00
Wayne Davison
721ddc903f Updated the news about the exit_cleanup() improvement. 2006-10-14 20:01:22 +00:00
Wayne Davison
154c345db0 Improved the _exit_cleanup() function to handle potential recursions
back to the function via the calls that it is making.  The new code
treats each recursion back into the function as an opportunity to
take up where we left off (skipping whatever step just failed).
2006-10-14 19:58:52 +00:00
Wayne Davison
25f637a334 Got rid of EXIT_OR_RETURN() macro again -- switching to a better
recursion-prevention heuristic in _exit_cleanup().
2006-10-14 18:51:21 +00:00
Wayne Davison
2356d73bb4 The cleanup code that handles moving the temp file to the partial
file needed to check that cleanup_fname was not NULL to prevent
any possibility of a recursion starting into that code again.
2006-10-14 02:29:29 +00:00
Wayne Davison
4968423e71 Mention the latest fixes and internal changes. 2006-10-14 02:02:47 +00:00
Wayne Davison
99eba67585 Got rid of the recent paranoid length check because it didn't help
to silence a code-checker warning.
2006-10-14 01:17:36 +00:00
Wayne Davison
5abe03d6e8 Restore build order back to normal. 2006-10-14 01:15:16 +00:00
Wayne Davison
83078af5b0 Changed sprintf() calls to snprintf(). 2006-10-13 23:46:32 +00:00
Wayne Davison
185aa5b0e5 Turned an sprintf() call into snprintf(). 2006-10-13 23:42:52 +00:00
Wayne Davison
cabd60fdce - Changed some sprintf() calls to snprintf() calls.
- Changed two last strcpy() calls to strlcpy() calls.
2006-10-13 23:38:14 +00:00
Wayne Davison
10944395bf Changed sprintf() calls to snprintf() calls. 2006-10-13 23:35:53 +00:00
Wayne Davison
204f4f4d09 Changed strcpy() calls into memcpy() calls. 2006-10-13 23:17:37 +00:00
Wayne Davison
c9bce0b8f8 Changed strcpy() calls into strlcpy() calls, just to be extra safe. 2006-10-13 23:17:33 +00:00
Wayne Davison
deee574b11 Added a paranoid length check. 2006-10-13 23:17:30 +00:00
Wayne Davison
55410368e5 - Changed strcpy() calls into strlcpy() calls, just to be extra safe.
- Added a default: exit_cleanup() case to a switch.
- Made the check_name() function take a buffer size arg.
2006-10-13 23:17:27 +00:00
Wayne Davison
e4fdf1debe - Use precompiler conditionals in to_wire_mode() and from_write_mode()
to get rid of code that is not needed on the current system.
- Silence a code-checker warning in send_file_entry().
- Silence a code-checker warning in make_file().
- Fixed a bug in f_name_cmp() that could compare an empty filename
  incorrectly (which might only happen if we transformed a dot-dir
  into an empty name).  (Thanks, code checker!)
2006-10-13 17:07:13 +00:00
Wayne Davison
1580899c1d More temporary name juggling to get all code analyzed. 2006-10-13 17:02:39 +00:00
Wayne Davison
f863b76300 Changed one more exit_cleanup() call into EXIT_OR_RETURN(). 2006-10-13 14:28:56 +00:00
Wayne Davison
5e1ec06f09 Temporarily reorder the OBJS line so that the IBM code checker
can analyze some of the other programs (since it runs out of
time analyzing them all).
2006-10-13 14:17:22 +00:00
Wayne Davison
36e2ea6068 Use new FNONE value when setting/comparing enum logcode vars. 2006-10-13 07:48:35 +00:00
Wayne Davison
f4164b73b4 - Use the new FNONE enum instead of a literal 0 value. 2006-10-13 07:38:21 +00:00
Wayne Davison
9ef506a2b2 If in_exit_cleanup is set, some of our functions return instead of
calling exit_cleanup() (which is a safer way to avoid an infinite
loop when the exit code uses the log functions than allowing the
_exit_cleanup() function to return back into our code).
2006-10-13 07:38:18 +00:00
Wayne Davison
b1b54199ef - When exiting, set the flag "in_exit_cleanup".
- Mark _exit_cleanup() with NORETURN.
- Don't ever return from _exit_cleanup().
2006-10-13 07:38:15 +00:00
Wayne Davison
33394b769d Mark out_of_memory() and overflow_exit() with NORETURN. 2006-10-13 07:38:11 +00:00
Wayne Davison
011e85a5e3 - Added FNONE to the "enum logcode" values.
- Added a NORETURN define to mark a function that never returns.
2006-10-13 07:38:05 +00:00
Wayne Davison
d5dcb6f775 Silence some IBM checker warnings and made a slight optimization
to get_tmpname().
2006-10-13 07:18:29 +00:00
Wayne Davison
0c25dedf31 Simplified the function-finding regex, and made it more versatile
(so we don't need to keep adding variable-type strings).
2006-10-13 06:50:56 +00:00
Wayne Davison
6105464b79 Indented the function comments with "* ". 2006-10-13 06:49:44 +00:00
Wayne Davison
4d51f0db79 Don't use a bool directly in an int comparison. 2006-10-13 06:27:59 +00:00
Wayne Davison
ff530f04a0 Function fcntl() only takes 2 args when using F_GETFL. 2006-10-13 06:26:02 +00:00
Wayne Davison
e8b21fe406 Cast pat_len to an int when using it as a field width. 2006-10-13 06:24:24 +00:00
Wayne Davison
71cb9df386 Some OSes can't chmod -t for a file, so I changed the logic of our
to to substitute a chmod that will work everywhere.
2006-10-13 04:59:53 +00:00
Wayne Davison
f97c2d4a9b - Clarified the "dont compress" option.
- Cleaned up some trailing whitespace.
2006-10-13 01:37:44 +00:00
Wayne Davison
b8a6dae038 Updated the man pages to work with version 2.x of yodl. 2006-10-13 01:24:57 +00:00
Wayne Davison
969f7ed5b7 Fixed an infinite loop in parse_rule() when a filter rule is too
longer for MAXPATHLEN.  Also fixed a couple spots nearby that were
erroneously treating pointer "cp" as a '\0'-terminated string.
2006-10-13 01:22:48 +00:00
Wayne Davison
e825409a84 Preparing for release of 2.6.9pre1 2006-10-12 03:45:53 +00:00
Wayne Davison
b8d29fd8e6 Added a line for 2.6.9. 2006-10-12 03:44:44 +00:00
Wayne Davison
200f2d98db Make sure we tweak the right RSYNC_VERSION line in configure. 2006-10-12 03:32:18 +00:00
Wayne Davison
1a7f3d99c5 Removed the changes in symlink handling in non-chroot daemon mode as
they were not yet safe (I'll consider similar changes for the next
release).
2006-10-12 03:01:18 +00:00
Wayne Davison
e80876700c Got rid of changes that aren't going to make it into 2.6.9. 2006-10-12 03:01:12 +00:00
Wayne Davison
ec55b4f2fb Changed the indent for one else ... if section. 2006-10-12 03:01:01 +00:00
Wayne Davison
798cde474f Some minor improvements to parse_merge_name(). 2006-10-12 02:14:47 +00:00
Wayne Davison
558d482c47 Renumbered tests after adding one in the middle. 2006-10-11 00:51:50 +00:00
Wayne Davison
418b6a2703 Handle the itemizing of of the "." dir when it is newly created. 2006-10-11 00:04:48 +00:00
Wayne Davison
1ef5bf3cfd If new_root_dir is set, itemize the output of the "." dir as a
directory-creation event.
2006-10-11 00:04:44 +00:00
Wayne Davison
2a94207ad6 Added a new variable, new_root_dir, that is set if we created the
destination directory.
2006-10-11 00:04:41 +00:00
Wayne Davison
ddcba3f075 Changed the fix_basis_dirs() function to only remove a single ../
prefix from each --*-dest option's path.
2006-10-10 23:44:59 +00:00
Wayne Davison
db3ae95cac Made some of the --link-dest tests use a relative destination
directory, and made one of those do a --dry-run test before
the regular test.
2006-10-09 03:06:50 +00:00
Wayne Davison
1a05de2bff - If a finished link came from a link-dest dir and --dry-run is in
effect, we now stat the link-dest file instead of the non-existent
  destination file.
- Use int32 for the index variables.
2006-10-09 03:05:19 +00:00
Wayne Davison
d9163a4cf5 If the combination of --dry-run, --link-dest, and -H finds a matching
file in on of the extra basis dirs, make a note of which basis dir
we would have used in the hard-link with the destination file.
2006-10-09 02:59:23 +00:00
Wayne Davison
44885a398f Added link_dest_used unsigned short to struct hlink and made the
other values explicitly 32-bit so that the total size can't be
larger than the other struct we're in a union with.
2006-10-09 02:57:04 +00:00
Wayne Davison
dfe1ed5e97 Another tweak to the --chmod summary. 2006-10-09 00:55:04 +00:00
Wayne Davison
242f6052c2 Mention the latest bug fix. 2006-10-08 22:17:39 +00:00
Wayne Davison
519d55a950 Make the daemon's "incoming chmod" tweaks happen last, as documented. 2006-10-08 22:02:13 +00:00
Wayne Davison
b6008dc645 Clarify the short description of --chmod. 2006-10-08 22:00:31 +00:00
Wayne Davison
6f3684ffb5 Call push_dir() with its new boolean arg. 2006-10-08 20:57:01 +00:00
Wayne Davison
615a5415c9 - Call push_dir() with its new boolean arg, including the spot in
get_local_name() where we need push_dir() to skip the chdir() because
  the destination dir does no yet exist and --dry-run was specified.
- Added fix_basis_dirs(), which will combine the dest-dir with each non-
  absolute basis_dir arg to make sure that they end up being relative to
  the right dir when --dry-run was specified and the dest dir does not
  yet exist.
2006-10-08 20:56:56 +00:00
Wayne Davison
ba081be327 Made the push_dir() function take an option to skip the actual chdir()
call.  Used when the dest-dir doesn't exist and --dry-run was specified.
2006-10-08 20:56:52 +00:00
Wayne Davison
3e88414e4e Moved some of the variable setup from "make check" into the
runtest.sh script.
2006-10-07 14:54:56 +00:00
Wayne Davison
0888952768 Moved some variable setup here from the Makefile and made it
possible to specify extra rsync options for the test.
2006-10-07 14:54:14 +00:00
Wayne Davison
5dcd9a2b70 Changed the -o to -a in the "if". 2006-10-07 14:39:01 +00:00
Wayne Davison
6ce9432d75 A bug-fix for die_on_unsafe_path() when the path doesn't exist. 2006-10-07 14:19:00 +00:00
Wayne Davison
6c8507724b Added exception-checking to a couple select() calls, as suggested
by Hugh Daschbach.
2006-09-30 22:11:20 +00:00
Wayne Davison
d04e95e968 Document that --ignore-times thwarts all --link-dest linking. 2006-09-30 15:21:25 +00:00
Wayne Davison
b06050f9ad I decided that combining --link-dest with -I doesn't make much sense
(without some kind of a post-transfer identicality check, at least)
so I'm removing the code that tried to make the two play nice.
2006-09-30 15:20:17 +00:00
Wayne Davison
ad75d18d2e Mention that the --backup-dir option is a receiver-side path. 2006-09-26 16:44:27 +00:00
Wayne Davison
ed4b8da048 Mention the latest bugfix. 2006-09-24 03:36:04 +00:00
Wayne Davison
2cd421d809 Output the who_am_i() info in out-of-memory() and overflow_exit(). 2006-09-24 03:12:24 +00:00
Wayne Davison
ea0ea357f4 Provide the who_am_i() function. 2006-09-24 03:11:41 +00:00
Wayne Davison
0480a946f5 Some more testing based on Matt's recent patch. 2006-09-23 23:49:20 +00:00
Wayne Davison
67f8a41be5 Matt tracked down a bug in the daemon option "incoming chmod" where
a newly created directory would get the chmod permissions that were
specified for a file (via the F previx).
2006-09-23 23:15:11 +00:00
Wayne Davison
5e1f082d0c Improvments by Matt for the --progress option, including updating
the examples to look like the actual output in a modern rsync.
(I did a little rewording too...)
2006-09-23 00:07:28 +00:00
Wayne Davison
a633351962 Mention the current limitation of the RSYNC_EXIT_STATUS value. 2006-09-20 14:04:19 +00:00
Wayne Davison
2edfe52230 Mention the new --remove-s*-files error. 2006-09-20 01:54:40 +00:00
Wayne Davison
acee1ad853 Complain if a --remove-s*-files option is set and we can't remove
the source file.
2006-09-20 01:53:32 +00:00
Wayne Davison
8f4ae68ca7 The [ & ] are now removed from a literal IPv6 hostname passed to the
remote shell.
2006-09-18 17:39:13 +00:00
Wayne Davison
ff1b9344c9 When parsing a literal IPv6 address in square brackets, pass the
whole string (including the brackets) to the remote shell.  (The
old code stripped the leading '[' but left the trailing ']'.)
2006-09-18 01:19:26 +00:00
Wayne Davison
a923437bc0 Added a missing '-' to the string "-rsh". 2006-09-18 01:15:19 +00:00
Wayne Davison
dde698c2e8 Mention the permission bug-fix for new files created by --inplace. 2006-09-18 00:47:56 +00:00
Wayne Davison
c2b47e31a5 Mention the adding of the --remove-source-files option. 2006-09-18 00:38:20 +00:00
Wayne Davison
4e0bf97716 Mention the --server and --sender option as being internal,
not-for use by a normal user options.  Also mention the
support/rrsync script in this context.
2006-09-18 00:19:04 +00:00
Wayne Davison
174e51b5bf Added parsing for all the latest options. 2006-09-18 00:16:31 +00:00
Wayne Davison
30cd7ec1cf The --min-size arg doesn't need to be path-checked either. 2006-09-18 00:13:50 +00:00
Wayne Davison
48459ba15c The --inplace option now notices when the basis data is not coming
from the destination file (or an identical copy) and always writes
out the data (instead of seeking when at an identical offset).
2006-09-17 23:28:19 +00:00
Wayne Davison
48ecccce2d The --delete-excluded code now also drops any merge file that was
marked as MATCHFLG_NO_PREFIXES because they can only contain
include/exclude rules.
2006-09-09 18:59:10 +00:00
Wayne Davison
a739128df9 Document the new RSYNC_PID environment variable. 2006-09-09 18:56:13 +00:00
Wayne Davison
2c1775620a Try various long, long-long, etc. types for a 64-bit integer
before trying off64_t.
2006-09-09 18:53:23 +00:00
Wayne Davison
40f910c43a Mention the latest changes. 2006-09-09 18:31:45 +00:00
Wayne Davison
503114a782 Added the RSYNC_PID environment variable for the pre-/post-xfer
commands so that the pre-xfer command has a unique ID it can
use to cache information for the post-xfer command.
2006-09-09 17:59:02 +00:00
Wayne Davison
71f9e4673e A slight simplification to the last change. 2006-09-02 20:05:08 +00:00
Wayne Davison
176e8e94c3 An even better way to un-backslash-escape the filenames from find. 2006-09-02 19:57:56 +00:00
Wayne Davison
814b340c27 Improved the --delete-excluded test based on Matt's input and
another corner case I noticed.
2006-09-01 00:43:52 +00:00
Wayne Davison
f167879035 Matt pointed out that the code was not properly dropping excludes
that were read from a per-dir merge file when --delete-excluded
is enabled.  This additional code fixes that.
2006-09-01 00:42:39 +00:00
Wayne Davison
4187572616 Fixed handling of filenames with an embedded $, @, or %. 2006-08-31 20:30:16 +00:00
Wayne Davison
ff43d8b449 Added Matt's --delete-excluded test for merge-file correctness. 2006-08-31 17:19:26 +00:00
Wayne Davison
97bf86f8ee Make sure that --delete-excluded does not elide a per-dir merge
filter file, while still dumping the .cvsignore file from -C.
2006-08-31 17:18:24 +00:00
Wayne Davison
8c449e6285 When we're cleaning up a path of "/" in relative mode, we must make
the name "/." (as it was of old) so that there is a filename for us
to send.  Fixes a problem with --delete --relative when copying from
the root (/) of the filesystem.
2006-08-26 16:02:17 +00:00
Wayne Davison
29930a9fd2 Fixed an exclude bug with --relative excluding "/". 2006-08-12 16:22:03 +00:00
Wayne Davison
c98ad3df96 Check return value of asprintf() in full_fname(), as pointed
out by Ilja van Sprundel.
2006-07-29 21:04:35 +00:00
Wayne Davison
9c3c30e5c7 Assign datarootdir=@datarootdir@ so that a modern autoconf
doesn't complain about our Makefile.in.
2006-07-21 13:58:52 +00:00
Wayne Davison
b4a09b72ee Use new MAKEDEV() macro instead of makedev() directly. 2006-07-10 04:25:53 +00:00
Wayne Davison
5a3810b463 Define MAKEDEV() based on the MAKEDEV_TAKES_3_ARGS define. 2006-07-10 04:25:10 +00:00
Wayne Davison
e8d97006e5 If makedev() takes 3 args, define MAKEDEV_TAKES_3_ARGS. 2006-07-10 04:24:07 +00:00
Wayne Davison
8adc22e362 Mention the "munge symlinks" daemon setting. 2006-07-03 22:35:41 +00:00
Wayne Davison
dcebf78fe0 Obey the new "munge symlinks" dameon setting. 2006-07-03 22:35:00 +00:00
Wayne Davison
651c8510e8 Document "munge symlinks". 2006-07-03 22:33:56 +00:00
Wayne Davison
1ed3f5ed61 Added the "munge symlinks" setting. 2006-07-03 22:33:49 +00:00
Wayne Davison
70c81b0c07 Fixed the indentation on a few lines. 2006-07-03 22:30:13 +00:00
Wayne Davison
47c1197534 Decided that I like remove-source-files better than remove-sender-files. 2006-06-30 15:52:52 +00:00
Wayne Davison
fb41a3c669 Changed --remove-sent-files into --remove-sender-files. 2006-06-30 15:42:41 +00:00
Wayne Davison
2700069d5a Added --remove-sender-files and deprecated --remove-sent-files. 2006-06-30 15:42:36 +00:00
Wayne Davison
044ccbaacf The remove_sent_files var was renamed to remove_sender_files. 2006-06-30 15:42:32 +00:00
Wayne Davison
841d943651 Handle the --remove-sender-files option by sending MSG_SUCCESS for
any file that is being hard-linked.
2006-06-30 15:42:29 +00:00
Wayne Davison
04cd8789cb Handle the --remove-sender-files option by sending MSG_SUCCESS for
any up-to-date file (non-dir).
2006-06-30 15:42:26 +00:00
Wayne Davison
9578783a71 Changed the name of the nightly symlink. 2006-06-30 14:26:01 +00:00
Wayne Davison
4cff5fa462 Make use of module_dirlen in full_fname(). 2006-06-30 14:24:25 +00:00
Wayne Davison
cc1b4f776a Allow --with-nobody-group=GROUP (patch from Olivier Thauvin). 2006-06-19 19:30:51 +00:00
Wayne Davison
72d1b262ac Mention the latest bug-fix. 2006-06-16 09:05:21 +00:00
Wayne Davison
6fb7cc38a2 Make sure that the %f escape always has the full path info when
receiving files.
2006-06-16 09:01:31 +00:00
Wayne Davison
8a7b8400e7 Updated the "use chroot" section with the latest symlink info. 2006-06-16 08:56:26 +00:00
Wayne Davison
d2ab094dec Mention the latest log-file improvements. 2006-06-07 23:06:18 +00:00
Wayne Davison
ccd2966da9 Moved the "log file" and "syslog facility" sections into the per-module
options and improved them a little.
2006-06-07 23:05:27 +00:00
Wayne Davison
6dc9b74bc6 Call log_init() with its new "restart" (0 or 1) arg. 2006-06-07 23:05:24 +00:00
Wayne Davison
04c841190f - Pass "module_id" to the two log-related settings that are no longer
global.
- Added a "restart" arg to log_init() that lets us request that logging
  be reinitialized if the log-file/syslog-facility params changed.
2006-06-07 23:05:17 +00:00
Wayne Davison
d20ce6e144 Made "log file" and "syslog facility" per-module settings. 2006-06-07 23:05:14 +00:00
Wayne Davison
a7d461fccd Improved some comments in get_local_name() and improved the
error checking a little more.
2006-06-05 22:50:52 +00:00
Wayne Davison
4c5a2da65f Mention the latest bug-fix. 2006-06-05 17:00:47 +00:00
Wayne Davison
caff33228e If we fail to create a new directory, skip trying to update
everything that is inside that dir.
2006-06-05 16:56:50 +00:00
Wayne Davison
f38f6f80b7 Added FLAG_MISSING. 2006-06-05 16:52:34 +00:00
Wayne Davison
e848e06618 Got rid of an unused extern. 2006-06-05 16:17:33 +00:00
Wayne Davison
eece5fe32c Mention the temp-file fix. 2006-06-01 08:40:55 +00:00
Wayne Davison
8590993185 Got rid of the FNAME logcode enum. 2006-06-01 08:04:50 +00:00
Wayne Davison
b64ee91a41 Changed rprintf() messages that started with a newline into two
rprintf() calls (the first of which just outputs an empty line).
2006-06-01 08:04:47 +00:00
Wayne Davison
d0133e6eba - Got rid of the FNAME logcode enum.
- rwrite() no longer supports newlines at the start of the string.
- maybe_log_item() avoids outputting a non-significant update to
  the log file if the log-file-format doesn't include %i.
2006-06-01 08:04:43 +00:00
Wayne Davison
1925c3448c - Got rid of the FNAME logcode enum.
- We no longer output " is uptodate" messages to the log file.
2006-06-01 08:04:40 +00:00
Wayne Davison
19b8587654 Fixed a typo that set stdout_format_has_i instead of logfile_format_has_i. 2006-06-01 06:49:15 +00:00
Wayne Davison
051f5df526 Mention the latest --log-* option changes. 2006-05-30 18:35:36 +00:00
Wayne Davison
e525519509 Authorize the current host in the rsyncd.conf file in addition
to localhost and 127.0.0.1 (which will hopefully fix the failing
of the daemon tests on FreeBSD).
2006-05-30 18:26:17 +00:00
Wayne Davison
4b90820d9f - Added the --log-file-format option to the daemon section.
- Updated and improved the --out-format section.
- Moved and improved the description of the non-daemon --log-file and
  --log-file-format options.
2006-05-30 17:47:20 +00:00
Wayne Davison
2873603ab5 If the user specifies --log-file-format without --log-file,
ignore the useless value.
2006-05-30 17:41:54 +00:00
Wayne Davison
ec52c3b9da Skip transfer logging if the logfile_format string is empty. 2006-05-30 17:41:04 +00:00
Wayne Davison
10ae3406ee Allow the --log-file-format=FMT option (if given when starting a daemon)
to override the "log format" setting.
2006-05-30 17:15:24 +00:00
Wayne Davison
232658d9d3 - Allow the --log-file-format option to override the "log format"
setting when starting a daemon.
- Make a daemon refuse all --log-file* options.
- Don't use refuse logic on daemon-mode options given to a daemon
  module -- reject them via their own message.
2006-05-30 17:14:17 +00:00
Wayne Davison
c000002f46 Document the new --log-file-format option and renamed --log-format to
--out-format.
2006-05-29 22:57:05 +00:00
Wayne Davison
2fedf3d596 - Use the renamed stdout_format_has_i variable.
- Call log_item() with its new arg (and call it more often).
2006-05-29 22:57:01 +00:00
Wayne Davison
887d745549 Turn off the --log-file option on the server side for a local transfer. 2006-05-29 22:56:58 +00:00
Wayne Davison
20f90d5e8a Use the renamed stdout_format_has_i variable. 2006-05-29 22:56:55 +00:00
Wayne Davison
17bda2d109 - Use the renamed stdout_format_has_i variable.
- Call log_item() with its new arg.
2006-05-29 22:56:51 +00:00
Wayne Davison
b534351058 - Use the renamed stdout_format_has_i, stdout_format_has_o_or_i, and
stdout_format variables.
- In rwrite(), make FNAME output only go to the client.
- Added an arg to log_item() that indicates what kind of output is
  desired: FNAME (stdout only),  FLOG (log file only), or FINFO (both).
2006-05-29 22:56:48 +00:00
Wayne Davison
b3e4e7ef2e - Renamed log_format -> stdout_format.
- Renamed log_format_has_i -> stdout_format_has_i.
- Renamed log_format_has_o_or_i -> stdout_format_has_o_or_i.
- Changed the --log-format to --out-format (though we still accept
  the old option, and still send it as well).
- Added the --log-file-format option (and got rid of the code that
  made --out-format sometimes affect the log-file's format).
2006-05-29 22:56:45 +00:00
Wayne Davison
a3f6dbdf5c The print_child_argv() function should be outputting FCLIENT
messages these days, not FINFO.
2006-05-29 22:33:06 +00:00
Wayne Davison
95ae5224b0 The cleanup_set() call was not getting called w/o --partial. 2006-05-18 18:53:24 +00:00
Wayne Davison
03dbc0b831 - Improved the setting of cleanup_new_fname and cleanup_fname.
- Don't try to keep a partial file if cleanup_new_fname is not set.
2006-05-18 18:52:40 +00:00
Wayne Davison
ffa8ab8eb5 Improved two lseek() error messages. 2006-05-18 17:04:40 +00:00
Wayne Davison
a17e119d8b Mention the latest fixes. 2006-05-17 06:54:11 +00:00
Wayne Davison
6bfc7b4d79 Tweaked a couple things in try_dests_reg(). 2006-05-16 22:27:26 +00:00
Wayne Davison
b3e8e7c79e Make --quiet quieter (like it used to be), but also don't allow it
to interfere with any logging of messages that is going on.
2006-05-14 00:27:33 +00:00
Wayne Davison
bdd3a4fef5 Updated the (commented out) valgrind command. 2006-05-11 23:41:18 +00:00
Wayne Davison
a00f5a371e Got rid of the .ignore kluge. 2006-05-11 23:38:10 +00:00
Wayne Davison
55c412630c Added ".bzr/" to the default CVS exclusions. 2006-05-11 07:54:33 +00:00
Wayne Davison
778ee637ee This file hasn't been needed for a while now... 2006-05-10 18:34:32 +00:00
Wayne Davison
80aff93b32 Added the updating of a symlink to the very latest nightly tar file. 2006-05-10 16:37:07 +00:00
Wayne Davison
6721973e37 Mention the --log-file option. 2006-05-09 18:44:58 +00:00
Wayne Davison
a2ed5801d3 Document the new --log-file option. 2006-05-09 18:31:24 +00:00
Wayne Davison
15ce4b24fc Output the progress message as FCLIENT instead of FINFO. 2006-05-09 18:31:19 +00:00
Wayne Davison
c5260884d6 Got rid of the call to log_exit() now that the cleanup code handles this. 2006-05-09 18:31:16 +00:00
Wayne Davison
ea124cb324 - Turned some FINFO rprintf() calls into FCLIENT calls that don't go
into a client-side log-file.
- Added a couple FLOG rprintf() calls.
2006-05-09 18:31:13 +00:00
Wayne Davison
13b597fa71 - Use the new logfile_* variables that are set by the --log-file
option instead of the old daemon_log_* variables.
- Renamed the "logfile" variable "logfile_fp".
- Enhanced the logic in rwrite() to handle client-side FLOG output.
2006-05-09 18:31:10 +00:00
Wayne Davison
ecc7623e7f Some demon_log_* variables changed into logfile_* variables that are
also used by the new --log-file option.
2006-05-09 18:31:06 +00:00
Wayne Davison
87c0f9d6b4 Added --log-file and several logfile_* support variables. 2006-05-09 18:31:03 +00:00
Wayne Davison
1cfcb8af11 Revised the logic for when to call log_exit() to handle the
new --log-file option.
2006-05-09 18:31:00 +00:00
Wayne Davison
56aaa4c44c Tweaked the comment about log-message categories. 2006-05-09 18:30:57 +00:00
Wayne Davison
4b6a7bd706 Got rid of an unused variable. 2006-05-09 18:00:15 +00:00
Wayne Davison
5bc933a285 Mention the latest bugfix and improved an old description. 2006-05-09 17:46:04 +00:00
Wayne Davison
01d124d9e2 If the --partial-dir value is an absolute path and we use a file in
it as an alternate basis file, make sure that we delete it when the
associated destination file is successfully updated.
2006-05-09 17:38:47 +00:00
Wayne Davison
58a06312a4 Improved the doc for --existing and --ignore-existing. 2006-05-05 20:41:17 +00:00
Wayne Davison
c2c8db9195 - Moved the sanitizing of the partial_dir value here from options.c.
- Call die_on_unsafe_path() in a few needed places.
- Handle the server-excluded checks for an absolute partial_dir and
  the --*-dest options.
2006-05-05 16:00:33 +00:00
Wayne Davison
d1e6b0e225 - Added some calls to die_on_unsafe_path() to the path-sanitizing code.
- Moved the sanitizing of the partial_dir value into main.c.
2006-05-05 15:58:44 +00:00
Wayne Davison
8936367695 - Added a call to die_on_unsafe_path() to handle_partial_dir().
- Fixed some strange slash handling in partial_dir_fname().
2006-05-05 15:54:20 +00:00
Wayne Davison
8517e9c10a A few minor changes to match the recent --help changes in
options.c.
2006-05-05 06:24:25 +00:00
Wayne Davison
fcecb70b1d - Don't check HAVE_LINK directly, use SUPPORT_HARD_LINKS instead.
- Updated a few items in the --help text.
2006-05-05 06:16:22 +00:00
Wayne Davison
582c1589f3 Call the new die_on_unsafe_path() function in a few places. 2006-05-05 05:57:48 +00:00
Wayne Davison
cb15269eb0 Call the new die_on_unsafe_path() function in a couple spots. 2006-05-05 05:56:37 +00:00
Wayne Davison
f47807900b Added a new function named die_on_unsafe_path(). This is used
by a non-chroot daemon to ensure that a user-supplied path does
not contain an unsafe symlink element.
2006-05-05 05:55:40 +00:00
Wayne Davison
40410a38bc - Don't check HAVE_LINK directly, use SUPPORT_HARD_LINKS instead.
- Tweaked Paul's recent change just a tad.
- Fixed the output of --compare-dest when SUPPORT_HARD_LINKS is
  not defined.
2006-05-05 05:53:36 +00:00
Wayne Davison
6b54a688cf Cast file->mode to an int when printing it via %o. 2006-05-05 05:40:17 +00:00
Paul Green
b59dc8d5ae Fix generator.c to avoid calling do_link() on systems that do not support
the link() function.  The changes test OK on SuSE Linux and on my own
Stratus VOS system, but I would be grateful if other folks could
double-check this change.  Paul G.
2006-05-04 19:00:37 +00:00
Wayne Davison
45ba206a94 A few more improvements. 2006-05-04 02:42:55 +00:00
Wayne Davison
2220ec0a69 A few minor twiddles. 2006-05-04 02:38:58 +00:00
Wayne Davison
5fdbb87df8 Added/clarified the latest bug-fix info. 2006-05-04 02:29:58 +00:00
Wayne Davison
f1c9bcd0fc Cast the enum in rwrite() when calling send_msg(). 2006-05-03 16:58:36 +00:00
Wayne Davison
3723548ded Use send_msg() when forwarding a log message, not io_multiplex_write().
This allows send_msg() to decide if the message should be sent right
away, or should be deferred.
2006-05-03 16:17:49 +00:00
Wayne Davison
12ccc73ae7 Changed read_msg_fd() to always use send_msg()/rwrite() instead of
sometimes calling io_multiplex_write()/rwrite() or msg_list_add().
This simplifies the code that does the defer_forwarding_messages
checking because it can now be done in just one place, in send_msg()
(because rwrite() also calls send_msg() now when forwarding a msg).
2006-05-03 16:17:46 +00:00
Wayne Davison
ee8d9636d1 A small optimization to the new code in msg2sndr_flush(). 2006-05-03 06:32:59 +00:00
Wayne Davison
38de2866e5 Made log_init() call timestring() instead of just localtime() prior to a
chroot (note that timestring() makes use of localtime() plus strftime()).
2006-05-03 06:11:11 +00:00
Wayne Davison
bdac7621ee Improved the last bugfix description. 2006-05-03 05:37:00 +00:00
Wayne Davison
8ac4774675 Mention the fix for the "unexpected tag 3" bug. 2006-05-03 05:22:01 +00:00
Wayne Davison
229e1950ed Fixed a bug where deferred MSG_INFO/MSG_ERROR/MSG_LOG messages were
not being forwarded from the generator to the sender using rwrite()
(and MSG_LOG messages didn't need to be deferred at all).
2006-05-03 05:19:01 +00:00
Wayne Davison
93977bca10 Added module_dirlen now that utils.o needs it. 2006-05-03 00:49:31 +00:00
Wayne Davison
c2a2147a5b - Call safe_stat() instead of do_stat() when a sanitizing daemon might
need to ensure that it doesn't follow any unsafe symlinks.
- Got rid of startdir_depth code (in favor of util.c's curr_dir_depth).
- Use the new calling syntax for sanitize_path().
2006-05-03 00:48:32 +00:00
Wayne Davison
73173af955 - Call safe_stat() instead of do_stat() when a sanitizing daemon might
need to ensure that it doesn't follow any unsafe symlinks.
- Don't sanitize the string of a symlink -- just use it verbatim.
2006-05-03 00:48:29 +00:00
Wayne Davison
a2248aea2e - Call safe_stat() instead of do_stat() when a sanitizing daemon might
need to ensure that it doesn't follow any unsafe symlinks.
- Use the new calling syntax for sanitize_path().
2006-05-03 00:48:26 +00:00
Wayne Davison
a8167c6611 - Added curr_dir_depth, a variable that keeps track of the depth past
the module root when a sanitizing daemon is running.
- Use the new calling syntax for sanitize_path().
- Updated count_dir_elements() to not count a . component.
- Improved sanitize_path() so that it can take a symlink target string
  and combine it with the symlink's name when the target is relative.
  When working with a symlink, the routine also returns NULL if any ..
  elements try to escape past the module root.
- The new routine safe_stat(), is used when sanitizing paths (i.e. when
  the daemon does not have chroot enabled).  This manually follows a
  chain of symlinks, ensuring they don't try to escape the module.
2006-05-03 00:48:23 +00:00
Wayne Davison
91f4b31fe1 Use the new calling syntax for sanitize_path(). 2006-05-03 00:48:20 +00:00
Wayne Davison
cad8f6f980 Tweaked some variable names in readlink_stat() and link_stat(). 2006-05-02 19:52:28 +00:00
Wayne Davison
d8bf7ea8e9 Mention the latest bug-fixes. 2006-05-02 17:38:34 +00:00
Wayne Davison
d8f28a663c Test the new symlink sanitizing fix by using ::test-scratchdir/to
as the destination and including a symlink with a leading "../" .
2006-05-02 17:13:11 +00:00
Wayne Davison
2ae4126a9e Tweaked our test config file to include transfer logging that
includes %i, and to have a test-scratchdir module.
2006-05-02 17:11:42 +00:00
Wayne Davison
6f1c2aab43 Moved the sanitizing of a symlink's link string here from flist.c. 2006-05-02 16:52:51 +00:00
Wayne Davison
e71c1c26df Fixed a problem in the --link-dest processing where -I (--ignore-times)
or --size-only could adversely affect our ability to find identical
files to hard-link.
2006-05-02 16:46:48 +00:00
Wayne Davison
b24498ec2c Set a new variable, startdir_depth, to indicate how deep the
destination dir is in a daemon module's path.
2006-05-02 16:42:20 +00:00
Wayne Davison
b2d4639543 Got rid of the sanitizing of a symlink's link string because it
is happening too early to work correctly (before we know what
our destination-directory's depth in the module will be).
2006-05-02 16:36:07 +00:00
Wayne Davison
d3ef985954 We can't check the --*-dest args against the server filter rules
here because we don't know what the args are going to be relative
to yet.
2006-04-28 17:34:53 +00:00
Wayne Davison
7c58c99184 We sanitize the --*-dest args here so they can be relative to the
destination directory.
2006-04-28 16:58:20 +00:00
Wayne Davison
ad77db8b71 Moved the sanitizing of the --*-dest args into main.c. 2006-04-28 16:57:39 +00:00
Wayne Davison
e7c67065c0 Updated the FSF's address to an even newer one. 2006-04-25 23:51:12 +00:00
Wayne Davison
0f78b81511 - Updated the address for the FSF in the opening comment.
- Standardized the format of the opening comment, including adding a
  brief description of what's in the file for those that lacked it.
- Added some missing copyright lines.
- Some minor whitespace tweaks (in a few of the files).
2006-04-25 20:23:34 +00:00
Wayne Davison
d051056f92 Tweaked some whitespace to match the latest version from autoconf. 2006-04-24 23:43:45 +00:00
Wayne Davison
a4a38e8df0 Incremented the version to 2.6.9cvs. 2006-04-24 22:24:40 +00:00
Wayne Davison
60ef8ed128 Rolled over the news file for the next version. 2006-04-24 22:23:56 +00:00
Wayne Davison
8aa0dc7838 Updated to the version dated 2006-02-23. 2006-04-24 22:20:10 +00:00
Wayne Davison
4177f09b83 Preparing for release of 2.6.8 2006-04-22 15:39:57 +00:00
Wayne Davison
acaadb55c1 Mention the phase-unknown changes. 2006-04-21 16:57:13 +00:00
Wayne Davison
b88c2e8ffe - Got rid of the (mostly useless) io_read_phase and io_write_phase
variables.  In the future it might be useful to get rsync to
  mention what kind of a message it was trying to write, but the
  'phase "unknown"' output was ubiquitous and confusing.
- Got rid of the completely unused write_int_named() function.
2006-04-21 16:40:19 +00:00
Wayne Davison
f4ea5f47dc Got rid of the setting of io_write_phase. 2006-04-21 16:36:30 +00:00
Wayne Davison
62ae66d43b Mention the security fix for patches/xattrs.diff. 2006-04-21 00:05:30 +00:00
Wayne Davison
8641d28740 Improved the --owner and --group sections. 2006-04-18 18:58:07 +00:00
Wayne Davison
de3438407c Twiddle the trailing output in non-live mode. 2006-04-18 06:43:17 +00:00
Wayne Davison
434764269c Fixed a typo in the new code. 2006-04-18 06:38:58 +00:00
Wayne Davison
ba212fe0b6 - Fixed --copy-dest behavior on a system where CAN_HARDLINK_SYMLINK
and/or CAN_HARDLINK_SPECIAL is not defined.
- Changed --link-dest behavior on such systems to work just like
  --copy-dest for the non-hard-linkable files.
2006-04-18 05:48:46 +00:00
Wayne Davison
5f93b4d35e A slight improvement to the logic in try_dests_non(). 2006-04-18 05:24:02 +00:00
Wayne Davison
f8db4a8ab4 Mention the latest bugfix. 2006-04-17 19:55:16 +00:00
Wayne Davison
398612ba07 Fixed a bug where special files were not getting hard-linked via
the --link-dest option.
2006-04-17 19:53:41 +00:00
Wayne Davison
77b013afb5 Don't use the -C option to make (since it's not portable). 2006-04-17 18:15:02 +00:00
Wayne Davison
08c0cd8a42 Mention the latest fixes. 2006-04-17 18:00:09 +00:00
Wayne Davison
1c6e9dfabc Use the new CAN_HARDLINK_SYMLINK and CAN_HARDLINK_SPECIAL defines
from configure instead of the old (and not quite correct) run-time
checking.
2006-04-17 17:56:10 +00:00
Wayne Davison
0037bf23fc Added two new checks: 1. Does link() hard-link symlinks (not the
referent)?  2. Does link() hard-link a fifo?
2006-04-17 17:53:47 +00:00
Wayne Davison
285edc9169 Don't use -C with make because it's not portable. 2006-04-17 17:37:13 +00:00
Wayne Davison
c4aa84ad50 Got rid of the unused REPLACE_INET_NTOA and REPLACE_INET_ATON checks. 2006-04-13 16:54:24 +00:00
Wayne Davison
b635bc92d1 Got rid of inet_ntoa -> rep_inet_ntoa tom-foolery because rsync
doesn't use inet_ntoa() anymore.
2006-04-13 16:53:15 +00:00
Wayne Davison
146d2228cc Got rid of the replacement inet_aton() and inet_ntoa() functions
because no code in rsync has used these functions since 2.4.8.
2006-04-13 16:52:15 +00:00
Wayne Davison
b2501ccf12 Improved a sentence. 2006-04-12 16:59:32 +00:00
Wayne Davison
e60bba3fbc A few minor changes to some messages and a couple variable improvements. 2006-04-12 16:35:53 +00:00
Wayne Davison
e26cfccf16 Preparing for release of 2.6.8pre1 2006-04-12 16:23:46 +00:00
Wayne Davison
74f80abce2 Moved the include of netinet/ip.h into socket.c. 2006-04-11 00:48:55 +00:00
Wayne Davison
5899b8cf3e Moved the include of netinet/ip.h here along with its apparent
prerequisite, netinet/in_systm.h .
2006-04-11 00:48:28 +00:00
Wayne Davison
08e0a62956 Tweaked a comment. 2006-04-11 00:28:02 +00:00
Wayne Davison
2bd17a51ae Include netinet/ip.h . 2006-04-09 13:51:56 +00:00
Wayne Davison
c7b9ebb598 Mention the read-position fix. 2006-04-08 16:43:21 +00:00
Wayne Davison
e3db43ffe5 Fixed the value of map->p_fd_offset when a read() fails or is
abbreviated.
2006-04-08 16:37:50 +00:00
Wayne Davison
f61ab01d96 Use --delete-after instead of --delete. 2006-04-08 16:36:57 +00:00
Wayne Davison
ceca8ccac8 We don't need log_initialised exported after all. 2006-04-08 16:04:34 +00:00
Wayne Davison
374c3e1278 Moved the calls to client_addr() and client_name() below the lp_load()
call so that their potential to output log messages can't cause the
log-file to initialize before we know what "log name" to use.
2006-04-08 16:03:16 +00:00
Wayne Davison
e09d8a304c Clarified a few items. 2006-04-06 07:54:03 +00:00
Wayne Davison
2a7d9fe9b8 A slightly better fix than the last version. 2006-04-06 07:38:54 +00:00
Wayne Davison
e63aeb6d68 Made log_initialised public. 2006-04-06 07:33:12 +00:00
Wayne Davison
077d5d4ebc There's no need for lp_load() to check am_daemon. 2006-04-06 07:28:22 +00:00
Wayne Davison
e2d774cdd7 Improved the bind()-failure message to mention what family failed. 2006-04-02 21:15:37 +00:00
Wayne Davison
415b598346 Got rid of duplicate rsync: prefix from an rsyserr() call. 2006-04-02 15:02:02 +00:00
Wayne Davison
69627d66f8 Improved a couple sentences. 2006-04-02 14:23:22 +00:00
Wayne Davison
ac98cd98e3 - Mention the logging fix for a single-use daemon.
- Mention the fatal error for when --daemon can't be honored.
2006-03-31 17:56:19 +00:00
Wayne Davison
91d324b4ea Log the connect message after calling log_init(). 2006-03-31 17:37:21 +00:00
Wayne Davison
89fb50263b - Complain if the user specified --delete without -r or -d.
- Got rid of the saw_delete_* vars.
2006-03-28 23:09:36 +00:00
Wayne Davison
e257c6c20b Use the regular delete* vars instead of the saw_delete* vars
(which are no longer around).
2006-03-28 23:09:07 +00:00
Wayne Davison
43eae40e45 Include the version number when we exit with an error or warning. 2006-03-28 18:23:24 +00:00
Wayne Davison
920240a687 - Mention two omitted --files-from bug-fixes.
- Added a place-holder release line for 2.6.8.
2006-03-28 16:49:23 +00:00
Wayne Davison
f8b9da1a2c Output the who_am_i() info in the "unknown message" error. 2006-03-28 06:12:18 +00:00
Wayne Davison
3c987ee956 Mention latest tweaks. 2006-03-22 18:26:44 +00:00
Wayne Davison
5c6d46329b If open_socket_in() fails, we now log the reasons why. 2006-03-22 17:48:59 +00:00
Wayne Davison
8b3e964d14 Mention the new support/file-attr-restore script. 2006-03-21 18:11:43 +00:00
Wayne Davison
91a93df049 A nice file-attribute maintenance script that lets you restore
permissions, ownership, and group-info on files that may be
different than the originals.
2006-03-21 18:06:26 +00:00
Wayne Davison
19826af5f0 Fixed a few things that looked like yodl macros but were not. 2006-03-21 03:45:03 +00:00
Wayne Davison
49f4cfdf39 Improved a few things that a more modern yodl complained about. 2006-03-21 03:41:00 +00:00
Wayne Davison
b3222792ad Changed where ITEM_REPORT_ATIME goes in the list. 2006-03-17 23:57:19 +00:00
Wayne Davison
0640710115 Go ahead and define upcoming ITEM_REPORT_* defines now. 2006-03-17 21:59:25 +00:00
Wayne Davison
fa65989a8b Added support for using solaris's "setfacl -s" in place of
GNU's "setfacl -k".
2006-03-16 21:37:18 +00:00
Wayne Davison
4209f079dd Make sure that the --relative test creates the implied directories
with user-write permission, and turns any symlinks in the implied
dirs into real dirs.
2006-03-16 20:02:36 +00:00
Wayne Davison
a7704777ce An extra safeguard for msg2sndr_flush(). 2006-03-16 10:08:08 +00:00
Wayne Davison
7d51b8374d Made the new msg2sndr handling even better. 2006-03-16 09:57:32 +00:00
Wayne Davison
a27042b521 Mention fix for stunnel-using rsync. 2006-03-16 03:18:16 +00:00
Wayne Davison
5b51c893c5 Optimized the reacquisition of the code value from the msg2sndr list. 2006-03-16 02:26:27 +00:00
Wayne Davison
408e69396c Fixed the reacquisition of the code value from the msg2sndr list. 2006-03-16 01:27:26 +00:00
Wayne Davison
954bbed84a - Optimized the msg_list_item structure to make the buffer an
integral part of the structure instead of pointer to a
  separately allocated buffer.
- Improved the code that was ensuring that no messages from the
  receiver could be merged into the middle of a partially written
  buffer from the generator.  The new code ensures that we never
  avoid reading the messages from the receiver (like we used to).
  This ensures that the generator will not hang when the receiver
  got a read error on the socket, sent us a message about it, but
  the socket in the generator never becomes writable for it to get
  a similar error (now we are assured of getting the receiver's
  note about their read error, and we know to shut things down).
2006-03-16 00:57:54 +00:00
Wayne Davison
7c329ec72c Mention the log-file.diff. 2006-03-15 18:47:31 +00:00
Wayne Davison
07a8a360a5 Got rid of an errant newline. 2006-03-15 16:54:13 +00:00
Wayne Davison
1618c9e6d1 Improved the regex to match syslog lines and be easier to read. 2006-03-13 16:45:24 +00:00
Wayne Davison
ba0147ac42 Changing the version to 2.6.8cvs. 2006-03-13 16:44:47 +00:00
Wayne Davison
9e88f057b4 Starting the news for 2.6.8. 2006-03-13 16:42:50 +00:00
Wayne Davison
f171bf5b8f Rolling over the NEWS from 2.6.7. 2006-03-13 16:42:33 +00:00
Wayne Davison
1b1628b90a Fixed a bug where the NEWS file got an extra newline inserted when
the release date was added.  Changed "ln -f" to "cp -p" because
samba.org doesn't allow ln to be used at the moment.
2006-03-13 16:42:08 +00:00
Wayne Davison
50cf25672e Added a test of a simple exclude when --relative is enabled. 2006-03-13 01:57:13 +00:00
Wayne Davison
b316862831 Fixed a problem when copying an absolute source path with
the --relative option enabled.
2006-03-13 01:56:19 +00:00
Wayne Davison
38a4b9c297 Block-quote the itemized list in the --stats section so that
it is indented in the manpage.
2006-03-13 00:45:07 +00:00
Wayne Davison
a058cbc410 Preparing for release of 2.6.7 2006-03-11 18:43:42 +00:00
Wayne Davison
1ef7913497 Mention solo-dir fix for a dir without S_IWUSR. 2006-03-11 17:59:37 +00:00
Wayne Davison
88a16c8b4f Don't force S_IWUSR on a solo directory transfer. 2006-03-10 15:57:03 +00:00
Wayne Davison
8030b28ff8 Make extra sure that authbuf can't overflow. 2006-03-07 08:46:29 +00:00
Wayne Davison
1c598b1db8 Mention fix for Proxy-Authorization header. 2006-03-06 18:28:06 +00:00
Wayne Davison
6854bf69a8 Call base4_encode() with "1" for its new "pad" arg so that the
Proxy-Authorization header is properly padded with trailing '='
chars.
2006-03-06 18:22:26 +00:00
Wayne Davison
293def601d The base4_encode() function now takes a "pad" arg which indicates
if the caller wants to pad the value with trailing '=' chars.
2006-03-06 18:22:20 +00:00
Wayne Davison
651dc65efc Tweaked the mode of the files in the tar file. 2006-03-04 08:21:58 +00:00
Wayne Davison
c2b2bd6a93 Since the samba.org rsync is so old that it doesn't handle
out-of-order hard-linked files, changed the script to do the
hard-linking manually.
2006-03-02 23:42:56 +00:00
126 changed files with 19796 additions and 6939 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

19
.ignore
View File

@@ -1,19 +0,0 @@
.#*
*.log
Makefile
config.h
*.o
CVS
.ignore
.cvsignore
*~
rsync
config.status
config.cache
TAGS
config.log
test
*.gz
rsync-*
*.dvi
*.aux

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.
59 Temple Place, Suite 330, Boston, MA 02111-1307 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

@@ -2,6 +2,7 @@
# Makefile
prefix=@prefix@
datarootdir=@datarootdir@
exec_prefix=@exec_prefix@
bindir=@bindir@
mandir=@mandir@
@@ -25,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
@@ -73,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)
@@ -91,16 +104,17 @@ t_unsafe$(EXEEXT): $(T_UNSAFE_OBJ)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(T_UNSAFE_OBJ) $(LIBS)
gen:
$(MAKE) -C $(srcdir) -f prepare-source.mak gen
cd $(srcdir) && $(MAKE) -f prepare-source.mak gen
man:
$(MAKE) -C $(srcdir) -f prepare-source.mak man
cd $(srcdir) && $(MAKE) -f prepare-source.mak man
proto:
$(MAKE) -C $(srcdir) -f prepare-source.mak proto.h
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*
@@ -130,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.
@@ -141,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)
POSIXLY_CORRECT=1 TOOLDIR=`pwd` rsync_bin=`pwd`/rsync$(EXEEXT) srcdir="$(srcdir)" $(srcdir)/runtests.sh
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

420
NEWS
View File

@@ -1,310 +1,232 @@
NEWS for rsync 2.6.7 (UNRELEASED)
Protocol: 29 (unchanged)
Changes since 2.6.6:
NEWS for rsync 3.0.0 (UNRELEASED)
Protocol: 30 (changed)
Changes since 2.6.9:
OUTPUT CHANGES:
NOTABLE CHANGES IN BEHAVIOR:
- The letter 'D' in the itemized output was being used for both devices
(character or block) as well as other special files (such as fifos and
named sockets). This has changed to separate non-device special files
under the 'S' designation (e.g. "cS+++++++ path/fifo"). See also the
"--specials" option, below.
- 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.)
- The way rsync escapes unreadable characters has changed. First, rsync
now has support for recognizing valid multibyte character sequences in
your current locale, allowing it to escape fewer characters than before
for a locale such as UTF-8. Second, it now uses an escape idiom of
"\#123", which is the literal string "\#" followed by exactly 3 octal
digits. Rsync no longer doubles a backslash character in a filename
(e.g. it used to output "foo\\bar" when copying "foo\bar") -- now it only
escapes a backslash that is followed by a hash-sign and 3 digits (0-9)
(e.g. it will output "foo\#134#789" when copying "foo\#789"). See also
the --8-bit-output (-8) option, mentioned below.
Script writers: the local rsync is the one that outputs escaped names,
so if you need to support unescaping of filenames for older rsyncs, I'd
suggest that you parse the output of "rsync --version" and only use the
old unescaping rules for 2.6.5 and 2.6.6.
- 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:
- Fixed a really old bug that caused --checksum (-c) to checksum all the
files encountered during the delete scan (ouch).
- 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 a potential hang in a remote generator: when the receiver gets a
read-error on the socket, it now signals the generator about this so that
the generator does not try to send any of the terminating error messages
to the client (avoiding a potential hang in some setups).
- 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.
- Made hard-links work with symlinks and devices again.
- 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.
- If the sender gets an early EOF reading a source file, we propagate this
error to the receiver so that it can discard the file and try requesting
it again (which is the existing behavior for other kinds of read errors).
- A negated filter rule (with a '!' modifier) no longer loses the negation
when sending the filter rules to the remote rsync.
- If a device-file/special-file changes permissions, rsync now updates the
permissions without recreating the file.
- Fixed a problem with the --out-format (aka --log-format) option %f: it
would output superfluous directory information for a non-daemon rsync.
- If the user specifies a remote-host for both the source and destination,
we now output a syntax error rather than trying to open the destination
hostspec as a filename.
- 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.
- When --inplace creates a new destination file, rsync now creates it with
permissions 0600 instead of 0000 -- this makes restarting possible when
the transfer gets interrupted in the middle of sending a new file.
- 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.
- Reject the combination of --inplace and --sparse since the sparse-output
algorithm doesn't work when overwriting existing data.
- Make sure that directory permissions of a newly-created destination
directory are handled right when --perms is left off.
- Fixed the directory name in the error that is output when pop_dir()
fails.
- The itemized output of a newly-created destination directory is now
output as a creation event, not a change event.
- Really fixed the parsing of a "!" entry in .cvsignore files this time.
- Improved --hard-link so that more corner cases are handled correctly
when combined with options such as --link-dest and/or --ignore-existing.
- If the generator gets a stat() error on a file, output it (this used to
require at least -vv for the error to be seen).
- The --append option no longer updates a file that has the same size.
- If waitpid() fails or the child rsync didn't exit cleanly, we now handle
the exit status properly and generate a better error.
- Fixed a bug when combining --backup and --backup-dir with --inplace:
any missing backup directories are now created.
- Fixed some glitches in the double-verbose output when using --copy-dest,
--link-dest, or --compare-dest. Also improved how the verbose output
handles hard-links (within the transfer) that had an up-to-date alternate
"dest" file, and copied files (via --copy-dest).
- Fixed a bug when using --backup and --inplace with --whole-file or
--read-batch: backup files are actually created now.
- Fixed the matching of the dont-compress items (e.g. *.gz) against files
that have a path component containing a slash.
- 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 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.
- The daemon pidfile is checked and created sooner in the startup sequence.
- If --relative is active, the sending side cleans up trailing "/" or "/."
suffixes to avoid triggering a bug in older rsync versions. Also, we now
reject a ".." dir if it would be sent as a relative dir.
- If a non-directory is in the way of a directory and rsync is run with
--dry-run and --delete, rsync no longer complains about not being able
to opendir() the not-yet present directory.
- When --list-only is used and a non-existent local destination dir was
also specified as a destination, rsync no longer generates a warning
about being unable to create the missing directory.
- Fixed some problems with --relative --no-implied-dirs when the
destination directory did not yet exist: we can now create a symlink or
device when it is the first thing in the missing dir, and --fuzzy no
longer complains about being unable to open the missing dir.
- Fixed a bug where the --copy-links option would not affect implied
directories without --copy-unsafe-links (see --relative).
- Got rid of the need for --force to be used in some circumstances with
--delete-after (making it consistent with --delete-before/-during).
- Rsync now ignores the SIGXFSZ signal, just in case your OS sends this
when a file is too large (rsync handles the write error).
- Fixed a bug in the debug output (-vvvvv) that could mention the wrong
checksum for the current file offset.
- Rsync no longer allows a single directory to be copied over a non-
directory destination arg.
- 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 --append option that makes rsync append data onto files that
are longer on the source than the destination (this includes new files).
- 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.
- Added the --min-size=SIZE option to exclude small files from the
transfer.
- Lowered memory use in the non-incremental-recursion algorithm for typical
option values (usually saving from 21-29 bytes per file).
- Added the --compress-level option to allow you to set how aggressive
rsync's compression should be (this option implies --compress).
- 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.
- Enhanced the parsing of the SIZE value for --min-size and --max-size to
allow easy entry of multiples of 1000 (instead of just multiples of 1024)
and off-by-one values too (e.g. --max-size=8mb-1).
- 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 --8-bit-output (-8) option, which tells rsync to avoid escaping
high-bit characters that it thinks are unreadable in the current locale.
- 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 (*?[).
- The new option --human-readable (-h) changes the output of --progress,
--stats, and the end-of-run summary to be easier to read. If repeated,
the units become powers of 1024 instead of powers of 1000. (The old
meaning of -h, as a shorthand for --help, still works as long as you
just use it on its own, as in "rsync -h".)
- 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.
- If lutimes() and/or lchmod() are around, use them to allow the
preservation of attributes on symlinks.
- 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.)
- The --link-dest option now affects symlinks and devices (when possible).
- 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 two config items to the rsyncd.conf parsing: "pre-xfer exec" and
"post-xfer exec". These allow a command to be specified on a per-module
basis that will be run before and/or after a daemon-mode transfer. (See
the man page for a list of the environment variables that are set with
information about the transfer.)
- 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.
- When using the --relative option, you can now insert a dot dir in
the source path to indicate where the replication of the source dirs
should start. For example, if you specify a source path of
rsync://host/module/foo/bar/./baz/dir with -R, rsync will now only
replicate the "baz/dir" part of the source path (note: a trailing
dot dir is unaffected unless it also has a trailing slash).
- 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 some new --no-FOO options that make it easier to override unwanted
implied or default options. For example, "-a --no-o" (aka "--archive
--no-owner") can be used to turn off the preservation of file ownership
that is implied by -a.
- 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.
- Added the --chmod=MODE option that allows the destination permissions to
be changed from the source permissions. E.g. --chmod=g+w,o-rwx
- 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.)
- Added the "incoming chmod" and "outgoing chmod" daemon options that allow
a module to specify what permissions changes should be applied to all
files copied to and from the daemon.
- 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).
- Allow the --temp-dir option to be specified when starting a daemon, which
sets the default temporary directory for incoming files.
- 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).
- If --delete is combined with --dirs without --recursive, rsync will now
delete in any directory whose content is being synchronized.
- 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 --backup is combined with --delete without --backup-dir (and without
--delete-excluded), we add a "protect" filter-rule to ensure that files
with the backup suffix are not deleted.
- 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).
- The file-count stats that are output by --progress were improved to
better indicate what the numbers mean. For instance, the output:
"(xfer#5, to-check=8383/9999)" indicates that this was the fifth file
to be transferred, and we still need to check 8383 more files out of
a total of 9999.
- Protocol 30 now uses MD5 checksums instead of MD4.
- The include/exclude code now allows a dir/*** directive (with 3 trailing
stars) to match both the dir itself as well as all the content below the
dir (dir/** would not match the dir).
- Changed the --append option to not checksum the existing data in the
destination file, which speeds up file appending.
- Added the --prune-empty-dirs (-m) option that makes the receiving rsync
discard empty chains of directories from the file-list. This makes it
easier to selectively copy files from a source hierarchy and end up with
just the directories needed to hold the resulting files.
- 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.
- If the --itemize-changes (-i) option is repeated, rsync now includes
unchanged files in the itemized output (similar to -vv, but without all
the other verbose messages that can get in the way). Of course, the
client must be version 2.6.7 for this to work, but the remote rsync only
needs to be 2.6.7 if you're pushing files.
- Documented and extended the support for the RSYNC_CONNECT_PROG variable
that can be used to enhance the client side of a daemon connection.
- Added the --specials option to tell rsync to copy non-device special
files (which rsync now attempts even as a normal user). The --devices
option now requests the copying of just devices (character and block).
The -D option still requests both (e.g. --devices and --specials), -a
still implies -D, and non-root users still get a silent downgrade that
omits device copying.
- Improved the dashes and double-quotes in the nroff manpage output.
- Added the --super option to make the receiver always attempt super-user
activities. This is useful for systems that allow things such as devices
to be created or ownership to be set without being UID 0, and is also
useful for someone who wants to ensure that errors will be output if the
receiving rsync isn't being run as root.
- Added the --sockopts option for those few who want to customize the TCP
options used to contact a daemon rsync.
- Added a way for the --temp-dir option to be combined with a partial-dir
setting that lets rsync avoid non-atomic updates (for those times when
--temp-dir is not being used because space is tight).
- A new support script, files-to-excludes, will transform a list of files
into a set of include/exclude directives that will copy those files.
- A new option, --executability (-E) can be used to preserve just the
execute bit on files, for those times when using the --perms option is
not desired.
- The daemon now logs each connection and also each module-list request
that it receives.
- New log-format options: %M (modtime), %U (uid), %G (gid), and %B
(permission bits, e.g. "rwxr-xrwt").
- The --dry-run option no longer forces the enabling of --verbose.
- The --remove-sent-files option now does a better job of incrementally
removing the sent files on the sending side (older versions tended to
clump up all the removals at the end).
- A daemon now supersedes its minimal SIGCHLD handler with the standard
PID-remembering version after forking. This ensures that the generator
can get the child-exit status from the receiver.
- Use of the --bwlimit option no longer interferes with the remote rsync
sending error messages about invalid/refused options.
- Rsync no longer returns a usage error when used with one local source arg
and no destination: this now implies the --list-only option, just like
the comparable situation with a remote source arg.
- Added the --copy-dirlinks option, a more limited version of --copy-links.
- Various documentation improvements, including: a better synopsis, some
improved examples, a better discussion of the presence and absence of
--perms (including how it interacts with the new --executability and
--chmod options), an extended discussion of --temp-dir, an improved
discussion of --partial-dir, a better description of rsync's pattern
matching characters, an improved --no-implied-dirs section, and the
documenting of what the --stats option outputs.
- Various new and updated diffs in the patches dir, including: acls.diff,
xattrs.diff, atimes.diff, detect-renamed.diff, and slp.diff.
- We now support a lot more --no-OPTION override options.
INTERNAL:
- We now use sigaction() and sigprocmask() if possible, and fall back on
signal() if not. Using sigprocmask() ensures that rsync enables all the
signals that it needs, just in case it was started in a masked state.
- 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.
- Some buffer sizes were expanded a bit, particularly on systems where
MAXPATHLEN is overly small (e.g. cygwin).
- Rsync now supports the transfer of 64-bit timestamps (time_t values).
- If io_printf() tries to format more data than fits in the buffer, exit
with an error instead of transmitting a truncated buffer.
- Fixed a build problem with older (2.x) versions of gcc.
- If a va_copy macro is defined, lib/snprintf.c will use it when defining
the VA_COPY macro.
- Added some isType() functions that make dealing with signed characters
easier without forcing variables via casts.
- Reduced the amount of stack memory needed for each level of directory
recursion by nearly MAXPATHLEN bytes.
- Changed strcat/strcpy/sprintf function calls to use safer versions.
- The wildmatch function was extended to allow an array of strings to be
supplied as the string to match. This allows the exclude code to do less
string copying.
- Upgraded the included popt version to 1.10.2 and improved its use of
string-handling functions.
- Got rid of the safe_fname() function (and all the myriad calls) and
replaced it with a new function in the log.c code that filters all the
output going to the terminal.
- Added missing prototypes for compatibility functions from the lib dir.
- Unified the f_name() and the f_name_to() functions.
- Configure determines if iconv() has a const arg, allowing us to avoid a
compiler warning.
- Improved the hash-table code the sender uses to handle checksums to make
it use slightly less memory and run just a little faster.
- 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 diffs in the patches dir now require "patch -p1 <DIFF" instead of
the previous -p0. Also, the version included in the release tar now
affect generated files (e.g. configure, rsync.1, proto.h, etc.), so
it is no longer necessary to run autoconf and/or yodl unless you're
applying a patch that was checked out from CVS.
- Rsync is now licensed under the GPLv3 or later.
- Several diffs in the patches dir now use the proper --enable-FOO
configure option instead of --with-FOO to turn on the inclusion of
the newly patched feature.
- 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).
- There is a new script, "prepare-source" than can be used to update the
various generated files (proto.h, configure, etc.) even before configure
has created the Makefile (this is mainly useful when patching the source
with a patch that doesn't affect generated files).
- The testsuite now sets HOME so that it won't be affected by a file such
as ~/.popt.
- 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).

564
OLDNEWS
View File

@@ -1,3 +1,555 @@
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:
BUG FIXES:
- Fixed a bug in the exclude code where an anchored exclude without any
wildcards fails to match an absolute source arg, but only when --relative
is in effect.
- Improved the I/O code for the generator to fix a potential hang when the
receiver gets an EOF on the socket but the generator's select() call
never indicates that the socket is writable for it to be notified about
the EOF. (This can happen when using stunnel).
- Fixed a problem with the file-reading code where a failed read (such as
that caused by a bad sector) would not advance the file's read-position
beyond the failed read's data.
- Fixed a logging bug where the "log file" directive was not being honored
in a single-use daemon (one spawned by a remote-shell connection or by
init).
- If rsync cannot honor the --delete option, we output an error and exit
instead of silently ignoring the option.
- Fixed a bug in the --link-dest code that prevented special files (such as
fifos) from being linked.
- The ability to hard-link symlinks and special files is now determined at
configure time instead of at runtime. This fixes a bug with --link-dest
creating a hard-link to a symlink's referent on a BSD system.
ENHANCEMENTS:
- In daemon mode, if rsync fails to bind to the requested port, the
error(s) returned by socket() and/or bind() are now logged.
- When we output a fatal error, we now output the version of rsync in the
message.
- Improved the documentation for the --owner and --group options.
- The rsyncstats script in "support" has an improved line-parsing regex
that is easier to read and also makes it to parse syslog-generated lines.
- A new script in "support": file-attr-restore, can be used to restore the
attributes of a file-set (the permissions, ownership, and group info)
taken from the cached output of a "find ARG... -ls" command.
DEVELOPER RELATED:
- Removed the unused function write_int_named(), the unused variable
io_read_phase, and the rarely used variable io_write_phase. This also
elides the confusing 'phase "unknown"' part of one error message.
- Removed two unused configure checks and two related (also unused)
compatibility functions.
- The xattrs.diff patch received a security fix that prevents a potential
buffer overflow in the receive_xattr() code.
- The acls.diff patch has been improved quite a bit, with more to come.
- A new patch was added: log-file.diff. This contains an early version of
a future option, --log-file=FILE, that will allow any rsync to log its
actions to a file (something that only a daemon supports at present).
NEWS for rsync 2.6.7 (11 Mar 2006)
Protocol: 29 (unchanged)
Changes since 2.6.6:
OUTPUT CHANGES:
- The letter 'D' in the itemized output was being used for both devices
(character or block) as well as other special files (such as fifos and
named sockets). This has changed to separate non-device special files
under the 'S' designation (e.g. "cS+++++++ path/fifo"). See also the
"--specials" option, below.
- The way rsync escapes unreadable characters has changed. First, rsync
now has support for recognizing valid multibyte character sequences in
your current locale, allowing it to escape fewer characters than before
for a locale such as UTF-8. Second, it now uses an escape idiom of
"\#123", which is the literal string "\#" followed by exactly 3 octal
digits. Rsync no longer doubles a backslash character in a filename
(e.g. it used to output "foo\\bar" when copying "foo\bar") -- now it only
escapes a backslash that is followed by a hash-sign and 3 digits (0-9)
(e.g. it will output "foo\#134#789" when copying "foo\#789"). See also
the --8-bit-output (-8) option, mentioned below.
Script writers: the local rsync is the one that outputs escaped names,
so if you need to support unescaping of filenames for older rsyncs, I'd
suggest that you parse the output of "rsync --version" and only use the
old unescaping rules for 2.6.5 and 2.6.6.
BUG FIXES:
- Fixed a really old bug that caused --checksum (-c) to checksum all the
files encountered during the delete scan (ouch).
- Fixed a potential hang in a remote generator: when the receiver gets a
read-error on the socket, it now signals the generator about this so that
the generator does not try to send any of the terminating error messages
to the client (avoiding a potential hang in some setups).
- Made hard-links work with symlinks and devices again.
- If the sender gets an early EOF reading a source file, we propagate this
error to the receiver so that it can discard the file and try requesting
it again (which is the existing behavior for other kinds of read errors).
- If a device-file/special-file changes permissions, rsync now updates the
permissions without recreating the file.
- If the user specifies a remote-host for both the source and destination,
we now output a syntax error rather than trying to open the destination
hostspec as a filename.
- When --inplace creates a new destination file, rsync now creates it with
permissions 0600 instead of 0000 -- this makes restarting possible when
the transfer gets interrupted in the middle of sending a new file.
- Reject the combination of --inplace and --sparse since the sparse-output
algorithm doesn't work when overwriting existing data.
- Fixed the directory name in the error that is output when pop_dir()
fails.
- Really fixed the parsing of a "!" entry in .cvsignore files this time.
- If the generator gets a stat() error on a file, output it (this used to
require at least -vv for the error to be seen).
- If waitpid() fails or the child rsync didn't exit cleanly, we now handle
the exit status properly and generate a better error.
- Fixed some glitches in the double-verbose output when using --copy-dest,
--link-dest, or --compare-dest. Also improved how the verbose output
handles hard-links (within the transfer) that had an up-to-date alternate
"dest" file, and copied files (via --copy-dest).
- Fixed the matching of the dont-compress items (e.g. *.gz) against files
that have a path component containing a slash.
- 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
reject a ".." dir if it would be sent as a relative dir.
- If a non-directory is in the way of a directory and rsync is run with
--dry-run and --delete, rsync no longer complains about not being able
to opendir() the not-yet present directory.
- When --list-only is used and a non-existent local destination dir was
also specified as a destination, rsync no longer generates a warning
about being unable to create the missing directory.
- Fixed some problems with --relative --no-implied-dirs when the
destination directory did not yet exist: we can now create a symlink or
device when it is the first thing in the missing dir, and --fuzzy no
longer complains about being unable to open the missing dir.
- Fixed a bug where the --copy-links option would not affect implied
directories without --copy-unsafe-links (see --relative).
- Got rid of the need for --force to be used in some circumstances with
--delete-after (making it consistent with --delete-before/-during).
- Rsync now ignores the SIGXFSZ signal, just in case your OS sends this
when a file is too large (rsync handles the write error).
- Fixed a bug in the Proxy-Authorization header's base64-encoded value: it
was not properly padded with trailing '=' chars. This only affects a
user that need to use a password-authenticated proxy for an outgoing
daemon-rsync connection.
- If we're transferring an empty directory to a new name, rsync no longer
forces S_IWUSR if it wasn't already set, nor does it accidentally leave
it set.
- Fixed a bug in the debug output (-vvvvv) that could mention the wrong
checksum for the current file offset.
- Rsync no longer allows a single directory to be copied over a non-
directory destination arg.
ENHANCEMENTS:
- Added the --append option that makes rsync append data onto files that
are longer on the source than the destination (this includes new files).
- Added the --min-size=SIZE option to exclude small files from the
transfer.
- Added the --compress-level option to allow you to set how aggressive
rsync's compression should be (this option implies --compress).
- Enhanced the parsing of the SIZE value for --min-size and --max-size to
allow easy entry of multiples of 1000 (instead of just multiples of 1024)
and off-by-one values too (e.g. --max-size=8mb-1).
- Added the --8-bit-output (-8) option, which tells rsync to avoid escaping
high-bit characters that it thinks are unreadable in the current locale.
- The new option --human-readable (-h) changes the output of --progress,
--stats, and the end-of-run summary to be easier to read. If repeated,
the units become powers of 1024 instead of powers of 1000. (The old
meaning of -h, as a shorthand for --help, still works as long as you
just use it on its own, as in "rsync -h".)
- If lutimes() and/or lchmod() are around, use them to allow the
preservation of attributes on symlinks.
- The --link-dest option now affects symlinks and devices (when possible).
- Added two config items to the rsyncd.conf parsing: "pre-xfer exec" and
"post-xfer exec". These allow a command to be specified on a per-module
basis that will be run before and/or after a daemon-mode transfer. (See
the man page for a list of the environment variables that are set with
information about the transfer.)
- When using the --relative option, you can now insert a dot dir in
the source path to indicate where the replication of the source dirs
should start. For example, if you specify a source path of
rsync://host/module/foo/bar/./baz/dir with -R, rsync will now only
replicate the "baz/dir" part of the source path (note: a trailing
dot dir is unaffected unless it also has a trailing slash).
- Added some new --no-FOO options that make it easier to override unwanted
implied or default options. For example, "-a --no-o" (aka "--archive
--no-owner") can be used to turn off the preservation of file ownership
that is implied by -a.
- Added the --chmod=MODE option that allows the destination permissions to
be changed from the source permissions. E.g. --chmod=g+w,o-rwx
- Added the "incoming chmod" and "outgoing chmod" daemon options that allow
a module to specify what permissions changes should be applied to all
files copied to and from the daemon.
- Allow the --temp-dir option to be specified when starting a daemon, which
sets the default temporary directory for incoming files.
- If --delete is combined with --dirs without --recursive, rsync will now
delete in any directory whose content is being synchronized.
- If --backup is combined with --delete without --backup-dir (and without
--delete-excluded), we add a "protect" filter-rule to ensure that files
with the backup suffix are not deleted.
- The file-count stats that are output by --progress were improved to
better indicate what the numbers mean. For instance, the output:
"(xfer#5, to-check=8383/9999)" indicates that this was the fifth file
to be transferred, and we still need to check 8383 more files out of
a total of 9999.
- The include/exclude code now allows a dir/*** directive (with 3 trailing
stars) to match both the dir itself as well as all the content below the
dir (dir/** would not match the dir).
- Added the --prune-empty-dirs (-m) option that makes the receiving rsync
discard empty chains of directories from the file-list. This makes it
easier to selectively copy files from a source hierarchy and end up with
just the directories needed to hold the resulting files.
- If the --itemize-changes (-i) option is repeated, rsync now includes
unchanged files in the itemized output (similar to -vv, but without all
the other verbose messages that can get in the way). Of course, the
client must be version 2.6.7 for this to work, but the remote rsync only
needs to be 2.6.7 if you're pushing files.
- Added the --specials option to tell rsync to copy non-device special
files (which rsync now attempts even as a normal user). The --devices
option now requests the copying of just devices (character and block).
The -D option still requests both (e.g. --devices and --specials), -a
still implies -D, and non-root users still get a silent downgrade that
omits device copying.
- Added the --super option to make the receiver always attempt super-user
activities. This is useful for systems that allow things such as devices
to be created or ownership to be set without being UID 0, and is also
useful for someone who wants to ensure that errors will be output if the
receiving rsync isn't being run as root.
- Added the --sockopts option for those few who want to customize the TCP
options used to contact a daemon rsync.
- Added a way for the --temp-dir option to be combined with a partial-dir
setting that lets rsync avoid non-atomic updates (for those times when
--temp-dir is not being used because space is tight).
- A new support script, files-to-excludes, will transform a list of files
into a set of include/exclude directives that will copy those files.
- A new option, --executability (-E) can be used to preserve just the
execute bit on files, for those times when using the --perms option is
not desired.
- The daemon now logs each connection and also each module-list request
that it receives.
- New log-format options: %M (modtime), %U (uid), %G (gid), and %B
(permission bits, e.g. "rwxr-xrwt").
- The --dry-run option no longer forces the enabling of --verbose.
- The --remove-sent-files option now does a better job of incrementally
removing the sent files on the sending side (older versions tended to
clump up all the removals at the end).
- A daemon now supersedes its minimal SIGCHLD handler with the standard
PID-remembering version after forking. This ensures that the generator
can get the child-exit status from the receiver.
- Use of the --bwlimit option no longer interferes with the remote rsync
sending error messages about invalid/refused options.
- Rsync no longer returns a usage error when used with one local source arg
and no destination: this now implies the --list-only option, just like
the comparable situation with a remote source arg.
- Added the --copy-dirlinks option, a more limited version of --copy-links.
- Various documentation improvements, including: a better synopsis, some
improved examples, a better discussion of the presence and absence of
--perms (including how it interacts with the new --executability and
--chmod options), an extended discussion of --temp-dir, an improved
discussion of --partial-dir, a better description of rsync's pattern
matching characters, an improved --no-implied-dirs section, and the
documenting of what the --stats option outputs.
- Various new and updated diffs in the patches dir, including: acls.diff,
xattrs.diff, atimes.diff, detect-renamed.diff, and slp.diff.
INTERNAL:
- We now use sigaction() and sigprocmask() if possible, and fall back on
signal() if not. Using sigprocmask() ensures that rsync enables all the
signals that it needs, just in case it was started in a masked state.
- Some buffer sizes were expanded a bit, particularly on systems where
MAXPATHLEN is overly small (e.g. cygwin).
- If io_printf() tries to format more data than fits in the buffer, exit
with an error instead of transmitting a truncated buffer.
- If a va_copy macro is defined, lib/snprintf.c will use it when defining
the VA_COPY macro.
- Reduced the amount of stack memory needed for each level of directory
recursion by nearly MAXPATHLEN bytes.
- The wildmatch function was extended to allow an array of strings to be
supplied as the string to match. This allows the exclude code to do less
string copying.
- Got rid of the safe_fname() function (and all the myriad calls) and
replaced it with a new function in the log.c code that filters all the
output going to the terminal.
- Unified the f_name() and the f_name_to() functions.
- Improved the hash-table code the sender uses to handle checksums to make
it use slightly less memory and run just a little faster.
DEVELOPER RELATED:
- The diffs in the patches dir now require "patch -p1 <DIFF" instead of
the previous -p0. Also, the version included in the release tar now
affect generated files (e.g. configure, rsync.1, proto.h, etc.), so
it is no longer necessary to run autoconf and/or yodl unless you're
applying a patch that was checked out from CVS.
- Several diffs in the patches dir now use the proper --enable-FOO
configure option instead of --with-FOO to turn on the inclusion of
the newly patched feature.
- There is a new script, "prepare-source" than can be used to update the
various generated files (proto.h, configure, etc.) even before configure
has created the Makefile (this is mainly useful when patching the source
with a patch that doesn't affect generated files).
- The testsuite now sets HOME so that it won't be affected by a file such
as ~/.popt.
NEWS for rsync 2.6.6 (28 Jul 2005)
Protocol: 29 (unchanged)
Changes since 2.6.5:
@@ -770,6 +1322,8 @@ Changes since 2.6.2:
user chose to combine the output of rsync's stdout and stderr (e.g.
using the "2>&1").
- Fixed an option-parsing bug when --files-from got passed to a daemon.
ENHANCEMENTS:
- Added the --partial-dir=DIR option that lets you specify where to
@@ -1036,6 +1590,9 @@ Changes since 2.6.0:
- Fixed the ability to request an empty backup --suffix when sending
files to an rsync daemon.
- Fixed an option-parsing bug when --files-from was sent to a server
sender.
INTERNAL:
- Most of the I/O is now buffered, which results in a pretty large
@@ -1295,7 +1852,7 @@ Changes since 2.5.5:
* The --suffix option can now be used with --backup-dir. (Michael
Zimmerman)
* Combining "::" syntax with the -rsh/-e option now uses the
* Combining "::" syntax with the --rsh/-e option now uses the
specified remote-shell as a transport to talk to a (newly-spawned)
server-daemon. This allows someone to use daemon features, such
as modules, over a secure protocol, such as ssh. (JD Paul)
@@ -1687,7 +2244,10 @@ Changes since 2.4.6:
Partial Protocol History
RELEASE DATE VER. DATE OF COMMIT* PROTOCOL
?? ??? 2006 2.6.7 29
?? ??? 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
28 Jul 2005 2.6.6 29
01 Jun 2005 2.6.5 29
30 Mar 2005 2.6.4 17 Jan 2005 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

@@ -1,29 +1,25 @@
/*
Copyright (C) Andrew Tridgell 1998
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
hosts allow/deny code for rsync
*/
* Routines to authenticate access to a daemon (hosts allow/deny).
*
* Copyright (C) 1998 Andrew Tridgell
* 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 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"
static int match_hostname(char *host, char *tok)
{
if (!host || !*host)

1079
acls.c Normal file
View File

File diff suppressed because it is too large Load Diff

View File

@@ -1,23 +1,23 @@
/* -*- c-file-style: "linux"; -*-
/*
* Support rsync daemon authentication.
*
* Copyright (C) 1998-2000 Andrew Tridgell
* 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 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.
*/
Copyright (C) 1998-2000 by 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* support rsync authentication */
#include "rsync.h"
extern char *password_file;
@@ -26,15 +26,13 @@ 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)
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;
memset(out, 0, bytes+1);
for (i = 0; i < bytes; i++) {
byte_offset = (i*6)/8;
bit_offset = (i*6)%8;
@@ -48,18 +46,24 @@ void base64_encode(char *buf, int len, char *out)
}
out[i] = b64[idx];
}
while (pad && (i % 4))
out[i++] = '=';
out[i] = '\0';
}
/* 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);
@@ -67,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);
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;
@@ -132,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;
@@ -199,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);
base64_encode(buf, len, out, 0);
}
/* Possibly negotiate authentication with the client. Use "leader" to
@@ -217,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! */
@@ -235,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",
@@ -282,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";

189
backup.c
View File

@@ -1,40 +1,41 @@
/*
Copyright (C) Andrew Tridgell 1999
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* backup handling code */
* Backup handling code.
*
* Copyright (C) 1999 Andrew Tridgell
* 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 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"
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,
@@ -51,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;
@@ -91,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;
}
}
}
@@ -125,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
@@ -167,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) {
@@ -221,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;
@@ -245,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;
}
@@ -253,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",
@@ -271,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);

26
batch.c
View File

@@ -1,9 +1,23 @@
/* -*- c-file-style: "linux" -*-
Weiss 1/1999
Batch utilities for rsync.
*/
/*
* Support for the batch-file options.
*
* Copyright (C) 1999 Weiss
* Copyright (C) 2004 Chris Shoemaker
* 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 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 "zlib/zlib.h"

View File

@@ -1,26 +1,27 @@
/*
simple byteorder handling
Copyright (C) Andrew Tridgell 1992-1995
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* 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 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.
*/
#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
@@ -30,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)))
@@ -50,5 +50,3 @@
#define IVAL(buf,pos) (*(uint32 *)((char *)(buf) + (pos)))
#define SIVAL(buf,pos,val) IVAL(buf,pos)=((uint32)(val))
#endif

79
case_N.h Normal file
View File

@@ -0,0 +1,79 @@
/*
* End-of-run cleanup helper code used by cleanup.c.
*
* 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 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.
*/
/* This is included by cleanup.c multiple times, once for every segement in
* the _exit_cleanup() code. This produces the next "case N:" statement in
* sequence and increments the cleanup_step variable by 1. This ensures that
* our case statements never get out of whack due to added/removed steps. */
#if !defined EXIT_CLEANUP_CASE_0
#define EXIT_CLEANUP_CASE_0
case 0:
#elif !defined EXIT_CLEANUP_CASE_1
#define EXIT_CLEANUP_CASE_1
case 1:
#elif !defined EXIT_CLEANUP_CASE_2
#define EXIT_CLEANUP_CASE_2
case 2:
#elif !defined EXIT_CLEANUP_CASE_3
#define EXIT_CLEANUP_CASE_3
case 3:
#elif !defined EXIT_CLEANUP_CASE_4
#define EXIT_CLEANUP_CASE_4
case 4:
#elif !defined EXIT_CLEANUP_CASE_5
#define EXIT_CLEANUP_CASE_5
case 5:
#elif !defined EXIT_CLEANUP_CASE_6
#define EXIT_CLEANUP_CASE_6
case 6:
#elif !defined EXIT_CLEANUP_CASE_7
#define EXIT_CLEANUP_CASE_7
case 7:
#elif !defined EXIT_CLEANUP_CASE_8
#define EXIT_CLEANUP_CASE_8
case 8:
#elif !defined EXIT_CLEANUP_CASE_9
#define EXIT_CLEANUP_CASE_9
case 9:
#elif !defined EXIT_CLEANUP_CASE_10
#define EXIT_CLEANUP_CASE_10
case 10:
#elif !defined EXIT_CLEANUP_CASE_11
#define EXIT_CLEANUP_CASE_11
case 11:
#elif !defined EXIT_CLEANUP_CASE_12
#define EXIT_CLEANUP_CASE_12
case 12:
#elif !defined EXIT_CLEANUP_CASE_13
#define EXIT_CLEANUP_CASE_13
case 13:
#elif !defined EXIT_CLEANUP_CASE_14
#define EXIT_CLEANUP_CASE_14
case 14:
#elif !defined EXIT_CLEANUP_CASE_15
#define EXIT_CLEANUP_CASE_15
case 15:
#elif !defined EXIT_CLEANUP_CASE_16
#define EXIT_CLEANUP_CASE_16
case 16:
#else
#error Need to add more case statements!
#endif
cleanup_step++;

View File

@@ -1,31 +1,31 @@
/*
Copyright (C) Andrew Tridgell 1996
Copyright (C) Paul Mackerras 1996
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
* Routines to support checksumming of bytes.
*
* Copyright (C) 1996 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* 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 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"
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)
@@ -51,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)
@@ -106,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);
}
}
/**
@@ -148,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;
}
@@ -172,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;
}

26
chmod.c
View File

@@ -1,3 +1,23 @@
/*
* Implement the core of the --chmod option.
*
* Copyright (C) 2002 Scott Howard
* 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 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"
extern mode_t orig_umask;
@@ -84,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;
@@ -130,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;

211
cleanup.c
View File

@@ -1,30 +1,34 @@
/* -*- c-file-style: "linux" -*-
Copyright (C) 1996-2000 by Andrew Tridgell
Copyright (C) Paul Mackerras 1996
Copyright (C) 2002 by Martin Pool
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* End-of-run cleanup routines.
*
* Copyright (C) 1996-2000 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2002 Martin Pool
* 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 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"
extern int am_server;
extern int am_daemon;
extern int io_error;
extern int keep_partial;
extern int log_got_error;
extern char *partial_dir;
extern char *logfile_name;
#ifdef HAVE_SIGACTION
static struct sigaction sigact;
@@ -87,83 +91,124 @@ pid_t cleanup_child_pid = -1;
*
* @param code one of the RERR_* codes from errcode.h.
**/
void _exit_cleanup(int code, const char *file, int line)
NORETURN void _exit_cleanup(int code, const char *file, int line)
{
int ocode = code;
static int inside_cleanup = 0;
if (inside_cleanup > 10) {
/* prevent the occasional infinite recursion */
return;
}
inside_cleanup++;
static int cleanup_step = 0;
static int exit_code = 0;
static int unmodified_code = 0;
SIGACTION(SIGUSR1, SIG_IGN);
SIGACTION(SIGUSR2, SIG_IGN);
if (verbose > 3) {
rprintf(FINFO,"_exit_cleanup(code=%d, file=%s, line=%d): entered\n",
code, file, line);
}
if (exit_code) /* Preserve first error code when recursing. */
code = exit_code;
if (cleanup_child_pid != -1) {
int status;
if (wait_process(cleanup_child_pid, &status, WNOHANG)
== cleanup_child_pid) {
status = WEXITSTATUS(status);
if (status > code)
code = status;
/* 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) {
#include "case_N.h" /* case 0: cleanup_step++; */
exit_code = unmodified_code = code;
if (verbose > 3) {
rprintf(FINFO,
"_exit_cleanup(code=%d, file=%s, line=%d): entered\n",
code, file, line);
}
}
if (cleanup_got_literal && cleanup_fname && keep_partial
&& handle_partial_dir(cleanup_new_fname, PDIR_CREATE)) {
char *fname = cleanup_fname;
cleanup_fname = NULL;
if (cleanup_fd_r != -1)
close(cleanup_fd_r);
if (cleanup_fd_w != -1) {
flush_write_file(cleanup_fd_w);
close(cleanup_fd_w);
/* FALLTHROUGH */
#include "case_N.h"
if (cleanup_child_pid != -1) {
int status;
int pid = wait_process(cleanup_child_pid, &status, WNOHANG);
if (pid == cleanup_child_pid) {
status = WEXITSTATUS(status);
if (status > code)
code = exit_code = status;
}
}
finish_transfer(cleanup_new_fname, fname, NULL,
cleanup_file, 0, !partial_dir);
}
io_flush(FULL_FLUSH);
if (cleanup_fname)
do_unlink(cleanup_fname);
if (code)
kill_all(SIGUSR1);
if (cleanup_pid && cleanup_pid == getpid()) {
char *pidf = lp_pid_file();
if (pidf && *pidf)
unlink(lp_pid_file());
/* FALLTHROUGH */
#include "case_N.h"
if (cleanup_got_literal && cleanup_fname && cleanup_new_fname
&& keep_partial && handle_partial_dir(cleanup_new_fname, PDIR_CREATE)) {
char *fname = cleanup_fname;
cleanup_fname = NULL;
if (cleanup_fd_r != -1)
close(cleanup_fd_r);
if (cleanup_fd_w != -1) {
flush_write_file(cleanup_fd_w);
close(cleanup_fd_w);
}
finish_transfer(cleanup_new_fname, fname, NULL, NULL,
cleanup_file, 0, !partial_dir);
}
/* FALLTHROUGH */
#include "case_N.h"
io_flush(FULL_FLUSH);
/* FALLTHROUGH */
#include "case_N.h"
if (cleanup_fname)
do_unlink(cleanup_fname);
if (code)
kill_all(SIGUSR1);
if (cleanup_pid && cleanup_pid == getpid()) {
char *pidf = lp_pid_file();
if (pidf && *pidf)
unlink(lp_pid_file());
}
if (code == 0) {
if (io_error & IOERR_DEL_LIMIT)
code = exit_code = RERR_DEL_LIMIT;
if (io_error & IOERR_VANISHED)
code = exit_code = RERR_VANISHED;
if (io_error & IOERR_GENERAL || log_got_error)
code = exit_code = RERR_PARTIAL;
}
if (code || am_daemon || (logfile_name && (am_server || !verbose)))
log_exit(code, file, line);
/* FALLTHROUGH */
#include "case_N.h"
if (verbose > 2) {
rprintf(FINFO,
"_exit_cleanup(code=%d, file=%s, line=%d): "
"about to call exit(%d)\n",
unmodified_code, file, line, code);
}
/* FALLTHROUGH */
#include "case_N.h"
if (am_server && code)
msleep(100);
close_all();
/* FALLTHROUGH */
default:
break;
}
if (code == 0) {
if (io_error & IOERR_DEL_LIMIT)
code = RERR_DEL_LIMIT;
if (io_error & IOERR_VANISHED)
code = RERR_VANISHED;
if (io_error & IOERR_GENERAL || log_got_error)
code = RERR_PARTIAL;
}
if (code)
log_exit(code, file, line);
if (verbose > 2) {
rprintf(FINFO,"_exit_cleanup(code=%d, file=%s, line=%d): about to call exit(%d)\n",
ocode, file, line, code);
}
close_all();
exit(code);
}
void cleanup_disable(void)
{
cleanup_fname = NULL;
cleanup_fname = cleanup_new_fname = NULL;
cleanup_got_literal = 0;
}
@@ -171,8 +216,8 @@ void cleanup_disable(void)
void cleanup_set(char *fnametmp, char *fname, struct file_struct *file,
int fd_r, int fd_w)
{
cleanup_fname = fname ? fnametmp : NULL;
cleanup_new_fname = fname;
cleanup_fname = fnametmp;
cleanup_new_fname = fname; /* can be NULL on a partial-dir failure */
cleanup_file = file;
cleanup_fd_r = fd_r;
cleanup_fd_w = fd_w;

View File

@@ -1,35 +1,30 @@
/* -*- c-file-style: "linux" -*-
rsync -- fast file replication program
Copyright (C) 1992-2001 by Andrew Tridgell <tridge@samba.org>
Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/**
* @file clientname.c
*
/*
* Functions for looking up the remote name or addr of a socket.
*
* Copyright (C) 1992-2001 Andrew Tridgell <tridge@samba.org>
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
* 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 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.
*/
/*
* This file is now converted to use the new-style getaddrinfo()
* interface, which supports IPv6 but is also supported on recent
* IPv4-only machines. On systems that don't have that interface, we
* emulate it using the KAME implementation.
**/
*/
#include "rsync.h"
@@ -54,7 +49,7 @@ char *client_addr(int fd)
initialised = 1;
if (am_server) { /* daemon over --rsh mode */
strcpy(addr_buf, "0.0.0.0");
strlcpy(addr_buf, "0.0.0.0", sizeof addr_buf);
if ((ssh_info = getenv("SSH_CONNECTION")) != NULL
|| (ssh_info = getenv("SSH_CLIENT")) != NULL
|| (ssh_info = getenv("SSH2_CLIENT")) != NULL) {
@@ -103,7 +98,7 @@ char *client_name(int fd)
if (initialised)
return name_buf;
strcpy(name_buf, default_name);
strlcpy(name_buf, default_name, sizeof name_buf);
initialised = 1;
memset(&ss, 0, sizeof ss);
@@ -137,6 +132,8 @@ char *client_name(int fd)
memcpy(&ss, answer->ai_addr, ss_len);
break;
#endif
default:
exit_cleanup(RERR_SOCKETIO);
}
freeaddrinfo(answer);
} else {
@@ -146,7 +143,7 @@ char *client_name(int fd)
if (lookup_name(fd, &ss, ss_len, name_buf, sizeof name_buf,
port_buf, sizeof port_buf) == 0)
check_name(fd, &ss, name_buf);
check_name(fd, &ss, name_buf, sizeof name_buf);
return name_buf;
}
@@ -210,18 +207,18 @@ void client_sockaddr(int fd,
**/
int lookup_name(int fd, const struct sockaddr_storage *ss,
socklen_t ss_len,
char *name_buf, size_t name_buf_len,
char *port_buf, size_t port_buf_len)
char *name_buf, size_t name_buf_size,
char *port_buf, size_t port_buf_size)
{
int name_err;
/* reverse lookup */
name_err = getnameinfo((struct sockaddr *) ss, ss_len,
name_buf, name_buf_len,
port_buf, port_buf_len,
name_buf, name_buf_size,
port_buf, port_buf_size,
NI_NAMEREQD | NI_NUMERICSERV);
if (name_err != 0) {
strcpy(name_buf, default_name);
strlcpy(name_buf, default_name, name_buf_size);
rprintf(FLOG, "name lookup failed for %s: %s\n",
client_addr(fd), gai_strerror(name_err));
return name_err;
@@ -302,7 +299,7 @@ int compare_addrinfo_sockaddr(const struct addrinfo *ai,
**/
int check_name(int fd,
const struct sockaddr_storage *ss,
char *name_buf)
char *name_buf, size_t name_buf_size)
{
struct addrinfo hints, *res, *res0;
int error;
@@ -316,7 +313,7 @@ int check_name(int fd,
if (error) {
rprintf(FLOG, "forward name lookup for %s failed: %s\n",
name_buf, gai_strerror(error));
strcpy(name_buf, default_name);
strlcpy(name_buf, default_name, name_buf_size);
return error;
}
@@ -332,13 +329,13 @@ int check_name(int fd,
* address that was the same as ss. */
rprintf(FLOG, "no known address for \"%s\": "
"spoofed address?\n", name_buf);
strcpy(name_buf, default_name);
strlcpy(name_buf, default_name, name_buf_size);
} else if (res == NULL) {
/* We hit the end of the list without finding an
* address that was the same as ss. */
rprintf(FLOG, "%s is not a known address for \"%s\": "
"spoofed address?\n", client_addr(fd), name_buf);
strcpy(name_buf, default_name);
strlcpy(name_buf, default_name, name_buf_size);
}
freeaddrinfo(res0);

View File

@@ -1,11 +1,13 @@
/* -*- c-file-style: "linux"; -*-
/*
* The socket based protocol for setting up a connection with rsyncd.
*
* Copyright (C) 1998-2001 by Andrew Tridgell <tridge@samba.org>
* Copyright (C) 2001-2002 by Martin Pool <mbp@samba.org>
* Copyright (C) 1998-2001 Andrew Tridgell <tridge@samba.org>
* Copyright (C) 2001-2002 Martin Pool <mbp@samba.org>
* 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,
@@ -13,28 +15,22 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, visit the http://fsf.org website.
*/
/**
* @file
*
* The socket based protocol for setting up a connection with
* rsyncd.
**/
#include "rsync.h"
#include "ifuncs.h"
extern int verbose;
extern int quiet;
extern int output_motd;
extern int list_only;
extern int am_sender;
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;
@@ -44,25 +40,31 @@ extern int protocol_version;
extern int io_timeout;
extern int no_detach;
extern int default_af_hint;
extern int logfile_format_has_i;
extern int logfile_format_has_o_or_i;
extern mode_t orig_umask;
extern char *bind_address;
extern char *sockopts;
extern char *config_file;
extern char *logfile_format;
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 daemon_log_format_has_i = 0;
int daemon_log_format_has_o_or_i = 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
@@ -81,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;
@@ -89,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;
@@ -108,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;
@@ -136,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;
@@ -161,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 = '/';
@@ -181,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;
}
@@ -209,14 +279,24 @@ int start_inband_exchange(char *user, char *path, int f_in, int f_out,
return -1;
}
rprintf(FINFO, "%s\n", line);
/* This might be a MOTD line or a module listing, but there is
* no way to differentiate it. The manpage mentions this. */
if (output_motd)
rprintf(FINFO, "%s\n", line);
}
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;
@@ -328,20 +408,19 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
if (lp_read_only(i))
read_only = 1;
if (lp_transfer_logging(i)) {
if (log_format_has(lp_log_format(i), 'i'))
daemon_log_format_has_i = 1;
if (daemon_log_format_has_i
|| log_format_has(lp_log_format(i), 'o'))
daemon_log_format_has_o_or_i = 1;
}
if (lp_transfer_logging(i) && !logfile_format)
logfile_format = lp_log_format(i);
if (log_format_has(logfile_format, 'i'))
logfile_format_has_i = 1;
if (logfile_format_has_i || log_format_has(logfile_format, 'o'))
logfile_format_has_o_or_i = 1;
am_root = (MY_UID() == 0);
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;
@@ -351,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;
@@ -367,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,
@@ -394,14 +484,14 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
parse_rule(&server_filter_list, p, MATCHFLG_WORD_SPLIT,
XFLG_ABS_IF_SLASH | XFLG_OLD_PREFIXES);
log_init();
log_init(1);
#ifdef HAVE_PUTENV
if (*lp_prexfer_exec(i) || *lp_postxfer_exec(i)) {
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)
@@ -423,17 +513,18 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
return -1;
}
if (pid) {
char *ret1, *ret2;
if (asprintf(&p, "RSYNC_PID=%ld", (long)pid) > 0)
putenv(p);
if (wait_process(pid, &status, 0) < 0)
status = -1;
if (asprintf(&ret1, "RSYNC_RAW_STATUS=%d", status) > 0)
putenv(ret1);
if (asprintf(&p, "RSYNC_RAW_STATUS=%d", status) > 0)
putenv(p);
if (WIFEXITED(status))
status = WEXITSTATUS(status);
else
status = -1;
if (asprintf(&ret2, "RSYNC_EXIT_STATUS=%d", status) > 0)
putenv(ret2);
if (asprintf(&p, "RSYNC_EXIT_STATUS=%d", status) > 0)
putenv(p);
system(lp_postxfer_exec(i));
_exit(status);
}
@@ -443,6 +534,8 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
* send us the user's request via a pipe. */
if (*lp_prexfer_exec(i)) {
int fds[2];
if (asprintf(&p, "RSYNC_PID=%ld", (long)getpid()) > 0)
putenv(p);
if (pipe(fds) < 0 || (pre_exec_pid = fork()) < 0) {
rsyserr(FLOG, errno, "pre-xfer exec preparation failed");
io_printf(f_out, "@ERROR: pre-xfer exec preparation failed\n");
@@ -456,9 +549,8 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
len = read_arg_from_pipe(fds[0], buf, BIGPATHBUFLEN);
if (len <= 0)
_exit(1);
if (asprintf(&p, "RSYNC_REQUEST=%s", buf) < 0)
out_of_memory("rsync_module");
putenv(p);
if (asprintf(&p, "RSYNC_REQUEST=%s", buf) > 0)
putenv(p);
for (j = 0; ; j++) {
len = read_arg_from_pipe(fds[0], buf,
BIGPATHBUFLEN);
@@ -467,9 +559,8 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
break;
_exit(1);
}
if (asprintf(&p, "RSYNC_ARG%d=%s", j, buf) < 0)
out_of_memory("rsync_module");
putenv(p);
if (asprintf(&p, "RSYNC_ARG%d=%s", j, buf) > 0)
putenv(p);
}
close(fds[0]);
close(STDIN_FILENO);
@@ -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("/")) {
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))) {
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,19 +776,21 @@ static void send_listing(int fd)
int start_daemon(int f_in, int f_out)
{
char line[1024];
char *motd;
char *addr = client_addr(f_in);
char *host = client_name(f_in);
char *addr, *host;
int i;
rprintf(FLOG, "connect from %s (%s)\n", host, addr);
io_set_sock_fds(f_in, f_out);
/* We must load the config file before calling any function that
* might cause log-file output to occur. This ensures that the
* "log file" param gets honored for the 2 non-forked use-cases
* (when rsync is run by init and run by a remote shell). */
if (!lp_load(config_file, 0))
exit_cleanup(RERR_SYNTAX);
log_init();
addr = client_addr(f_in);
host = client_name(f_in);
rprintf(FLOG, "connect from %s (%s)\n", host, addr);
if (!am_server) {
set_socket_options(f_in, "SO_KEEPALIVE");
@@ -751,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) {
@@ -810,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;
@@ -828,18 +915,22 @@ 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;
if (bind_address == NULL && *lp_bind_address())
bind_address = lp_bind_address();
log_init();
log_init(0);
rprintf(FLOG, "rsyncd version %s starting, listening on port %d\n",
RSYNC_VERSION, rsync_port);
@@ -847,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;
}

181
compat.c
View File

@@ -1,46 +1,125 @@
/*
Copyright (C) Andrew Tridgell 1996
Copyright (C) Paul Mackerras 1996
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/**
* @file compat.c
*
/*
* Compatibility routines for older rsync protocol versions.
**/
*
* Copyright (C) Andrew Tridgell 1996
* Copyright (C) Paul Mackerras 1996
* 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 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"
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);
@@ -48,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);
}
@@ -78,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,
@@ -110,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);

650
config.guess vendored
View File

File diff suppressed because it is too large Load Diff

206
config.sub vendored
View File

@@ -1,9 +1,10 @@
#! /bin/sh
# Configuration validation subroutine script.
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
# 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
# Inc.
timestamp='2003-08-18'
timestamp='2006-07-02'
# This file is (in principle) common to ALL GNU software.
# The presence of a machine in this file suggests that SOME GNU software
@@ -21,14 +22,15 @@ timestamp='2003-08-18'
#
# 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.
# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
# 02110-1301, USA.
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# Please send patches to <config-patches@gnu.org>. Submit a context
# diff and a properly formatted ChangeLog entry.
#
@@ -70,7 +72,7 @@ Report bugs and patches to <config-patches@gnu.org>."
version="\
GNU config.sub ($timestamp)
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
@@ -83,11 +85,11 @@ Try \`$me --help' for more information."
while test $# -gt 0 ; do
case $1 in
--time-stamp | --time* | -t )
echo "$timestamp" ; exit 0 ;;
echo "$timestamp" ; exit ;;
--version | -v )
echo "$version" ; exit 0 ;;
echo "$version" ; exit ;;
--help | --h* | -h )
echo "$usage"; exit 0 ;;
echo "$usage"; exit ;;
-- ) # Stop option processing
shift; break ;;
- ) # Use stdin as input.
@@ -99,7 +101,7 @@ while test $# -gt 0 ; do
*local*)
# First pass through any local machine types.
echo $1
exit 0;;
exit ;;
* )
break ;;
@@ -118,7 +120,9 @@ esac
# Here we must recognize all the valid KERNEL-OS combinations.
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
case $maybe_os in
nto-qnx* | linux-gnu* | linux-dietlibc | kfreebsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*)
nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
storm-chaos* | os2-emx* | rtmk-nova*)
os=-$maybe_os
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
;;
@@ -144,7 +148,7 @@ case $os in
-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
-apple | -axis)
-apple | -axis | -knuth | -cray)
os=
basic_machine=$1
;;
@@ -169,6 +173,10 @@ case $os in
-hiux*)
os=-hiuxwe2
;;
-sco6)
os=-sco5v6
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-sco5)
os=-sco3.2v5
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
@@ -185,6 +193,10 @@ case $os in
# Don't forget version if it is 3.2v4 or newer.
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-sco5v6*)
# Don't forget version if it is 3.2v4 or newer.
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-sco*)
os=-sco3.2v2
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
@@ -229,14 +241,16 @@ case $basic_machine in
| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
| am33_2.0 \
| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
| bfin \
| c4x | clipper \
| d10v | d30v | dlx | dsp16xx \
| fr30 | frv \
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
| i370 | i860 | i960 | ia64 \
| ip2k | iq2000 \
| m32r | m68000 | m68k | m88k | mcore \
| m32c | m32r | m32rle | m68000 | m68k | m88k \
| maxq | mb | microblaze | mcore \
| mips | mipsbe | mipseb | mipsel | mipsle \
| mips16 \
| mips64 | mips64el \
@@ -245,6 +259,7 @@ case $basic_machine in
| mips64vr4100 | mips64vr4100el \
| mips64vr4300 | mips64vr4300el \
| mips64vr5000 | mips64vr5000el \
| mips64vr5900 | mips64vr5900el \
| mipsisa32 | mipsisa32el \
| mipsisa32r2 | mipsisa32r2el \
| mipsisa64 | mipsisa64el \
@@ -253,20 +268,23 @@ case $basic_machine in
| mipsisa64sr71k | mipsisa64sr71kel \
| mipstx39 | mipstx39el \
| mn10200 | mn10300 \
| mt \
| msp430 \
| nios | nios2 \
| ns16k | ns32k \
| openrisc | or32 \
| or32 \
| pdp10 | pdp11 | pj | pjl \
| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
| pyramid \
| sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
| sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
| sh64 | sh64le \
| sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \
| strongarm \
| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
| spu | strongarm \
| tahoe | thumb | tic4x | tic80 | tron \
| v850 | v850e \
| we32k \
| x86 | xscale | xstormy16 | xtensa \
| x86 | xscale | xscalee[bl] | xstormy16 | xtensa \
| z8k)
basic_machine=$basic_machine-unknown
;;
@@ -277,6 +295,9 @@ case $basic_machine in
;;
m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
;;
ms1)
basic_machine=mt-unknown
;;
# We use `pc' rather than `unknown'
# because (1) that's what they normally are, and
@@ -296,10 +317,10 @@ case $basic_machine in
| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
| arm-* | armbe-* | armle-* | armeb-* | armv*-* \
| avr-* \
| bs2000-* \
| avr-* | avr32-* \
| bfin-* | bs2000-* \
| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
| clipper-* | cydra-* \
| clipper-* | craynv-* | cydra-* \
| d10v-* | d30v-* | dlx-* \
| elxsi-* \
| f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \
@@ -307,9 +328,9 @@ case $basic_machine in
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
| i*86-* | i860-* | i960-* | ia64-* \
| ip2k-* | iq2000-* \
| m32r-* \
| m32c-* | m32r-* | m32rle-* \
| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
| m88110-* | m88k-* | mcore-* \
| m88110-* | m88k-* | maxq-* | mcore-* \
| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
| mips16-* \
| mips64-* | mips64el-* \
@@ -318,6 +339,7 @@ case $basic_machine in
| mips64vr4100-* | mips64vr4100el-* \
| mips64vr4300-* | mips64vr4300el-* \
| mips64vr5000-* | mips64vr5000el-* \
| mips64vr5900-* | mips64vr5900el-* \
| mipsisa32-* | mipsisa32el-* \
| mipsisa32r2-* | mipsisa32r2el-* \
| mipsisa64-* | mipsisa64el-* \
@@ -325,24 +347,28 @@ case $basic_machine in
| mipsisa64sb1-* | mipsisa64sb1el-* \
| mipsisa64sr71k-* | mipsisa64sr71kel-* \
| mipstx39-* | mipstx39el-* \
| mmix-* \
| mt-* \
| msp430-* \
| none-* | np1-* | nv1-* | ns16k-* | ns32k-* \
| nios-* | nios2-* \
| none-* | np1-* | ns16k-* | ns32k-* \
| orion-* \
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
| pyramid-* \
| romp-* | rs6000-* \
| sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \
| sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
| sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \
| sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
| sparclite-* \
| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
| tahoe-* | thumb-* \
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
| tron-* \
| v850-* | v850e-* | vax-* \
| we32k-* \
| x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \
| xtensa-* \
| x86-* | x86_64-* | xps100-* | xscale-* | xscalee[bl]-* \
| xstormy16-* | xtensa-* \
| ymp-* \
| z8k-*)
;;
@@ -362,6 +388,9 @@ case $basic_machine in
basic_machine=a29k-amd
os=-udi
;;
abacus)
basic_machine=abacus-unknown
;;
adobe68k)
basic_machine=m68010-adobe
os=-scout
@@ -379,6 +408,9 @@ case $basic_machine in
amd64)
basic_machine=x86_64-pc
;;
amd64-*)
basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
amdahl)
basic_machine=580-amdahl
os=-sysv
@@ -438,12 +470,27 @@ case $basic_machine in
basic_machine=j90-cray
os=-unicos
;;
craynv)
basic_machine=craynv-cray
os=-unicosmp
;;
cr16c)
basic_machine=cr16c-unknown
os=-elf
;;
crds | unos)
basic_machine=m68k-crds
;;
crisv32 | crisv32-* | etraxfs*)
basic_machine=crisv32-axis
;;
cris | cris-* | etrax*)
basic_machine=cris-axis
;;
crx)
basic_machine=crx-unknown
os=-elf
;;
da30 | da30-*)
basic_machine=m68k-da30
;;
@@ -466,6 +513,10 @@ case $basic_machine in
basic_machine=m88k-motorola
os=-sysv3
;;
djgpp)
basic_machine=i586-pc
os=-msdosdjgpp
;;
dpx20 | dpx20-*)
basic_machine=rs6000-bull
os=-bosx
@@ -644,10 +695,6 @@ case $basic_machine in
mips3*)
basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
;;
mmix*)
basic_machine=mmix-knuth
os=-mmixware
;;
monitor)
basic_machine=m68k-rom68k
os=-coff
@@ -660,6 +707,9 @@ case $basic_machine in
basic_machine=i386-pc
os=-msdos
;;
ms1-*)
basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
;;
mvs)
basic_machine=i370-ibm
os=-mvs
@@ -728,10 +778,6 @@ case $basic_machine in
np1)
basic_machine=np1-gould
;;
nv1)
basic_machine=nv1-cray
os=-unicosmp
;;
nsr-tandem)
basic_machine=nsr-tandem
;;
@@ -739,9 +785,12 @@ case $basic_machine in
basic_machine=hppa1.1-oki
os=-proelf
;;
or32 | or32-*)
openrisc | openrisc-*)
basic_machine=or32-unknown
os=-coff
;;
os400)
basic_machine=powerpc-ibm
os=-os400
;;
OSE68000 | ose68000)
basic_machine=m68000-ericsson
@@ -768,6 +817,12 @@ case $basic_machine in
pc532 | pc532-*)
basic_machine=ns32k-pc532
;;
pc98)
basic_machine=i386-pc
;;
pc98-*)
basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
pentium | p5 | k5 | k6 | nexgen | viac3)
basic_machine=i586-pc
;;
@@ -824,6 +879,10 @@ case $basic_machine in
basic_machine=i586-unknown
os=-pw32
;;
rdos)
basic_machine=i386-pc
os=-rdos
;;
rom68k)
basic_machine=m68k-rom68k
os=-coff
@@ -963,6 +1022,10 @@ case $basic_machine in
tower | tower-32)
basic_machine=m68k-ncr
;;
tpf)
basic_machine=s390x-ibm
os=-tpf
;;
udi29k)
basic_machine=a29k-amd
os=-udi
@@ -1006,6 +1069,10 @@ case $basic_machine in
basic_machine=hppa1.1-winbond
os=-proelf
;;
xbox)
basic_machine=i686-pc
os=-mingw32
;;
xps | xps100)
basic_machine=xps100-honeywell
;;
@@ -1036,6 +1103,9 @@ case $basic_machine in
romp)
basic_machine=romp-ibm
;;
mmix)
basic_machine=mmix-knuth
;;
rs6000)
basic_machine=rs6000-ibm
;;
@@ -1052,13 +1122,10 @@ case $basic_machine in
we32k)
basic_machine=we32k-att
;;
sh3 | sh4 | sh[34]eb | sh[1234]le | sh[23]ele)
sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele)
basic_machine=sh-unknown
;;
sh64)
basic_machine=sh64-unknown
;;
sparc | sparcv9 | sparcv9b)
sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
basic_machine=sparc-sun
;;
cydra)
@@ -1131,19 +1198,23 @@ case $os in
| -aos* \
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
| -hiux* | -386bsd* | -netbsd* | -openbsd* | -kfreebsd* | -freebsd* | -riscix* \
| -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
| -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
| -openbsd* | -solidbsd* \
| -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
| -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
| -chorusos* | -chorusrdb* \
| -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
| -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \
| -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
| -uxpv* | -beos* | -mpeix* | -udk* \
| -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
| -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
| -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
| -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
| -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
| -powermax* | -dnix* | -nx6 | -nx7 | -sei*)
| -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
| -skyos* | -haiku* | -rdos* | -toppers*)
# Remember, each alternative MUST END IN *, to match a version number.
;;
-qnx*)
@@ -1161,7 +1232,7 @@ case $os in
os=`echo $os | sed -e 's|nto|nto-qnx|'`
;;
-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
| -windows* | -osx | -abug | -netware* | -os9* | -beos* \
| -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
| -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
;;
-mac*)
@@ -1182,6 +1253,9 @@ case $os in
-opened*)
os=-openedition
;;
-os400*)
os=-os400
;;
-wince*)
os=-wince
;;
@@ -1203,6 +1277,9 @@ case $os in
-atheos*)
os=-atheos
;;
-syllable*)
os=-syllable
;;
-386bsd)
os=-bsd
;;
@@ -1225,6 +1302,9 @@ case $os in
-sinix*)
os=-sysv4
;;
-tpf*)
os=-tpf
;;
-triton*)
os=-sysv3
;;
@@ -1261,6 +1341,9 @@ case $os in
-kaos*)
os=-kaos
;;
-zvmoe)
os=-zvmoe
;;
-none)
;;
*)
@@ -1283,6 +1366,9 @@ else
# system, and we'll never get to this point.
case $basic_machine in
spu-*)
os=-elf
;;
*-acorn)
os=-riscix1.2
;;
@@ -1292,9 +1378,9 @@ case $basic_machine in
arm*-semi)
os=-aout
;;
c4x-* | tic4x-*)
os=-coff
;;
c4x-* | tic4x-*)
os=-coff
;;
# This must come before the *-dec entry.
pdp10-*)
os=-tops20
@@ -1338,9 +1424,15 @@ case $basic_machine in
*-be)
os=-beos
;;
*-haiku)
os=-haiku
;;
*-ibm)
os=-aix
;;
*-knuth)
os=-mmixware
;;
*-wec)
os=-proelf
;;
@@ -1473,9 +1565,15 @@ case $basic_machine in
-mvs* | -opened*)
vendor=ibm
;;
-os400*)
vendor=ibm
;;
-ptx*)
vendor=sequent
;;
-tpf*)
vendor=ibm
;;
-vxsim* | -vxworks* | -windiss*)
vendor=wrs
;;
@@ -1500,7 +1598,7 @@ case $basic_machine in
esac
echo $basic_machine$os
exit 0
exit
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)

View File

@@ -5,7 +5,7 @@ AC_CONFIG_SRCDIR([byteorder.h])
AC_CONFIG_HEADER(config.h)
AC_PREREQ(2.59)
RSYNC_VERSION=2.6.7pre3
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)
@@ -123,15 +123,23 @@ else
fi
AC_DEFINE_UNQUOTED(RSYNC_RSH, "$RSYNC_RSH", [default -e command])
AC_MSG_CHECKING([the group for user "nobody"])
if grep '^nobody:' /etc/group >/dev/null 2>&1; then
NOBODY_GROUP=nobody
elif grep '^nogroup:' /etc/group >/dev/null 2>&1; then
NOBODY_GROUP=nogroup
else
NOBODY_GROUP=nobody # test for others?
AC_ARG_WITH(nobody-group,
AC_HELP_STRING([--with-nobody-group=GROUP],
[set the default unprivileged group (default nobody or nogroup)]),
[ NOBODY_GROUP="$with_nobody_group" ])
if test x"$with_nobody_group" = x; then
AC_MSG_CHECKING([the group for user "nobody"])
if grep '^nobody:' /etc/group >/dev/null 2>&1; then
NOBODY_GROUP=nobody
elif grep '^nogroup:' /etc/group >/dev/null 2>&1; then
NOBODY_GROUP=nogroup
else
NOBODY_GROUP=nobody # test for others?
fi
AC_MSG_RESULT($NOBODY_GROUP)
fi
AC_MSG_RESULT($NOBODY_GROUP)
AC_DEFINE_UNQUOTED(NOBODY_USER, "nobody", [unprivileged user--e.g. nobody])
AC_DEFINE_UNQUOTED(NOBODY_GROUP, "$NOBODY_GROUP", [unprivileged group for unprivileged user])
@@ -275,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
@@ -302,12 +310,43 @@ AC_CHECK_HEADERS(sys/fcntl.h sys/select.h fcntl.h sys/time.h sys/unistd.h \
netdb.h malloc.h float.h limits.h iconv.h libcharset.h langinfo.h)
AC_HEADER_MAJOR
AC_CACHE_CHECK([if makedev takes 3 args],rsync_cv_MAKEDEV_TAKES_3_ARGS,[
AC_TRY_RUN([
#include <sys/types.h>
#ifdef MAJOR_IN_MKDEV
#include <sys/mkdev.h>
# if !defined makedev && (defined mkdev || defined _WIN32 || defined __WIN32__)
# define makedev mkdev
# endif
#elif defined MAJOR_IN_SYSMACROS
#include <sys/sysmacros.h>
#endif
int main(void)
{
dev_t dev = makedev(0, 5, 7);
if (major(dev) != 5 || minor(dev) != 7)
exit(1);
return 0;
}
],
rsync_cv_MAKEDEV_TAKES_3_ARGS=yes,rsync_cv_MAKEDEV_TAKES_3_ARGS=no,rsync_cv_MAKEDEV_TAKES_3_ARGS=no)])
if test x"$rsync_cv_MAKEDEV_TAKES_3_ARGS" = x"yes"; then
AC_DEFINE(MAKEDEV_TAKES_3_ARGS, 1, [Define to 1 if makedev() takes 3 args])
fi
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
@@ -372,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)])
@@ -482,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.
@@ -494,16 +560,31 @@ 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
# Determine whether chown follows symlinks (it should).
AC_CACHE_CHECK([whether chown() dereferences symlinks],rsync_cv_chown_follows_symlink,[
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
# include <unistd.h>
@@ -514,14 +595,52 @@ AC_CACHE_CHECK([whether chown() dereferences symlinks],rsync_cv_chown_follows_sy
char const *dangling_symlink = "conftest.dangle";
unlink(dangling_symlink);
if (symlink("conftest.no-such", dangling_symlink) < 0) abort();
if (chown(dangling_symlink, getuid(), getgid()) < 0 && errno == ENOENT) exit(0);
exit(1);
if (chown(dangling_symlink, getuid(), getgid()) < 0 && errno == ENOENT) exit(1);
exit(0);
}],
rsync_cv_chown_follows_symlink=yes,rsync_cv_chown_follows_symlink=no,rsync_cv_chown_follows_symlink=yes)])
if test $rsync_cv_chown_follows_symlink = no; then
rsync_cv_chown_modifies_symlink=yes,rsync_cv_chown_modifies_symlink=no,rsync_cv_chown_modifies_symlink=no)])
if test $rsync_cv_chown_modifies_symlink = yes; then
AC_DEFINE(CHOWN_MODIFIES_SYMLINK, 1, [Define to 1 if chown modifies symlinks.])
fi
AC_CACHE_CHECK([whether link() can hard-link symlinks],rsync_cv_can_hardlink_symlink,[
AC_TRY_RUN([
#if HAVE_UNISTD_H
# include <unistd.h>
#endif
#include <stdlib.h>
#include <errno.h>
#define FILENAME "conftest.dangle"
main() {
unlink(FILENAME);
if (symlink("conftest.no-such", FILENAME) < 0) abort();
if (link(FILENAME, FILENAME "2") < 0) exit(1);
exit(0);
}],
rsync_cv_can_hardlink_symlink=yes,rsync_cv_can_hardlink_symlink=no,rsync_cv_can_hardlink_symlink=no)])
if test $rsync_cv_can_hardlink_symlink = yes; then
AC_DEFINE(CAN_HARDLINK_SYMLINK, 1, [Define to 1 if link() can hard-link symlinks.])
fi
AC_CACHE_CHECK([whether link() can hard-link special files],rsync_cv_can_hardlink_special,[
AC_TRY_RUN([
#if HAVE_UNISTD_H
# include <unistd.h>
#endif
#include <stdlib.h>
#include <errno.h>
#define FILENAME "conftest.fifi"
main() {
unlink(FILENAME);
if (mkfifo(FILENAME, 0777) < 0) abort();
if (link(FILENAME, FILENAME "2") < 0) exit(1);
exit(0);
}],
rsync_cv_can_hardlink_special=yes,rsync_cv_can_hardlink_special=no,rsync_cv_can_hardlink_special=no)])
if test $rsync_cv_can_hardlink_special = yes; then
AC_DEFINE(CAN_HARDLINK_SPECIAL, 1, [Define to 1 if link() can hard-link special files.])
fi
AC_CACHE_CHECK([for working socketpair],rsync_cv_HAVE_SOCKETPAIR,[
AC_TRY_RUN([
#include <sys/types.h>
@@ -650,35 +769,6 @@ if test x"$rsync_cv_HAVE_SECURE_MKSTEMP" = x"yes"; then
fi
AC_CACHE_CHECK([for broken inet_ntoa],rsync_cv_REPLACE_INET_NTOA,[
AC_TRY_RUN([
#include <stdio.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
main() { struct in_addr ip; ip.s_addr = 0x12345678;
if (strcmp(inet_ntoa(ip),"18.52.86.120") &&
strcmp(inet_ntoa(ip),"120.86.52.18")) { exit(1); }
exit(0);}],
rsync_cv_REPLACE_INET_NTOA=no,rsync_cv_REPLACE_INET_NTOA=yes,rsync_cv_REPLACE_INET_NTOA=cross)])
if test x"$rsync_cv_REPLACE_INET_NTOA" = x"yes"; then
AC_DEFINE(REPLACE_INET_NTOA, 1, [Define to 1 if inet_ntoa() needs to be replaced])
fi
AC_CACHE_CHECK([for broken inet_aton],rsync_cv_REPLACE_INET_ATON,[
AC_TRY_RUN([
#include <stdio.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
main() { struct in_addr ip;
if (inet_aton("example", &ip) == 0) exit(0); exit(1);}],
rsync_cv_REPLACE_INET_ATON=no,rsync_cv_REPLACE_INET_ATON=yes,rsync_cv_REPLACE_INET_ATON=cross)])
if test x"$rsync_cv_REPLACE_INET_ATON" = x"yes"; then
AC_DEFINE(REPLACE_INET_ATON, 1, [Define to 1 if inet_aton() needs to be replaced])
fi
AC_CACHE_CHECK([if mknod creates FIFOs],rsync_cv_MKNOD_CREATES_FIFOS,[
AC_TRY_RUN([
#include <stdio.h>
@@ -738,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

@@ -1,49 +1,46 @@
/*
Copyright (C) Andrew Tridgell 1998
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* Support the max connections option.
*
* Copyright (C) 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 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.
*/
/* support the max connections option */
#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

@@ -1,27 +1,26 @@
/* -*- c-file-style: "linux"; -*-
Copyright (C) 1998-2000 by 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* error codes returned by rsync. If you change these, please also update the
* string mappings in log.c and the EXIT VALUES in rsync.yo
* Error codes returned by rsync.
*
* Copyright (C) 1998-2000 Andrew Tridgell
* 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 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.
*/
/* If you change these, please also update the string mappings in log.c and
* the EXIT VALUES in rsync.yo. */
#define RERR_OK 0
#define RERR_SYNTAX 1 /* syntax or usage error */
#define RERR_PROTOCOL 2 /* protocol incompatibility */

162
exclude.c
View File

@@ -1,12 +1,14 @@
/* -*- c-file-style: "linux" -*-
/*
* The filter include/exclude routines.
*
* Copyright (C) 1996-2001 by Andrew Tridgell <tridge@samba.org>
* Copyright (C) 1996 by Paul Mackerras
* Copyright (C) 2002 by Martin Pool
* Copyright (C) 1996-2001 Andrew Tridgell <tridge@samba.org>
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2002 Martin Pool
* 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,
@@ -14,29 +16,21 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, visit the http://fsf.org website.
*/
/* a lot of this stuff was originally derived from GNU tar, although
it has now changed so much that it is hard to tell :) */
/* include/exclude cluestick added by Martin Pool <mbp@samba.org> */
#include "rsync.h"
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 saw_delete_opt;
extern int saw_delete_excluded_opt;
extern int prune_empty_dirs;
extern int ignore_perishable;
extern int delete_mode;
extern int delete_excluded;
extern int cvs_exclude;
@@ -56,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
@@ -149,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 == '/')
@@ -303,29 +296,28 @@ static char *parse_merge_name(const char *merge_file, unsigned int *len_ptr,
strlcpy(to, merge_file, *len_ptr + 1);
merge_file = to;
}
if (!sanitize_path(fn, merge_file, r, dirbuf_depth)) {
if (!sanitize_path(fn, merge_file, r, dirbuf_depth, NULL)) {
rprintf(FERROR, "merge-file name overflows: %s\n",
merge_file);
return NULL;
}
fn_len = strlen(fn);
} else {
strlcpy(fn, merge_file, len_ptr ? *len_ptr + 1 : MAXPATHLEN);
clean_fname(fn, 1);
fn_len = clean_fname(fn, 1);
}
fn_len = strlen(fn);
if (fn == buf)
goto done;
if (dirbuf_len + fn_len >= MAXPATHLEN) {
rprintf(FERROR, "merge-file name overflows: %s\n", fn);
return NULL;
/* If the name isn't in buf yet, it's wasn't absolute. */
if (fn != buf) {
if (dirbuf_len + fn_len >= MAXPATHLEN) {
rprintf(FERROR, "merge-file name overflows: %s\n", fn);
return NULL;
}
memcpy(buf, dirbuf + prefix_skip, dirbuf_len - prefix_skip);
memcpy(buf + dirbuf_len - prefix_skip, fn, fn_len + 1);
fn_len = clean_fname(buf, 1);
}
memcpy(buf, dirbuf + prefix_skip, dirbuf_len - prefix_skip);
memcpy(buf + dirbuf_len - prefix_skip, fn, fn_len + 1);
fn_len = clean_fname(buf, 1);
done:
if (len_ptr)
*len_ptr = fn_len;
return buf;
@@ -498,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;
@@ -505,6 +525,8 @@ static int rule_matches(char *name, struct filter_struct *ex, int name_is_dir)
char *p, *pattern = ex->pattern;
const char *strings[16]; /* more than enough */
if (*name == '/')
name++;
if (!*name)
return 0;
@@ -536,8 +558,6 @@ static int rule_matches(char *name, struct filter_struct *ex, int name_is_dir)
if (*pattern == '/') {
anchored_match = 1;
pattern++;
if (strings[0][0] == '/')
strings[0]++;
}
if (!anchored_match && ex->u.slash_cnt
@@ -562,7 +582,7 @@ static int rule_matches(char *name, struct filter_struct *ex, int name_is_dir)
if (litmatch_array(pattern, strings, slash_handling))
return ret_match;
} else if (anchored_match) {
if (strcmp(name,pattern) == 0)
if (strcmp(name, pattern) == 0)
return ret_match;
} else {
int l1 = strlen(name);
@@ -607,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);
@@ -814,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;
@@ -852,13 +877,22 @@ static const char *parse_rule_tok(const char *p, uint32 mflags, int xflags,
exit_cleanup(RERR_SYNTAX);
}
/* --delete-excluded turns an un-modified include/exclude into a
* sender-side rule. We also affect per-dir merge files that take
* no prefixes as a simple optimization. */
if (delete_excluded
&& !(new_mflags & (MATCHFLG_RECEIVER_SIDE|MATCHFLG_SENDER_SIDE))
&& (!(new_mflags & MATCHFLG_PERDIR_MERGE)
|| new_mflags & MATCHFLG_NO_PREFIXES))
new_mflags |= MATCHFLG_SENDER_SIDE;
*len_ptr = len;
*mflags_ptr = new_mflags;
return (const char *)s;
}
static char default_cvsignore[] =
static char default_cvsignore[] =
/* These default ignored items come from the CVS manual. */
"RCS SCCS CVS CVS.adm RCSLOG cvslog.* tags TAGS"
" .make.state .nse_depinfo *~ #* .#* ,* _$* *$"
@@ -866,18 +900,20 @@ static char default_cvsignore[] =
" *.a *.olb *.o *.obj *.so *.exe"
" *.Z *.elc *.ln core"
/* The rest we added to suit ourself. */
" .svn/";
" .svn/ .bzr/";
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)
@@ -903,12 +939,14 @@ void parse_rule(struct filter_list_struct *listp, const char *pattern,
&pat_len, &new_mflags);
if (!cp)
break;
pattern = cp + pat_len;
if (pat_len >= MAXPATHLEN) {
rprintf(FERROR, "discarding over-long filter: %s\n",
cp);
rprintf(FERROR, "discarding over-long filter: %.*s\n",
(int)pat_len, cp);
continue;
}
pattern = cp + pat_len;
if (new_mflags & MATCHFLG_CLEAR_LIST) {
if (verbose > 2) {
@@ -928,11 +966,9 @@ void parse_rule(struct filter_list_struct *listp, const char *pattern,
}
len = pat_len;
if (new_mflags & MATCHFLG_EXCLUDE_SELF) {
const char *name = strrchr(cp, '/');
if (name)
len -= ++name - cp;
else
name = cp;
const char *name = cp + len;
while (name > cp && name[-1] != '/') name--;
len -= name - cp;
add_rule(listp, name, len, 0, 0);
new_mflags &= ~MATCHFLG_EXCLUDE_SELF;
len = pat_len;
@@ -1061,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 {
@@ -1084,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)
@@ -1103,11 +1147,20 @@ static void send_rules(int f_out, struct filter_list_struct *flp)
int elide = 0;
char *p;
/* Note we need to check delete_excluded here in addition to
* the code in parse_rule_tok() because some rules may have
* been added before we found the --delete-excluded option.
* We must also elide any CVS merge-file rules to avoid a
* backward compatibility problem, and we elide any no-prefix
* merge files as an optimization (since they can only have
* include/exclude rules). */
if (ent->match_flags & MATCHFLG_SENDER_SIDE)
elide = am_sender ? 1 : -1;
if (ent->match_flags & MATCHFLG_RECEIVER_SIDE)
elide = elide ? 0 : am_sender ? -1 : 1;
else if (delete_excluded && !elide)
else if (delete_excluded && !elide
&& (!(ent->match_flags & MATCHFLG_PERDIR_MERGE)
|| ent->match_flags & MATCHFLG_NO_PREFIXES))
elide = am_sender ? 1 : -1;
if (elide < 0) {
if (prev)
@@ -1129,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;
@@ -1161,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)
@@ -1185,8 +1233,8 @@ void recv_filter_list(int f_in)
char line[BIGPATHBUFLEN];
int xflags = protocol_version >= 29 ? 0 : XFLG_OLD_PREFIXES;
int receiver_wants_list = prune_empty_dirs
|| (saw_delete_opt
&& (!saw_delete_excluded_opt || protocol_version >= 29));
|| (delete_mode
&& (!delete_excluded || protocol_version >= 29));
unsigned int len;
if (!local_server && (am_sender || receiver_wants_list)) {

102
fileio.c
View File

@@ -1,25 +1,24 @@
/*
Copyright (C) Andrew Tridgell 1998
Copyright (C) 2002 by Martin Pool
* File IO utilities used in rsync.
*
* Copyright (C) 1998 Andrew Tridgell
* Copyright (C) 2002 Martin Pool
* 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 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.
*/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
File IO utilities used in rsync
*/
#include "rsync.h"
#ifndef ENODATA
@@ -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 {
@@ -232,7 +238,6 @@ char *map_ptr(struct map_struct *map, OFF_T offset, int32 len)
}
map->p_fd_offset = read_start;
}
map->p_fd_offset += read_size;
map->p_offset = window_start;
map->p_len = window_size;
@@ -246,6 +251,7 @@ char *map_ptr(struct map_struct *map, OFF_T offset, int32 len)
memset(map->p + read_offset, 0, read_size);
break;
}
map->p_fd_offset += nread;
read_offset += nread;
read_size -= nread;
}

2358
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

@@ -1,28 +1,22 @@
/*
* Copyright (C) 2002 by Martin Pool
*
* Print out the gids of all groups for the current user. This is like
* `id -G` on Linux, but it's too hard to find a portable equivalent.
*
* Copyright (C) 2002 Martin Pool
* 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
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/**
* @file getgroups.c
*
* Print out the gids of all groups for the current user. This is
* like `id -G` on Linux, but it's too hard to find a portable
* equivalent.
**/
* 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"
@@ -63,6 +57,6 @@ main(UNUSED(int argc), UNUSED(char *argv[]))
if (!gid_in_list)
printf("%lu", (unsigned long)gid);
printf("\n");
return 0;
}

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;
}

651
hlink.c
View File

@@ -1,160 +1,225 @@
/*
Copyright (C) Andrew Tridgell 1996
Copyright (C) Paul Mackerras 1996
Copyright (C) 2002 by Martin Pool <mbp@samba.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
* Routines to support hard-linking.
*
* Copyright (C) 1996 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2002 Martin Pool <mbp@samba.org>
* 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 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"
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 log_format_has_i;
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 int *hlink_list;
static int 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)
{
int 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];
}
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;
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, int, 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(int, 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)) {
@@ -163,77 +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 (!log_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 = f_name(head_file, NULL);
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 || !log_format_has_i)
itemizing = code = 0;
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);
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;
@@ -241,50 +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 && 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);
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);
}

1209
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

@@ -1,42 +1,34 @@
/*
Copyright (C) Andrew Tridgell 1998
Copyright (C) 2002 by Martin Pool
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/**
* @file compat.c
/*
* Reimplementations of standard functions for platforms that don't have them.
*
* Reimplementations of standard functions for platforms that don't
* have them.
**/
* Copyright (C) 1998 Andrew Tridgell
* Copyright (C) 2002 Martin Pool
* Copyright (C) 2004, 2005, 2006 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 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"
#ifndef HAVE_STRDUP
char *strdup(char *s)
{
int l = strlen(s) + 1;
char *ret = (char *)malloc(l);
if (ret)
strcpy(ret,s);
return ret;
int len = strlen(s) + 1;
char *ret = (char *)malloc(len);
if (ret)
memcpy(ret, s, len);
return ret;
}
#endif
@@ -86,7 +78,7 @@
/**
* Find the first ocurrence in @p s of any character in @p accept.
*
* Derived from glibc
* Derived from glibc
**/
char *strpbrk(const char *s, const char *accept)
{
@@ -105,7 +97,7 @@
#ifndef HAVE_STRLCPY
/**
* Like strncpy but does not 0 fill the buffer and always null
* Like strncpy but does not 0 fill the buffer and always null
* terminates.
*
* @param bufsize is the size of the destination buffer.
@@ -128,7 +120,7 @@
#ifndef HAVE_STRLCAT
/**
* Like strncat() but does not 0 fill the buffer and always null
* Like strncat() but does not 0 fill the buffer and always null
* terminates.
*
* @param bufsize length of the buffer, which should be one more than
@@ -150,49 +142,6 @@
}
#endif
#ifdef REPLACE_INET_NTOA
char *rep_inet_ntoa(struct in_addr ip)
{
unsigned char *p = (unsigned char *)&ip.s_addr;
static char buf[18];
#ifdef WORDS_BIGENDIAN
snprintf(buf, 18, "%d.%d.%d.%d",
(int)p[0], (int)p[1], (int)p[2], (int)p[3]);
#else
snprintf(buf, 18, "%d.%d.%d.%d",
(int)p[3], (int)p[2], (int)p[1], (int)p[0]);
#endif
return buf;
}
#endif
#ifdef REPLACE_INET_ATON
int inet_aton(const char *cp, struct in_addr *inp)
{
unsigned int a1, a2, a3, a4;
unsigned long ret;
if (strcmp(cp, "255.255.255.255") == 0) {
inp->s_addr = (unsigned) -1;
return 0;
}
if (sscanf(cp, "%u.%u.%u.%u", &a1, &a2, &a3, &a4) != 4 ||
a1 > 255 || a2 > 255 || a3 > 255 || a4 > 255) {
return 0;
}
ret = (a1 << 24) | (a2 << 16) | (a3 << 8) | a4;
inp->s_addr = htonl(ret);
if (inp->s_addr == (unsigned) -1) {
return 0;
}
return 1;
}
#endif
/* some systems don't take the 2nd argument */
int sys_gettimeofday(struct timeval *tv)
{

View File

@@ -75,13 +75,14 @@ inet_ntop4(const unsigned char *src, char *dst, size_t size)
{
static const char *fmt = "%u.%u.%u.%u";
char tmp[sizeof "255.255.255.255"];
size_t len;
if ((size_t)sprintf(tmp, fmt, src[0], src[1], src[2], src[3]) >= size)
{
len = snprintf(tmp, sizeof tmp, fmt, src[0], src[1], src[2], src[3]);
if (len >= size) {
errno = ENOSPC;
return (NULL);
}
strcpy(dst, tmp);
memcpy(dst, tmp, len + 1);
return (dst);
}
@@ -106,7 +107,7 @@ inet_ntop6(const unsigned char *src, char *dst, size_t size)
char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
struct { int base, len; } best, cur;
unsigned int words[NS_IN6ADDRSZ / NS_INT16SZ];
int i;
int i, inc;
/*
* Preprocess:
@@ -157,13 +158,14 @@ inet_ntop6(const unsigned char *src, char *dst, size_t size)
/* Is this address an encapsulated IPv4? */
if (i == 6 && best.base == 0 &&
(best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
if (!inet_ntop4(src+12, tp,
sizeof tmp - (tp - tmp)))
if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp)))
return (NULL);
tp += strlen(tp);
break;
}
tp += sprintf(tp, "%x", words[i]);
inc = snprintf(tp, 5, "%x", words[i]);
assert(inc < 5);
tp += inc;
}
/* Was it a trailing run of 0x00's? */
if (best.base != -1 && (best.base + best.len) ==
@@ -178,7 +180,7 @@ inet_ntop6(const unsigned char *src, char *dst, size_t size)
errno = ENOSPC;
return (NULL);
}
strcpy(dst, tmp);
memcpy(dst, tmp, tp - tmp);
return (dst);
}
#endif /* AF_INET6 */

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

@@ -1,32 +1,32 @@
/*
Unix SMB/Netbios implementation.
Version 1.9.
a implementation of MD4 designed for use in the SMB authentication protocol
Copyright (C) Andrew Tridgell 1997-1998.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
* 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
* 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 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"
/* NOTE: This code makes no attempt to be fast!
*
* It assumes that a int is at least 32 bits long. */
It assumes that a int is at least 32 bits long
*/
static struct mdfour *m;
static md_context *m;
#define MASK32 (0xffffffff)
@@ -48,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;
@@ -85,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;
@@ -102,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;
@@ -112,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
@@ -140,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 {
@@ -153,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);
@@ -163,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
@@ -211,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) {
@@ -223,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);
@@ -236,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,35 +0,0 @@
/*
Unix SMB/Netbios implementation.
Version 1.9.
a implementation of MD4 designed for use in the SMB authentication protocol
Copyright (C) Andrew Tridgell 1997-1998.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
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

@@ -1,40 +1,39 @@
/*
Copyright (C) Andrew Tridgell 1996
Copyright (C) Paul Mackerras 1996
Copyright (C) 2001 by Martin Pool <mbp@samba.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* A single utility routine.
*
* Copyright (C) 1996 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2001 Martin Pool <mbp@samba.org>
* Copyright (C) 2003, 2006 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 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"
/**
* Produce a string representation of Unix mode bits like that used by
* ls(1).
*
* @param buf buffer of at least 11 characters
**/
/* Produce a string representation of Unix mode bits like that used by ls(1).
* The "buf" buffer must be at least 11 characters. */
void permstring(char *perms, mode_t mode)
{
static const char *perm_map = "rwxrwxrwx";
int i;
strcpy(perms, "----------");
for (i=0;i<9;i++) {
if (mode & (1<<i)) perms[9-i] = perm_map[8-i];
strlcpy(perms, "----------", 11);
for (i = 0; i < 9; i++) {
if (mode & (1 << i))
perms[9-i] = perm_map[8-i];
}
/* Handle setuid/sticky bits. You might think the indices are
@@ -45,18 +44,22 @@ void permstring(char *perms, mode_t mode)
if (mode & S_ISGID)
perms[6] = (mode & S_IXGRP) ? 's' : 'S';
#ifdef S_ISVTX
if (mode & S_ISVTX)
perms[9] = (mode & S_IXOTH) ? 't' : 'T';
#endif
if (S_ISLNK(mode)) perms[0] = 'l';
if (S_ISDIR(mode)) perms[0] = 'd';
if (S_ISBLK(mode)) perms[0] = 'b';
if (S_ISCHR(mode)) perms[0] = 'c';
if (S_ISSOCK(mode)) perms[0] = 's';
if (S_ISFIFO(mode)) perms[0] = 'p';
}
if (S_ISDIR(mode))
perms[0] = 'd';
else if (S_ISLNK(mode))
perms[0] = 'l';
else if (S_ISBLK(mode))
perms[0] = 'b';
else if (S_ISCHR(mode))
perms[0] = 'c';
else if (S_ISSOCK(mode))
perms[0] = 's';
else if (S_ISFIFO(mode))
perms[0] = 'p';
}

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);
strcpy(buf, " FREE BOUND\n");
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

@@ -1,26 +1,25 @@
/* This is based on loadparm.c from Samba, written by Andrew Tridgell
and Karl Auer */
/* some fixes
/*
* 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.
*
* Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
* 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.
*/
/*
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* some fixes
*
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
*/
/*
* Load parameters.
@@ -51,12 +50,20 @@
/* 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")
typedef char pstring[1024];
#define pstrcpy(a,b) strlcpy(a,b,sizeof(pstring))
#ifndef LOG_DAEMON
#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
{
@@ -99,13 +106,11 @@ struct parm_struct
typedef struct
{
char *bind_address;
char *log_file;
char *motd_file;
char *pid_file;
char *socket_options;
int rsync_port;
int syslog_facility;
} global;
static global Globals;
@@ -131,6 +136,7 @@ typedef struct
char *include_from;
char *incoming_chmod;
char *lock_file;
char *log_file;
char *log_format;
char *name;
char *outgoing_chmod;
@@ -144,8 +150,10 @@ typedef struct
int max_connections;
int max_verbosity;
int syslog_facility;
int timeout;
BOOL fake_super;
BOOL ignore_errors;
BOOL ignore_nonreadable;
BOOL list;
@@ -165,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,
@@ -176,6 +184,7 @@ static service sDefault =
/* include_from; */ NULL,
/* incoming_chmod; */ NULL,
/* lock_file; */ DEFAULT_LOCK_FILE,
/* log_file; */ NULL,
/* log_format; */ "%o %h [%a] %m (%u) %f %l",
/* name; */ NULL,
/* outgoing_chmod; */ NULL,
@@ -189,8 +198,10 @@ static service sDefault =
/* max_connections; */ 0,
/* max_verbosity; */ 1,
/* syslog_facility; */ LOG_DAEMON,
/* timeout; */ 0,
/* fake_super; */ False,
/* ignore_errors; */ False,
/* ignore_nonreadable; */ False,
/* list; */ True,
@@ -282,18 +293,17 @@ static struct enum_list enum_facilities[] = {
static struct parm_struct parm_table[] =
{
{"address", P_STRING, P_GLOBAL,&Globals.bind_address, NULL,0},
{"log file", P_STRING, P_GLOBAL,&Globals.log_file, NULL,0},
{"motd file", P_STRING, P_GLOBAL,&Globals.motd_file, NULL,0},
{"pid file", P_STRING, P_GLOBAL,&Globals.pid_file, NULL,0},
{"port", P_INTEGER,P_GLOBAL,&Globals.rsync_port, NULL,0},
{"socket options", P_STRING, P_GLOBAL,&Globals.socket_options, NULL,0},
{"syslog facility", P_ENUM, P_GLOBAL,&Globals.syslog_facility,enum_facilities,0},
{"auth users", P_STRING, P_LOCAL, &sDefault.auth_users, NULL,0},
{"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL,0},
{"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},
@@ -305,6 +315,7 @@ static struct parm_struct parm_table[] =
{"incoming chmod", P_STRING, P_LOCAL, &sDefault.incoming_chmod, NULL,0},
{"list", P_BOOL, P_LOCAL, &sDefault.list, NULL,0},
{"lock file", P_STRING, P_LOCAL, &sDefault.lock_file, NULL,0},
{"log file", P_STRING, P_LOCAL, &sDefault.log_file, NULL,0},
{"log format", P_STRING, P_LOCAL, &sDefault.log_format, NULL,0},
{"max connections", P_INTEGER,P_LOCAL, &sDefault.max_connections, NULL,0},
{"max verbosity", P_INTEGER,P_LOCAL, &sDefault.max_verbosity, NULL,0},
@@ -319,6 +330,7 @@ static struct parm_struct parm_table[] =
{"refuse options", P_STRING, P_LOCAL, &sDefault.refuse_options, NULL,0},
{"secrets file", P_STRING, P_LOCAL, &sDefault.secrets_file, NULL,0},
{"strict modes", P_BOOL, P_LOCAL, &sDefault.strict_modes, NULL,0},
{"syslog facility", P_ENUM, P_LOCAL, &sDefault.syslog_facility,enum_facilities,0},
{"temp dir", P_PATH, P_LOCAL, &sDefault.temp_dir, NULL,0},
{"timeout", P_INTEGER,P_LOCAL, &sDefault.timeout, NULL,0},
{"transfer logging", P_BOOL, P_LOCAL, &sDefault.transfer_logging, NULL,0},
@@ -330,18 +342,15 @@ static struct parm_struct parm_table[] =
/***************************************************************************
Initialise the global parameter structure.
* Initialise the global parameter structure.
***************************************************************************/
static void init_globals(void)
{
memset(&Globals, 0, sizeof Globals);
#ifdef LOG_DAEMON
Globals.syslog_facility = LOG_DAEMON;
#endif
}
/***************************************************************************
Initialise the sDefault parameter structure.
* Initialise the sDefault parameter structure.
***************************************************************************/
static void init_locals(void)
{
@@ -373,13 +382,11 @@ static void init_locals(void)
FN_GLOBAL_STRING(lp_bind_address, &Globals.bind_address)
FN_GLOBAL_STRING(lp_log_file, &Globals.log_file)
FN_GLOBAL_STRING(lp_motd_file, &Globals.motd_file)
FN_GLOBAL_STRING(lp_pid_file, &Globals.pid_file)
FN_GLOBAL_STRING(lp_socket_options, &Globals.socket_options)
FN_GLOBAL_INTEGER(lp_rsync_port, &Globals.rsync_port)
FN_GLOBAL_INTEGER(lp_syslog_facility, &Globals.syslog_facility)
FN_LOCAL_STRING(lp_auth_users, auth_users)
FN_LOCAL_STRING(lp_comment, comment)
@@ -394,6 +401,7 @@ FN_LOCAL_STRING(lp_include, include)
FN_LOCAL_STRING(lp_include_from, include_from)
FN_LOCAL_STRING(lp_incoming_chmod, incoming_chmod)
FN_LOCAL_STRING(lp_lock_file, lock_file)
FN_LOCAL_STRING(lp_log_file, log_file)
FN_LOCAL_STRING(lp_log_format, log_format)
FN_LOCAL_STRING(lp_name, name)
FN_LOCAL_STRING(lp_outgoing_chmod, outgoing_chmod)
@@ -402,6 +410,7 @@ FN_LOCAL_STRING(lp_postxfer_exec, postxfer_exec)
FN_LOCAL_STRING(lp_prexfer_exec, prexfer_exec)
FN_LOCAL_STRING(lp_refuse_options, refuse_options)
FN_LOCAL_STRING(lp_secrets_file, secrets_file)
FN_LOCAL_INTEGER(lp_syslog_facility, syslog_facility)
FN_LOCAL_STRING(lp_temp_dir, temp_dir)
FN_LOCAL_STRING(lp_uid, uid)
@@ -409,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)
@@ -429,7 +439,7 @@ static BOOL do_section(char *sectionname);
/***************************************************************************
initialise a service to the defaults
* initialise a service to the defaults
***************************************************************************/
static void init_service(service *pservice)
{
@@ -463,8 +473,8 @@ static void string_set(char **s, const char *v)
/***************************************************************************
add a new service to the services array initialising it with the given
service
* add a new service to the services array initialising it with the given
* service
***************************************************************************/
static int add_a_service(service *pservice, char *name)
{
@@ -503,7 +513,7 @@ static int add_a_service(service *pservice, char *name)
}
/***************************************************************************
Do a case-insensitive, whitespace-ignoring string compare.
* Do a case-insensitive, whitespace-ignoring string compare.
***************************************************************************/
static int strwicmp(char *psz1, char *psz2)
{
@@ -521,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++;
@@ -535,8 +544,8 @@ static int strwicmp(char *psz1, char *psz2)
}
/***************************************************************************
Map a parameter's string representation to something we can use.
Returns False if the parameter string is not recognised, else TRUE.
* Map a parameter's string representation to something we can use.
* Returns False if the parameter string is not recognised, else TRUE.
***************************************************************************/
static int map_parameter(char *parmname)
{
@@ -555,9 +564,9 @@ static int map_parameter(char *parmname)
/***************************************************************************
Set a boolean variable from the text value stored in the passed string.
Returns True in success, False if the passed string does not correctly
represent a boolean.
* Set a boolean variable from the text value stored in the passed string.
* Returns True in success, False if the passed string does not correctly
* represent a boolean.
***************************************************************************/
static BOOL set_boolean(BOOL *pb, char *parmvalue)
{
@@ -583,7 +592,7 @@ static BOOL set_boolean(BOOL *pb, char *parmvalue)
}
/***************************************************************************
Find a service by name. Otherwise works like get_service.
* Find a service by name. Otherwise works like get_service.
***************************************************************************/
static int getservicebyname(char *name, service *pserviceDest)
{
@@ -603,8 +612,7 @@ static int getservicebyname(char *name, service *pserviceDest)
/***************************************************************************
Copy a service structure to another
* Copy a service structure to another
***************************************************************************/
static void copy_service(service *pserviceDest,
service *pserviceSource)
@@ -649,8 +657,8 @@ static void copy_service(service *pserviceDest,
/***************************************************************************
Process a parameter for a particular service number. If snum < 0
then assume we are in the globals
* Process a parameter for a particular service number. If snum < 0
* then assume we are in the globals
***************************************************************************/
static BOOL lp_do_parameter(int snum, char *parmname, char *parmvalue)
{
@@ -741,7 +749,7 @@ static BOOL lp_do_parameter(int snum, char *parmname, char *parmvalue)
}
/***************************************************************************
Process a parameter.
* Process a parameter.
***************************************************************************/
static BOOL do_parameter(char *parmname, char *parmvalue)
{
@@ -749,9 +757,9 @@ static BOOL do_parameter(char *parmname, char *parmvalue)
}
/***************************************************************************
Process a new section (service). At this stage all sections are services.
Later we'll have special sections that permit server parameters to be set.
Returns True on success, False on failure.
* Process a new section (service). At this stage all sections are services.
* Later we'll have special sections that permit server parameters to be set.
* Returns True on success, False on failure.
***************************************************************************/
static BOOL do_section(char *sectionname)
{
@@ -796,14 +804,11 @@ static BOOL do_section(char *sectionname)
/***************************************************************************
Load the services array from the services file. Return True on success,
False on failure.
* Load the services array from the services file. Return True on success,
* False on failure.
***************************************************************************/
BOOL lp_load(char *pszFname, int globals_only)
{
extern int am_server;
extern int am_daemon;
extern int am_root;
pstring n2;
BOOL bRetval;
@@ -813,12 +818,7 @@ BOOL lp_load(char *pszFname, int globals_only)
init_globals();
if (pszFname)
pstrcpy(n2,pszFname);
else if (am_server && am_daemon && !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;
@@ -829,7 +829,7 @@ BOOL lp_load(char *pszFname, int globals_only)
/***************************************************************************
return the max number of services
* return the max number of services
***************************************************************************/
int lp_numservices(void)
{
@@ -837,10 +837,10 @@ int lp_numservices(void)
}
/***************************************************************************
Return the number of the service with the given name, or -1 if it doesn't
exist. Note that this is a DIFFERENT ANIMAL from the internal function
getservicebyname()! This works ONLY if all services have been loaded, and
does not copy the found service.
* Return the number of the service with the given name, or -1 if it doesn't
* exist. Note that this is a DIFFERENT ANIMAL from the internal function
* getservicebyname()! This works ONLY if all services have been loaded, and
* does not copy the found service.
***************************************************************************/
int lp_number(char *name)
{

464
log.c
View File

@@ -1,40 +1,33 @@
/* -*- c-file-style: "linux"; -*-
Copyright (C) 1998-2001 by Andrew Tridgell <tridge@samba.org>
Copyright (C) 2000-2001 by Martin Pool <mbp@samba.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
Logging and utility functions.
tridge, May 1998
* Logging and utility functions.
*
* Copyright (C) 1998-2001 Andrew Tridgell <tridge@samba.org>
* Copyright (C) 2000-2001 Martin Pool <mbp@samba.org>
* 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 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.
*/
Mapping to human-readable messages added by Martin Pool
<mbp@samba.org>, Oct 2000.
*/
#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;
@@ -42,20 +35,30 @@ extern int msg_fd_out;
extern int allow_8bit_chars;
extern int protocol_version;
extern int preserve_times;
extern int log_format_has_i;
extern int log_format_has_o_or_i;
extern int daemon_log_format_has_o_or_i;
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;
extern int logfile_format_has_o_or_i;
extern mode_t orig_umask;
extern char *auth_user;
extern char *log_format;
#if defined HAVE_ICONV_OPEN && defined HAVE_ICONV_H
extern char *stdout_format;
extern char *logfile_format;
extern char *logfile_name;
#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;
static int logfile_was_closed;
static char *logfname;
static FILE *logfile;
static FILE *logfile_fp;
struct stats stats;
int log_got_error = 0;
@@ -91,7 +94,6 @@ struct {
{ 0, NULL }
};
/*
* Map from rsync error code to name, or return NULL.
*/
@@ -105,14 +107,14 @@ 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();
if (logfile) {
fprintf(logfile,"%s [%d] %s",
if (logfile_fp) {
fprintf(logfile_fp, "%s [%d] %s",
timestring(time(NULL)), (int)getpid(), buf);
fflush(logfile);
fflush(logfile_fp);
} else {
syslog(priority, "%s", buf);
}
@@ -132,7 +134,7 @@ static void syslog_init()
#endif
#ifdef LOG_DAEMON
openlog("rsyncd", options, lp_syslog_facility());
openlog("rsyncd", options, lp_syslog_facility(module_id));
#else
openlog("rsyncd", options);
#endif
@@ -145,35 +147,49 @@ static void syslog_init()
static void logfile_open(void)
{
mode_t old_umask = umask(022 | orig_umask);
logfile = fopen(logfname, "a");
logfile_fp = fopen(logfile_name, "a");
umask(old_umask);
if (!logfile) {
if (!logfile_fp) {
int fopen_errno = errno;
/* Rsync falls back to using syslog on failure. */
syslog_init();
rsyserr(FERROR, fopen_errno,
"failed to open log-file %s", logfname);
"failed to open log-file %s", logfile_name);
rprintf(FINFO, "Ignoring \"log file\" setting.\n");
}
}
void log_init(void)
void log_init(int restart)
{
time_t t;
if (log_initialised) {
if (!restart)
return;
if (strcmp(logfile_name, lp_log_file(module_id)) != 0) {
if (logfile_fp) {
fclose(logfile_fp);
logfile_fp = NULL;
} else
closelog();
logfile_name = NULL;
} else if (*logfile_name)
return; /* unchanged, non-empty "log file" names */
else if (lp_syslog_facility(-1) != lp_syslog_facility(module_id))
closelog();
else
return; /* unchanged syslog settings */
} else
log_initialised = 1;
if (log_initialised)
return;
log_initialised = 1;
/* this looks pointless, but it is needed in order for the
/* This looks pointless, but it is needed in order for the
* C library on some systems to fetch the timezone info
* before the chroot */
t = time(NULL);
localtime(&t);
* before the chroot. */
timestring(time(NULL));
/* optionally use a log file instead of syslog */
logfname = lp_log_file();
if (logfname && *logfname)
/* Optionally use a log file instead of syslog. (Non-daemon
* rsyncs will have already set logfile_name, as needed.) */
if (am_daemon && !logfile_name)
logfile_name = lp_log_file(module_id);
if (logfile_name && *logfile_name)
logfile_open();
else
syslog_init();
@@ -181,10 +197,10 @@ void log_init(void)
void logfile_close(void)
{
if (logfile) {
if (logfile_fp) {
logfile_was_closed = 1;
fclose(logfile);
logfile = NULL;
fclose(logfile_fp);
logfile_fp = NULL;
}
}
@@ -202,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);
@@ -221,20 +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 (quiet && code == FINFO)
return;
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;
}
@@ -243,7 +264,7 @@ void rwrite(enum logcode code, char *buf, int len)
if (code == FCLIENT)
code = FINFO;
else if (am_daemon) {
else if (am_daemon || logfile_name) {
static int in_block;
char msg[2048];
int priority = code == FERROR ? LOG_WARNING : LOG_INFO;
@@ -252,19 +273,22 @@ void rwrite(enum logcode code, char *buf, int len)
return;
in_block = 1;
if (!log_initialised)
log_init();
log_init(0);
strlcpy(msg, buf, MIN((int)sizeof msg, len + 1));
logit(priority, msg);
in_block = 0;
if (code == FLOG || !am_server)
if (code == FLOG || (am_daemon && !am_server))
return;
} else if (code == FLOG)
return;
if (quiet && code != FERROR)
return;
if (am_server) {
/* Pass the message to the non-server side. */
if (io_multiplex_write((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? */
@@ -276,17 +300,8 @@ void rwrite(enum logcode code, char *buf, int len)
case FERROR:
log_got_error = 1;
f = stderr;
goto pre_scan;
case FINFO:
f = am_server ? stderr : stdout;
pre_scan:
while (len > 1 && *buf == '\n') {
fputc(*buf, f);
buf++;
len--;
}
break;
case FNAME:
case FINFO:
f = am_server ? stderr : stdout;
break;
default:
@@ -296,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);
@@ -365,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
@@ -382,7 +397,7 @@ void rsyserr(enum logcode code, int errcode, const char *format, ...)
char buf[BIGPATHBUFLEN];
size_t len;
strcpy(buf, RSYNC_NAME ": ");
strlcpy(buf, RSYNC_NAME ": ", sizeof buf);
len = (sizeof RSYNC_NAME ": ") - 1;
va_start(ap, format);
@@ -396,44 +411,33 @@ 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)
{
FILE *f = NULL;
if (am_daemon) {
if (am_daemon || code == FLOG)
return;
}
if (code == FLOG) {
return;
}
if (code == FERROR) {
if (code == FERROR || am_server)
f = stderr;
}
else
f = stdout;
if (code == FINFO) {
if (am_server)
f = stderr;
else
f = stdout;
}
if (!f) exit_cleanup(RERR_MESSAGEIO);
fflush(f);
}
/* 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)
/* A generic logging routine for send/recv, with parameter substitiution. */
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;
@@ -452,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) {
@@ -474,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;
@@ -500,52 +504,71 @@ 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;
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;
strcpy(buf2, " => ");
} else if (S_ISLNK(file->mode) && file->u.link) {
n = file->u.link;
strcpy(buf2, " -> ");
strlcpy(buf2, " => ", sizeof buf2);
} else if (S_ISLNK(file->mode) && !fname) {
n = F_SYMLINK(file);
strlcpy(buf2, " -> ", sizeof buf2);
} else {
n = "";
if (!fmt[1])
break;
strcpy(buf2, " ");
strlcpy(buf2, " ", sizeof buf2);
}
strlcat(fmt, "s", sizeof fmt);
snprintf(buf2 + 4, sizeof buf2 - 4, fmt, n);
@@ -558,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;
@@ -592,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;
@@ -664,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
@@ -679,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;
@@ -689,62 +713,70 @@ int log_format_has(const char *format, char esc)
return 0;
}
/* log the transfer of a file */
void log_item(struct file_struct *file, struct stats *initial_stats,
int iflags, char *hlink)
/* Log the transfer of a file. If the code is FCLIENT, the output just goes
* 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, const char *hlink)
{
char *s_or_r = am_sender ? "send" : "recv";
const char *s_or_r = am_sender ? "send" : "recv";
if (lp_transfer_logging(module_id)) {
log_formatted(FLOG, lp_log_format(module_id), s_or_r,
file, initial_stats, iflags, hlink);
} else if (log_format && !am_server) {
log_formatted(FNAME, log_format, s_or_r,
file, initial_stats, iflags, hlink);
if (code != FLOG && stdout_format && !am_server) {
log_formatted(FCLIENT, stdout_format, s_or_r,
file, NULL, initial_stats, iflags, hlink);
}
if (code != FCLIENT && logfile_format && *logfile_format) {
log_formatted(FLOG, logfile_format, s_or_r,
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
|| log_format_has_i > 1 || (verbose > 1 && log_format_has_i));
|| stdout_format_has_i > 1 || (verbose > 1 && stdout_format_has_i));
int local_change = iflags & ITEM_LOCAL_CHANGE && significant_flags;
if (am_server) {
if (am_daemon && !dry_run && see_item)
log_item(file, &stats, iflags, buf);
if (logfile_name && !dry_run && see_item
&& (significant_flags || logfile_format_has_i))
log_item(FLOG, file, &stats, iflags, buf);
} else if (see_item || local_change || *buf
|| (S_ISDIR(file->mode) && significant_flags))
log_item(file, &stats, iflags, buf);
|| (S_ISDIR(file->mode) && significant_flags)) {
enum logcode code = significant_flags || logfile_format_has_i ? FINFO : FCLIENT;
log_item(code, file, &stats, iflags, buf);
}
}
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 && !log_format)
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 = log_format_has_o_or_i ? log_format : "deleting %n";
log_formatted(FCLIENT, fmt, "del.", &file, &stats,
fmt = stdout_format_has_o_or_i ? stdout_format : "deleting %n";
log_formatted(FCLIENT, fmt, "del.", &x.file, fname, &stats,
ITEM_DELETED, NULL);
}
if (!am_daemon || dry_run || !lp_transfer_logging(module_id))
if (!logfile_name || dry_run || !logfile_format)
return;
fmt = daemon_log_format_has_o_or_i ? lp_log_format(module_id) : "deleting %n";
log_formatted(FLOG, fmt, "del.", &file, &stats, ITEM_DELETED, NULL);
fmt = logfile_format_has_o_or_i ? logfile_format : "deleting %n";
log_formatted(FLOG, fmt, "del.", &x.file, fname, &stats, ITEM_DELETED, NULL);
}
/*
@@ -760,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);
@@ -769,11 +801,11 @@ void log_exit(int code, const char *file, int line)
/* VANISHED is not an error, only a warning */
if (code == RERR_VANISHED) {
rprintf(FINFO, "rsync warning: %s (code %d) at %s(%d) [%s]\n",
name, code, file, line, who_am_i());
rprintf(FINFO, "rsync warning: %s (code %d) at %s(%d) [%s=%s]\n",
name, code, file, line, who_am_i(), RSYNC_VERSION);
} else {
rprintf(FERROR, "rsync error: %s (code %d) at %s(%d) [%s]\n",
name, code, file, line, who_am_i());
rprintf(FERROR, "rsync error: %s (code %d) at %s(%d) [%s=%s]\n",
name, code, file, line, who_am_i(), RSYNC_VERSION);
}
}
}

656
main.c
View File

File diff suppressed because it is too large Load Diff

85
match.c
View File

@@ -1,21 +1,23 @@
/*
Copyright (C) Andrew Tridgell 1996
Copyright (C) Paul Mackerras 1996
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
* Block matching used by the file-transfer code.
*
* Copyright (C) 1996 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* 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 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"
@@ -82,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) {
@@ -118,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;
@@ -251,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;
@@ -301,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;
@@ -311,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;
}
@@ -336,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");
@@ -348,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",

View File

@@ -54,15 +54,14 @@ BEGIN {
printf "int %s(void);\n", a[2]
}
/^static|^extern/ || !/^[a-zA-Z]/ || /[;]/ {
/^static|^extern/ || /[;]/ {
next;
}
!/^OFF_T|^size_t|^off_t|^pid_t|^unsigned|^mode_t|^DIR|^user|^int|^char|^uint|^uchar|^short|^struct|^BOOL|^void|^time|^const|^RETSIGTYPE/ {
!/^[A-Za-z][A-Za-z0-9_]* / {
next;
}
/[(].*[)][ \t]*$/ {
printf "%s;\n",$0;
next;
@@ -73,4 +72,3 @@ BEGIN {
printf "%s\n",$0;
next;
}

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;
}

747
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.7pre3
Version: 3.0.0pre2
Release: 1
Group: Applications/Internet
Source: ftp://rsync.samba.org/pub/rsync/rsync-%{version}.tar.gz

View File

@@ -18,6 +18,7 @@ use Date::Format;
our $unpacked = $ENV{HOME} . '/release/nightly';
# Where the local copy of /home/ftp/pub/rsync/nightly should be updated.
our $nightly = $ENV{HOME} . '/samba-rsync-ftp/nightly';
our $nightly_symlink = "$nightly/rsync-HEAD.tar.gz";
our($cvs_update, $make_tar, $upload, $help_opt);
&Getopt::Long::Configure('bundling');
@@ -69,6 +70,8 @@ if ($make_tar) {
}
close TAR;
rename($name, $unpacked) or die $!;
unlink($nightly_symlink);
symlink("$name.tar.gz", $nightly_symlink);
}
chdir($nightly) or die $!;
@@ -93,12 +96,23 @@ 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) {
$ENV{RSYNC_PARTIAL_DIR} = ''; # The rsync on samba.org is OLD.
system "rsync -aviHP --delete . samba.org:/home/ftp/pub/rsync/nightly";
my $opt = '';
if (defined $ENV{RSYNC_PARTIAL_DIR}) {
$opt = " -f 'R $ENV{RSYNC_PARTIAL_DIR}'";
}
system "rsync$opt -aviHP --delete-after . samba.org:/home/ftp/pub/rsync/nightly";
}
exit;

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
@@ -140,6 +147,7 @@ About to:
EOT
print "<Press Enter to continue> ";
$_ = <STDIN>;
my $f_opt = /f/ ? ' -f' : '';
print $break;
system "./prepare-source && touch proto.h";
@@ -147,38 +155,44 @@ 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 $!;
undef $/; $_ = <IN>; $/ = "\n";
close IN;
if ($fn =~ /configure/) {
s/^RSYNC_VERSION.*/RSYNC_VERSION=$version/m;
s/^RSYNC_VERSION=.*/RSYNC_VERSION=$version/m;
} elsif ($fn =~ /\.spec/) {
s/^(Version:) .*/$1 $version/m;
s/^(Release:) .*/$1 $release/m;
} elsif ($fn =~ /\.yo/) {
s/^(manpage\([^)]+\)\(\d+\)\()[^)]+(\).*)/$1$today$2/m;
s/^(This man ?page is current for version) \S+ (of rsync)/$1 $version $2/m;
} 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";
} else {
s/^(NEWS for rsync \Q$version\E) \(UNRELEASED\)\s*$/$1 ($today)\n/m;
s/^\t\S\S\s\S\S\S\s\d\d\d\d(\t\Q$version\E)/\t$ztoday$1/m;
die "Unrecognized file in \@tweak_files: $fn\n";
}
open(OUT, '>', $fn) or die $!;
print OUT $_;
close OUT;
}
system "yodl2man -o rsync.1 rsync.yo";
system "yodl2man -o rsyncd.conf.5 rsyncd.conf.yo";
#system "perl -pi -e \"s/\\\\\\'/\\\\&'/g\" rsync.1 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/";
print "\n", $break, $note, $break;
system "patches/verify-patches -un -an";
system "patches/verify-patches -n -an$f_opt";
print $break;
system "cvs -q diff | egrep -v '^(===============|RCS file: |retrieving revision |Index: )' | less -p '^diff .*'";
@@ -204,18 +218,21 @@ if (!/skip/i) {
system "patches/verify-patches -pun -an";
}
my $tar_file = "$dest/rsync-$version.tar.gz";
my $diff_file = "$dest/rsync-$lastversion-$version.diffs.gz";
my $tar_name = "rsync-$version.tar.gz";
my $diff_name = "rsync-$lastversion-$version.diffs.gz";
my $tar_file = "$dest/$tar_name";
my $diff_file = "$dest/$diff_name";
print $break, <<EOT;
About to do the following in the samba-rsync-ftp dir:
- move the old tar/diff files into the appropriate old-* dirs
- hard-link moved tar/diff files to old files on samba.org$skipping
- create release tar, "$tar_file"
- create release diffs, "$diff_file"
- hard-link the moved tar/diff files on samba.org$skipping
- create release tar, "$tar_name"
- create release diffs, "$diff_name"
- update README, *NEWS, TODO, and cvs.log
- update rsync*.html man pages
- gpg-sign the release files$skipping
EOT
print "<Press Enter to continue> ";
@@ -247,19 +264,22 @@ if ($diffdir ne $dest) {
push(@moved_files, $fn);
}
foreach my $fn (glob('rsync*pre*.diffs.gz*')) {
unlink($fn);
}
foreach my $fn (glob('rsync*.diffs.gz*')) {
next if $fn =~ /^rsync.*pre/;
link($fn, "old-patches/$fn") or die $!;
push(@moved_files, $fn);
}
}
# Optimize our future upload (in the absence of --detect-renamed) by
# uploading the above hard-linked files that we are about to delete.
# using rsync to hard-link the above files on samba.org.
if ($live) {
system "rsync -avHC --include='rsync*.gz*' --include='old-*/' --exclude='*' . samba.org:/home/ftp/pub/rsync";
system "rsync -avHOC --include='rsync*.gz*' --include='old-*/' --exclude='*' . samba.org:/home/ftp/pub/rsync";
}
foreach (@moved_files, glob("rsync*pre*.diffs.gz*")) {
foreach (@moved_files) {
unlink($_);
}
@@ -268,7 +288,7 @@ if ($diffdir ne $dest) {
print "Creating $tar_file ...\n";
system "fakeroot tar czf $tar_file rsync-$version";
open(TAR, '|-', "fakeroot tar --files-from=- --no-recursion --mode=g-w -czf $tar_file rsync-$version") or die $!;
open(TAR, '|-', "fakeroot tar --files-from=- --no-recursion --mode=g+w -czf $tar_file rsync-$version") or die $!;
foreach (@files) {
print TAR "rsync-$version/$_\n";
}
@@ -280,7 +300,7 @@ system "tar xzf $tar_file; tar xzf $diffdir/rsync-$lastversion.tar.gz";
## TWEAK THE VERSIONS AS DESIRED HERE ##
#mkdir("rsync-$lastversion/support", 0755) or die $!;
#rename("rsync-$lastversion/rsyncstats", "rsync-$lastversion/support/rsyncstats");
unlink("rsync-$lastversion/.ignore");
#unlink("rsync-$lastversion/.ignore");
## END ##
system "diff -urN --exclude=patches rsync-$lastversion rsync-$version| gzip -9 >$diff_file";
@@ -297,12 +317,12 @@ system "rm -rf rsync-*";
if ($live) {
chdir($dest) or die $!;
system "gpg -ba rsync-$version.tar.gz";
system "gpg -ba rsync-$lastversion-$version.diffs.gz";
}
print $break, <<EOT;
system "gpg -ba $tar_name; gpg -ba $diff_name";
print $break, <<EOT;
All done. Remember to announce the release on *BOTH*
rsync-announce\@lists.samba.org and rsync\@lists.samba.org!
EOT
} else {
print $break, "All done.\n";
}

View File

@@ -1,10 +1,10 @@
/*
This modules is based on the params.c module from Samba, written by Karl Auer
and much modifed by Christopher Hertel.
/* This modules is based on the params.c module from Samba, written by Karl Auer
and much modifed by Christopher Hertel. */
/*
* 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,
@@ -12,11 +12,11 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* -------------------------------------------------------------------------- **
* You should have received a copy of the GNU General Public License along
* with this program; if not, visit the http://fsf.org website.
*/
/* -------------------------------------------------------------------------- **
*
* Module name: params
*
@@ -74,6 +74,7 @@
*/
#include "rsync.h"
#include "ifuncs.h"
/* -------------------------------------------------------------------------- **
* Constants...
@@ -164,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 );
@@ -386,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 );
}
@@ -491,7 +492,7 @@ static FILE *OpenConfFile( char *FileName )
OpenedFile = fopen( FileName, "r" );
if( NULL == OpenedFile )
{
rsyserr(FERROR, errno, "rsync: unable to open configuration file \"%s\"",
rsyserr(FERROR, errno, "unable to open configuration file \"%s\"",
FileName);
}

32
pipe.c
View File

@@ -1,12 +1,14 @@
/* -*- c-file-style: "linux" -*-
/*
* Routines used to setup various kinds of inter-process pipes.
*
* Copyright (C) 1996-2000 by Andrew Tridgell
* Copyright (C) Paul Mackerras 1996
* Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
* Copyright (C) 1996-2000 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
* 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,
@@ -14,9 +16,8 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* 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"
@@ -26,6 +27,7 @@ extern int am_server;
extern int blocking_io;
extern int filesfrom_fd;
extern mode_t orig_umask;
extern char *logfile_name;
extern struct chmod_mode_struct *chmod_modes;
/**
@@ -47,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");
@@ -143,9 +144,18 @@ 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);
}
/* Let the client side handle this. */
if (logfile_name) {
logfile_name = NULL;
logfile_close();
}
if (close(from_child_pipe[1]) < 0 ||
close(to_child_pipe[0]) < 0) {
rsyserr(FERROR, errno, "Failed to close");

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

@@ -1,13 +1,12 @@
#!/bin/sh
# Use autoconf, autoheader, yodl, etc. to ready the generated files
# in the release. This is typically used after applying a diff from
# "patches" directory in CVS.
# Use autoconf, autoheader, yodl, etc. to ready the generated files in the
# release. This is typically used after applying a diff from the "patches"
# directory in a CVS-checked-out version.
#
# NOTE: if you use a diff from the "patches" directory in a release
# tar, this is not needed (but doesn't hurt anything).
# NOTE: if you use a diff from the "patches" directory of a *release tar*
# (as opposed to from CVS), this is not needed (but doesn't hurt anything).
dir=`dirname $0`
if test x"$dir" = x -o x"$dir" = x.; then
make -f prepare-source.mak
else
make -C "$dir" -f prepare-source.mak
if test x"$dir" != x -a x"$dir" != x.; then
cd "$dir"
fi
make -f prepare-source.mak

View File

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

View File

@@ -1,12 +1,14 @@
/* -*- c-file-style: "linux" -*-
/*
* Routines to output progress information during a file transfer.
*
* Copyright (C) 1996-2000 by Andrew Tridgell
* Copyright (C) Paul Mackerras 1996
* Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
* Copyright (C) 1996-2000 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
* 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,
@@ -14,9 +16,8 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* 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"
@@ -58,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. */
@@ -92,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",
@@ -102,10 +107,9 @@ static void rprint_progress(OFF_T ofs, OFF_T size, struct timeval *now,
stats.num_files - stats.current_file_index - 1,
stats.num_files);
} else
strcpy(eol, "\r");
rprintf(FINFO, "%12s %3d%% %7.2f%s %4d:%02d:%02d%s",
human_num(ofs), pct, rate, units,
remain_h, remain_m, remain_s, eol);
strlcpy(eol, "\r", sizeof 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

@@ -1,33 +1,35 @@
/* -*- c-file-style: "linux" -*-
Copyright (C) 1996-2000 by Andrew Tridgell
Copyright (C) Paul Mackerras 1996
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* Routines only used by the receiving process.
*
* Copyright (C) 1996-2000 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* 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 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"
extern int verbose;
extern int dry_run;
extern int do_xfers;
extern int am_daemon;
extern int am_server;
extern int do_progress;
extern int inc_recurse;
extern int log_before_transfer;
extern int log_format_has_i;
extern int daemon_log_format_has_i;
extern int stdout_format_has_i;
extern int logfile_format_has_i;
extern int csum_length;
extern int read_batch;
extern int write_batch;
@@ -36,27 +38,29 @@ 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;
extern int remove_sent_files;
extern int remove_source_files;
extern int append_mode;
extern int sparse_files;
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 *log_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
@@ -79,17 +83,15 @@ static int phase = 0;
* 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;
int length = 0;
int maxname;
if (tmpdir) {
/* Note: this can't overflow, so the return value is safe */
length = strlcpy(fnametmp, tmpdir, MAXPATHLEN - 2);
fnametmp[length++] = '/';
fnametmp[length] = '\0'; /* always NULL terminated */
}
if ((f = strrchr(fname, '/')) != NULL) {
@@ -102,8 +104,9 @@ static int get_tmpname(char *fnametmp, char *fname)
} else
f = fname;
fnametmp[length++] = '.';
fnametmp[length] = '\0'; /* always NULL terminated */
/* The maxname value is bufsize, and includes space for the '\0'.
* (Note that NAME_MAX get -8 for the leading '.' above.) */
maxname = MIN(MAXPATHLEN - 7 - length, NAME_MAX - 8);
if (maxname < 1) {
@@ -112,21 +115,23 @@ static int get_tmpname(char *fnametmp, char *fname)
return 0;
}
strlcpy(fnametmp + length, f, maxname);
strcat(fnametmp + length, ".XXXXXX");
added = strlcpy(fnametmp + length, f, maxname);
if (added >= maxname)
added = maxname - 1;
memcpy(fnametmp + length + added, ".XXXXXX", 8);
return 1;
}
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;
@@ -147,28 +152,30 @@ 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 (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);
}
}
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 (fd != -1 && do_lseek(fd, offset, SEEK_SET) != offset) {
rsyserr(FERROR, errno, "lseek failed on %s",
full_fname(fname));
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);
exit_cleanup(RERR_FILEIO);
}
}
@@ -215,15 +222,17 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
sum_update(map, len);
}
if (inplace) {
if (updating_basis) {
if (offset == offset2 && fd != -1) {
OFF_T pos;
if (flush_write_file(fd) < 0)
goto report_write_error;
offset += len;
if (do_lseek(fd, len, SEEK_CUR) != offset) {
if ((pos = do_lseek(fd, len, SEEK_CUR)) != offset) {
rsyserr(FERROR, errno,
"lseek failed on %s",
full_fname(fname));
"lseek of %s returned %.0f, not %.0f",
full_fname(fname),
(double)pos, (double)offset);
exit_cleanup(RERR_FILEIO);
}
continue;
@@ -252,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;
}
@@ -271,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",
@@ -293,110 +302,119 @@ static void handle_delayed_updates(struct file_list *flist, char *local_name)
"rename failed for %s (from %s)",
full_fname(fname), partialptr);
} else {
if (remove_sent_files
|| (preserve_hard_links
&& file->link_u.links)) {
SIVAL(numbuf, 0, i);
send_msg(MSG_SUCCESS,numbuf,4);
}
if (remove_source_files
|| (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_daemon ? daemon_log_format_has_i
: !am_server && log_format_has_i;
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) {
@@ -406,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
@@ -418,29 +458,30 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
}
if (!do_xfers) { /* log the transfer */
if (!am_server && log_format)
log_item(file, &stats, iflags, NULL);
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(file, &stats, iflags, NULL);
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;
@@ -457,6 +498,7 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
fnamecmp = get_backup_name(fname);
break;
case FNAMECMP_FUZZY:
updating_basis = 0;
if (file->dirname) {
pathjoin(fnamecmpbuf, MAXPATHLEN,
file->dirname, xname);
@@ -465,6 +507,7 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
fnamecmp = xname;
break;
default:
updating_basis = 0;
if (fnamecmp_type >= basis_dir_cnt) {
rprintf(FERROR,
"invalid basis_dir index: %d.\n",
@@ -482,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)
@@ -511,11 +554,16 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
}
}
if (fd1 != -1 && do_fstat(fd1,&st) != 0) {
if (fd1 == -1) {
st.st_mode = 0;
st.st_size = 0;
} 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;
}
@@ -527,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;
}
@@ -541,25 +591,38 @@ 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 file "inplace" */
/* We now check to see if we are writing the file "inplace" */
if (inplace) {
fd2 = do_open(fname, O_WRONLY|O_CREAT, 0600);
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;
}
@@ -583,28 +646,28 @@ 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;
}
if (keep_partial)
cleanup_set(fnametmp, partialptr, file, fd1, fd2);
cleanup_set(fnametmp, partialptr, file, fd1, fd2);
}
/* log the transfer */
if (log_before_transfer)
log_item(file, &initial_stats, iflags, NULL);
log_item(FCLIENT, file, &initial_stats, iflags, NULL);
else if (!am_server && verbose && do_progress)
rprintf(FINFO, "%s\n", fname);
/* recv file data */
recv_ok = receive_data(f_in, fnamecmp, fd1, st.st_size,
fname, fd2, file->length);
fname, fd2, F_LENGTH(file));
if (!log_before_transfer)
log_item(file, &initial_stats, iflags, NULL);
log_item(log_code, file, &initial_stats, iflags, NULL);
if (fd1 != -1)
close(fd1);
@@ -615,20 +678,25 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
}
if ((recv_ok && (!delay_updates || !partialptr)) || inplace) {
if (partialptr == fname || *partial_dir == '/')
partialptr = NULL;
finish_transfer(fname, fnametmp, partialptr,
file, recv_ok, 1);
char *temp_copy_name;
if (partialptr == fname)
partialptr = temp_copy_name = NULL;
else if (*partial_dir == '/')
temp_copy_name = NULL;
else
temp_copy_name = partialptr;
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 {
@@ -639,13 +707,11 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
cleanup_disable();
if (recv_ok > 0) {
if (remove_sent_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)
@@ -665,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");

460
rsync.c
View File

@@ -1,29 +1,26 @@
/*
Copyright (C) Andrew Tridgell 1996
Copyright (C) Paul Mackerras 1996
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* this file contains code used by more than one part of the rsync
process */
* Routines common to more than one of the rsync processes.
*
* Copyright (C) 1996 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* 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 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"
#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,44 +29,57 @@
extern int verbose;
extern int dry_run;
extern int daemon_log_format_has_i;
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);
@@ -87,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
*/
@@ -101,70 +312,96 @@ 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 cur_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,
* possibly tweaked by the --executability option. */
if (exists) {
new_mode = (flist_mode & ~CHMOD_BITS) | (stat_mode & CHMOD_BITS);
if (preserve_executability && S_ISREG(flist_mode)) {
/* If the source file is executable, grant execute
* rights to everyone who can read, but ONLY if the
* file isn't already executable. */
if (!(flist_mode & 0111))
cur_mode &= ~0111;
else if (!(cur_mode & 0111))
cur_mode |= (cur_mode & 0444) >> 2;
new_mode &= ~0111;
else if (!(stat_mode & 0111))
new_mode |= (new_mode & 0444) >> 2;
}
} else
cur_mode = flist_mode & ACCESSPERMS & ~orig_umask;
if (daemon_chmod_modes && !S_ISLNK(flist_mode))
cur_mode = tweak_mode(cur_mode, daemon_chmod_modes);
return (flist_mode & ~CHMOD_BITS) | (cur_mode & CHMOD_BITS);
} else {
/* 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(file->mode)
&& st->st_mode & S_ISGID) {
/* We just created this directory and its setgid
* bit is on, so make sure it stays on. */
file->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
@@ -172,45 +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) != (file->mode & CHMOD_BITS)) {
int ret = do_chmod(fname, file->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;
@@ -218,12 +469,21 @@ int set_file_attrs(char *fname, struct file_struct *file, STRUCT_STAT *st,
#endif
if (verbose > 1 && flags & ATTRS_REPORT) {
enum logcode code = daemon_log_format_has_i || dry_run
? FCLIENT : FINFO;
if (updated)
rprintf(code, "%s\n", fname);
rprintf(FCLIENT, "%s\n", fname);
else
rprintf(code, "%s is uptodate\n", fname);
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;
}
@@ -246,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)
{
@@ -259,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 */
@@ -287,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) {
@@ -299,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)

475
rsync.h
View File

@@ -1,23 +1,22 @@
/*
Copyright (C) by Andrew Tridgell 1996, 2000
Copyright (C) Paul Mackerras 1996
Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
* Copyright (C) 1996, 2000 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
* 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 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.
*/
#define False 0
#define True 1
@@ -43,30 +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_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
@@ -89,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)
@@ -135,13 +161,15 @@
#define FNAMECMP_FUZZY 0x83
/* For use by the itemize_changes code */
#define ITEM_REPORT_ATIME (1<<0)
#define ITEM_REPORT_CHECKSUM (1<<1)
#define ITEM_REPORT_SIZE (1<<2)
#define ITEM_REPORT_TIME (1<<3)
#define ITEM_REPORT_PERMS (1<<4)
#define ITEM_REPORT_OWNER (1<<5)
#define ITEM_REPORT_GROUP (1<<6)
#define ITEM_REPORT_XATTRS (1<<7)
#define ITEM_REPORT_ACL (1<<7)
#define ITEM_REPORT_XATTR (1<<8)
#define ITEM_BASIS_TYPE_FOLLOWS (1<<11)
#define ITEM_XNAME_FOLLOWS (1<<12)
#define ITEM_IS_NEW (1<<13)
@@ -150,28 +178,38 @@
/* 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))
/* Log-message categories. Only FERROR and FINFO get sent over the socket.
* FLOG and FCLIENT are only used on the daemon side for custom logging,
* while FNAME is only used on the client side. */
enum logcode { FERROR=1, FINFO=2, FLOG=3, FCLIENT=4, FNAME=5, FSOCKERR=6 };
/* Log-message categories. Only FERROR and FINFO get sent over the socket,
* but FLOG and FSOCKERR can be sent over the receiver -> generator pipe.
* FLOG only goes to the log file, not the client; FCLIENT is the opposite. */
enum logcode { FNONE=0, FERROR=1, FINFO=2, FLOG=3, FCLIENT=4, FSOCKERR=5 };
/* Messages types that are sent over the message channel. The logcode
* values must all be present here with identical numbers. */
enum msgcode {
MSG_DATA=0, /* raw data on the multiplexed stream */
MSG_ERROR=FERROR, MSG_INFO=FINFO, /* 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"
@@ -202,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
@@ -311,6 +355,12 @@ enum msgcode {
#include <sys/sysmacros.h>
#endif
#ifdef MAKEDEV_TAKES_3_ARGS
#define MAKEDEV(devmajor,devminor) makedev(0,devmajor,devminor)
#else
#define MAKEDEV(devmajor,devminor) makedev(devmajor,devminor)
#endif
#ifdef HAVE_COMPAT_H
#include <compat.h>
#endif
@@ -319,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"
@@ -335,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
@@ -362,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
@@ -380,8 +471,8 @@ 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_OFF64_T == 8
# define int64 off64_t
#if SIZEOF_INT64_T == 8
# define int64 int64_t
# define SIZEOF_INT64 8
#elif SIZEOF_LONG == 8
# define int64 long
@@ -392,6 +483,9 @@ enum msgcode {
#elif SIZEOF_LONG_LONG == 8
# define int64 long long
# define SIZEOF_INT64 8
#elif SIZEOF_OFF64_T == 8
# define int64 off64_t
# define SIZEOF_INT64 8
#elif SIZEOF_OFF_T == 8
# define int64 off_t
# define SIZEOF_INT64 8
@@ -410,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
@@ -453,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
@@ -483,46 +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 {
int next;
int hlindex;
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
@@ -531,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)
@@ -605,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;
@@ -635,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;
@@ -643,23 +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, ...);
@@ -676,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
@@ -815,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 *, ...)
@@ -830,10 +1038,6 @@ void rsyserr(enum logcode, int, const char *, ...)
__attribute__((format (printf, 3, 4)))
;
#ifdef REPLACE_INET_NTOA
#define inet_ntoa rep_inet_ntoa
#endif
/* Make sure that the O_BINARY flag is defined. */
#ifndef O_BINARY
#define O_BINARY 0
@@ -850,6 +1054,9 @@ size_t strlcat(char *d, const char *s, size_t bufsize);
#ifndef WEXITSTATUS
#define WEXITSTATUS(stat) ((int)(((stat)>>8)&0xFF))
#endif
#ifndef WIFEXITED
#define WIFEXITED(stat) ((int)((stat)&0xFF) == 0)
#endif
#define exit_cleanup(code) _exit_cleanup(code, __FILE__, __LINE__)

749
rsync.yo
View File

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
mailto(rsync-bugs@samba.org)
manpage(rsyncd.conf)(5)(2 Mar 2006)()()
manpage(rsyncd.conf)(5)(11 Oct 2007)()()
manpagename(rsyncd.conf)(configuration file for rsync in daemon mode)
manpagesynopsis()
@@ -8,27 +8,27 @@ rsyncd.conf
manpagedescription()
The rsyncd.conf file is the runtime configuration file for rsync when
run as an rsync daemon.
run as an rsync daemon.
The rsyncd.conf file controls authentication, access, logging and
available modules.
manpagesection(FILE FORMAT)
The file consists of modules and parameters. A module begins with the
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.
Only the first equals sign in a parameter is significant. Whitespace before
Only the first equals sign in a parameter is significant. Whitespace before
or after the first equals sign is discarded. Leading, trailing and internal
whitespace in module and parameter names is irrelevant. Leading and
trailing whitespace in a parameter value is discarded. Internal whitespace
within a parameter value is retained verbatim.
Any line beginning with a hash (#) is ignored, as are lines containing
Any line beginning with a hash (#) is ignored, as are lines containing
only whitespace.
Any line ending in a \ is "continued" on the next line in the
@@ -37,12 +37,12 @@ customary UNIX fashion.
The values following the equals sign in parameters are all either a string
(no quotes needed) or a boolean, which may be given as yes/no, 0/1 or
true/false. Case is not significant in boolean values, but is preserved
in string values.
in string values.
manpagesection(LAUNCHING THE RSYNC DAEMON)
The rsync daemon is launched by specifying the bf(--daemon) option to
rsync.
rsync.
The daemon must run with root privileges if you wish to use chroot, to
bind to a port numbered under 1024 (as is the default 873), or to set
@@ -58,7 +58,7 @@ When run via inetd you should add a line like this to /etc/services:
verb( rsync 873/tcp)
and a single line something like this to /etc/inetd.conf:
verb( rsync stream tcp nowait root /usr/bin/rsync rsyncd --daemon)
Replace "/usr/bin/rsync" with the path to where you have rsync installed on
@@ -67,12 +67,12 @@ reread its config file.
Note that you should bf(not) send the rsync daemon a HUP signal to force
it to reread the tt(rsyncd.conf) file. The file is re-read on each client
connection.
connection.
manpagesection(GLOBAL OPTIONS)
The first parameters in the file (before a [module] header) are the
global parameters.
global parameters.
You may also include any module parameters in the global part of the
config file in which case the supplied value will override the
@@ -84,24 +84,9 @@ dit(bf(motd file)) The "motd file" option allows you to specify a
usually contains site information and any legal notices. The default
is no motd file.
dit(bf(log file)) The "log file" option tells the rsync daemon to log
messages to that file rather than using syslog. This is particularly
useful on systems (such as AIX) where syslog() doesn't work for
chrooted programs. If the daemon fails to open to specified file, it
will fall back to using syslog and output an error about the failure.
(Note that a failure to open the specified log file used to be a fatal
error.)
dit(bf(pid file)) The "pid file" option tells the rsync daemon to write
its process ID to that file.
dit(bf(syslog facility)) The "syslog facility" option allows you to
specify the syslog facility name to use when logging messages from the
rsync daemon. You may use any standard syslog facility name which is
defined on your system. Common names are auth, authpriv, cron, daemon,
ftp, kern, lpr, mail, news, security, syslog, user, uucp, local0,
local1, local2, local3, local4, local5, local6 and local7. The default
is daemon.
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
@@ -114,7 +99,7 @@ being run by inetd, and is superseded by the bf(--address) command-line option.
dit(bf(socket options)) This option can provide endless fun for people
who like to tune their systems to the utmost degree. You can set all
sorts of socket options which may make transfers faster (or
slower!). Read the man page for the setsockopt() system call for
slower!). Read the man page for the code(setsockopt()) system call for
details on some of the options you may be able to set. By default no
special socket options are set. These settings are superseded by the
bf(--sockopts) command-line option.
@@ -142,7 +127,7 @@ for each module in tt(rsyncd.conf).
dit(bf(use chroot)) If "use chroot" is true, the rsync daemon will chroot
to the "path" before starting the file transfer with the client. This has
the advantage of extra protection against possible implementation security
holes, but it has the disadvantages of requiring super-user privileges,
holes, but it has the disadvantages of requiring super-user privileges,
of not being able to follow symbolic links that are either absolute or outside
of the new root path, and of complicating the preservation of usernames and groups
(see below). When "use chroot" is false, for security reasons,
@@ -154,7 +139,7 @@ The default for "use chroot" is true.
In order to preserve usernames and groupnames, rsync needs to be able to
use the standard library functions for looking up names and IDs (i.e.
getpwuid(), getgrgid(), getpwname(), and getgrnam()). This means a
code(getpwuid()), code(getgrgid()), code(getpwname()), and code(getgrnam())). This means a
process in the chroot namespace will need to have access to the resources
used by these library functions (traditionally /etc/passwd and
/etc/group). If these resources are not available, rsync will only be
@@ -165,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
@@ -177,9 +162,33 @@ 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
string, the rsync daemon will log messages to the indicated file rather
than using syslog. This is particularly useful on systems (such as AIX)
where code(syslog()) doesn't work for chrooted programs. The file is
opened before code(chroot()) is called, allowing it to be placed outside
the transfer. If this value is set on a per-module basis instead of
globally, the global log will still contain any authorization failures
or config-file error messages.
If the daemon fails to open to specified file, it will fall back to
using syslog and output an error about the failure. (Note that the
failure to open the specified log file used to be a fatal error.)
dit(bf(syslog facility)) The "syslog facility" option allows you to
specify the syslog facility name to use when logging messages from the
rsync daemon. You may use any standard syslog facility name which is
defined on your system. Common names are auth, authpriv, cron, daemon,
ftp, kern, lpr, mail, news, security, syslog, user, uucp, local0,
local1, local2, local3, local4, local5, local6 and local7. The default
is daemon. This setting has no effect if the "log file" setting is a
non-empty string (either set in the per-modules settings, or inherited
from the global settings).
dit(bf(max verbosity)) The "max verbosity" option allows you to control
the maximum amount of verbose information that you'll allow the daemon to
generate (since the information goes into the log file). The default is 1,
@@ -188,7 +197,7 @@ which allows the client to request one level of verbosity.
dit(bf(lock file)) The "lock file" option specifies the file to use to
support the "max connections" option. The rsync daemon uses record
locking on this file to ensure that the max connections limit is not
exceeded for the modules sharing the lock file.
exceeded for the modules sharing the lock file.
The default is tt(/var/run/rsyncd.lock).
dit(bf(read only)) The "read only" option determines whether clients
@@ -219,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
@@ -240,7 +254,7 @@ Because this exclude list is not passed to the client it only applies on
the daemon: that is, it excludes files received by a client when receiving
from a daemon and files deleted on a daemon when sending to a daemon, but
it doesn't exclude files from being deleted on a client when receiving
from a daemon.
from a daemon.
dit(bf(exclude from)) The "exclude from" option specifies a filename
on the daemon that contains exclude patterns, one per line.
@@ -294,7 +308,7 @@ usernames and passwords are stored in the file specified by the
connect without a password (this is called "anonymous rsync").
See also the "CONNECTING TO AN RSYNC DAEMON OVER A REMOTE SHELL
PROGRAM" section in rsync(1) for information on how handle an
PROGRAM" section in bf(rsync)(1) for information on how handle an
rsyncd.conf-level username that differs from the remote-shell-level
username when using a remote shell to connect to an rsync daemon.
@@ -306,13 +320,13 @@ username:password pairs separated by a single colon. Any line starting
with a hash (#) is considered a comment and is skipped. The passwords
can contain any characters but be warned that many operating systems
limit the length of passwords that can be typed at the client end, so
you may find that passwords longer than 8 characters don't work.
you may find that passwords longer than 8 characters don't work.
There is no default for the "secrets file" option, you must choose a name
(such as tt(/etc/rsyncd.secrets)). The file must normally not be readable
by "other"; see "strict modes".
dit(bf(strict modes)) The "strict modes" option determines whether or not
dit(bf(strict modes)) The "strict modes" option determines whether or not
the permissions on the secrets file will be checked. If "strict modes" is
true, then the secrets file must not be readable by any user ID other
than the one that the rsync daemon is running under. If "strict modes" is
@@ -326,7 +340,7 @@ connection is rejected.
Each pattern can be in one of five forms:
quote(itemize(
quote(itemization(
it() a dotted decimal IPv4 address of the form a.b.c.d, or an IPv6 address
of the form a:b:c::d:e:f. In this case the incoming machine's IP address
must match exactly.
@@ -357,7 +371,7 @@ You can also combine "hosts allow" with a separate "hosts deny"
option. If both options are specified then the "hosts allow" option s
checked first and a match results in the client being able to
connect. The "hosts deny" option is then checked and a match means
that the host is rejected. If the host does not match either the
that the host is rejected. If the host does not match either the
"hosts allow" or the "hosts deny" patterns then it is allowed to
connect.
@@ -376,14 +390,14 @@ phase of the transfer. Normally rsync skips the bf(--delete) step if any
I/O errors have occurred in order to prevent disastrous deletion due
to a temporary resource shortage or other I/O error. In some cases this
test is counter productive so you can use this option to turn off this
behavior.
behavior.
dit(bf(ignore nonreadable)) This tells the rsync daemon to completely
ignore files that are not readable by the user. This is useful for
public archives that may have some non-readable files among the
directories, and the sysadmin doesn't want those files to be seen at all.
dit(bf(transfer logging)) The "transfer logging" option enables per-file
dit(bf(transfer logging)) The "transfer logging" option enables per-file
logging of downloads and uploads in a format somewhat similar to that
used by ftp daemons. The daemon always logs the transfer at the end, so
if a transfer is aborted, no mention will be made in the log file.
@@ -395,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.
@@ -405,9 +419,9 @@ rsyncstats.)
The single-character escapes that are understood are as follows:
quote(itemize(
quote(itemization(
it() %a the remote IP address
it() %b the number of bytes actually transferred
it() %b the number of bytes actually transferred
it() %B the permission bits of the file (e.g. rwxrwxrwt)
it() %c the checksum bytes received for this file (only when sending)
it() %f the filename (long form on sender; no trailing "/")
@@ -459,21 +473,27 @@ without the former, instead refuse "delete-*" -- that refuses all the
delete modes without affecting bf(--remove-sent-files).
When an option is refused, the daemon prints an error message and exits.
To prevent all compression, you can use "dont compress = *" (see below)
To prevent all compression when serving files,
you can use "dont compress = *" (see below)
instead of "refuse options = compress" to avoid returning an error to a
client that requests compression.
dit(bf(dont compress)) The "dont compress" option allows you to select
filenames based on wildcard patterns that should not be compressed
during transfer. Compression is expensive in terms of CPU usage so it
when pulling files from the daemon (no analogous option exists to
govern the pushing of files to a daemon).
Compression is expensive in terms of CPU usage, so it
is usually good to not try to compress files that won't compress well,
such as already compressed files.
such as already compressed files.
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
@@ -482,22 +502,25 @@ transfer is aborted before it begins.
The following environment variables will be set, though some are
specific to the pre-xfer or the post-xfer environment:
quote(itemize(
quote(itemization(
it() bf(RSYNC_MODULE_NAME): The name of the module being accessed.
it() bf(RSYNC_MODULE_PATH): The path configured for the module.
it() bf(RSYNC_HOST_ADDR): The accessing host's IP address.
it() bf(RSYNC_HOST_NAME): The accessing host's name.
it() bf(RSYNC_USER_NAME): The accessing user's name (empty if no user).
it() bf(RSYNC_PID): A unique number for this transfer.
it() bf(RSYNC_REQUEST): (pre-xfer only) The module/path info specified
by the user (note that the user can specify multiple source files,
so the request can be something like "mod/path1 mod/path2", etc.).
it() bf(RSYNC_ARG#): (pre-xfer only) The pre-request arguments are set
in these numbered values. RSYNC_ARG0 is always "rsyncd", and the last
value contains a single period.
it() bf(RSYNC_EXIT_STATUS): (post-xfer only) rsync's exit value. This will be 0 for a
successful run, a positive value for an error that rsync returned
(e.g. 23=partial xfer), or a -1 if rsync failed to exit properly.
it() bf(RSYNC_RAW_STATUS): (post-xfer only) the raw exit value from waitpid().
it() bf(RSYNC_EXIT_STATUS): (post-xfer only) the server side's exit value.
This will be 0 for a successful run, a positive value for an error that the
server generated, or a -1 if rsync failed to exit properly. Note that an
error that occurs on the client side does not currently get sent to the
server side, so this is not the final exit status for the whole transfer.
it() bf(RSYNC_RAW_STATUS): (post-xfer only) the raw exit value from code(waitpid()).
))
Even though the commands can be associated with a particular module, they
@@ -555,7 +578,7 @@ pid file = /var/run/rsyncd.pid
[rsyncftp]
path = /var/ftp/pub/rsync
comment = rsync ftp area (approx 6 MB)
[sambawww]
path = /public_html/samba
comment = Samba WWW pages (approx 240 MB)
@@ -580,7 +603,7 @@ manpagefiles()
manpageseealso()
rsync(1)
bf(rsync)(1)
manpagediagnostics()
@@ -591,7 +614,7 @@ url(http://rsync.samba.org/)(http://rsync.samba.org/)
manpagesection(VERSION)
This man page is current for version 2.6.7pre3 of rsync.
This man page is current for version 3.0.0pre2 of rsync.
manpagesection(CREDITS)
@@ -613,7 +636,7 @@ manpagesection(THANKS)
Thanks to Warren Stanley for his original idea and patch for the rsync
daemon. Thanks to Karsten Thygesen for his many suggestions and
documentation!
documentation!
manpageauthor()
@@ -621,4 +644,4 @@ rsync was written by Andrew Tridgell and Paul Mackerras.
Many people have later contributed to it.
Mailing lists for support and development are available at
url(http://lists.samba.org)(lists.samba.org)
url(http://lists.samba.org)(lists.samba.org)

View File

@@ -1,6 +1,7 @@
#! /bin/sh
# Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
# Copyright (C) 2003, 2004, 2005, 2006 Wayne Davison
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version
@@ -13,8 +14,7 @@
#
# You should have received a copy of the GNU Lesser General Public
# License along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
# rsync top-level test script -- this invokes all the other more
# detailed tests in order. This script can either be called by `make
@@ -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
@@ -138,9 +138,27 @@ if [ "x$loglevel" != x ] && [ "$loglevel" -gt 8 ]; then
fi
fi
POSIXLY_CORRECT=1
if test x"$TOOLDIR" = x; then
TOOLDIR=`pwd`
fi
srcdir=`dirname $0`
if test x"$srcdir" = x -o x"$srcdir" = x.; then
srcdir="$TOOLDIR"
fi
if test x"$rsync_bin" = x; then
rsync_bin="$TOOLDIR/rsync"
fi
# This allows the user to specify extra rsync options -- use carefully!
RSYNC="$rsync_bin $*"
#RSYNC="valgrind $rsync_bin $*"
export POSIXLY_CORRECT TOOLDIR srcdir RSYNC
echo "============================================================"
echo "$0 running in `pwd`"
echo " rsync_bin=$rsync_bin"
echo "$0 running in $TOOLDIR"
echo " rsync_bin=$RSYNC"
echo " srcdir=$srcdir"
if [ -f /usr/bin/whoami ]; then
@@ -163,13 +181,20 @@ else
echo " preserve_scratch=no"
fi
# We'll use setfacl if it's around and it supports the -k option.
if setfacl --help 2>/dev/null | grep ' -k,' >/dev/null; then
setfacl=setfacl
# 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
setfacl=true
# The "true" command runs successfully, but does nothing.
setfacl_nodef=true
fi
export setfacl_nodef
if [ ! -f "$rsync_bin" ]; then
echo "rsync_bin $rsync_bin is not a file" >&2
exit 2
@@ -180,32 +205,31 @@ if [ ! -d "$srcdir" ]; then
exit 2
fi
RSYNC="$rsync_bin"
#RSYNC="valgrind --tool=addrcheck $rsync_bin"
export rsync_bin RSYNC
skipped=0
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.
scratchbase="`pwd`"/testtmp
# 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 -k "$scratchdir"
$setfacl_nodef "$scratchdir" || true
chmod g-s "$scratchdir"
ln -s "$srcdir" "$scratchdir/src"
return 0
}
@@ -221,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

273
sender.c
View File

@@ -1,37 +1,42 @@
/*
Copyright (C) Andrew Tridgell 1996
Copyright (C) Paul Mackerras 1996
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
* Routines only used by the sending process.
*
* Copyright (C) 1996 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* 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 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"
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 log_format_has_i;
extern int daemon_log_format_has_i;
extern int stdout_format_has_i;
extern int logfile_format_has_i;
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_sent_files;
extern int remove_source_files;
extern int updating_basis_file;
extern int make_backups;
extern int do_progress;
@@ -39,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 *log_format;
extern struct file_list *cur_flist, *first_flist, *dir_flist;
/**
* @file
@@ -73,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;
@@ -119,29 +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];
/* The generator might tell us about symlinks we didn't send. */
if (!(file->flags & FLAG_SENT) && !S_ISLNK(file->mode))
if (!(flist = flist_for_ndx(ndx))) {
rprintf(FERROR,
"INTERNAL ERROR: unable to find flist for item %d\n",
ndx);
return;
if (file->dir.root) {
offset = stringjoin(fname, sizeof fname,
file->dir.root, "/", NULL);
}
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
offset = 0;
f_name(file, fname + offset);
if (remove_sent_files && do_unlink(fname) == 0 && verbose > 1)
rprintf(FINFO, "sender removed %s\n", fname + offset);
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);
@@ -149,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_daemon ? daemon_log_format_has_i
: !am_server && log_format_has_i;
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) {
@@ -270,18 +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 */
if (!am_server && log_format)
log_item(file, &stats, iflags, NULL);
write_ndx_and_attrs(f_out, i, iflags, fnamecmp_type,
xname, xlen);
log_item(FCLIENT, file, &stats, iflags, NULL);
write_ndx_and_attrs(f_out, ndx, iflags, fname, file,
fnamecmp_type, xname, xlen);
continue;
}
@@ -290,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);
@@ -309,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;
}
@@ -318,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) {
@@ -328,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(file, &initial_stats, iflags, NULL);
log_item(FCLIENT, file, &initial_stats, iflags, NULL);
else if (!am_server && verbose && do_progress)
rprintf(FINFO, "%s\n", fname2);
rprintf(FCLIENT, "%s\n", fname);
set_compression(fname);
@@ -350,8 +343,7 @@ void send_files(struct file_list *flist, int f_out, int f_in)
if (do_progress)
end_progress(st.st_size);
if (!log_before_transfer)
log_item(file, &initial_stats, iflags, NULL);
log_item(log_code, file, &initial_stats, iflags, NULL);
if (mbuf) {
j = unmap_file(mbuf);
@@ -367,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);
}

154
socket.c
View File

@@ -1,37 +1,34 @@
/* -*- c-file-style: "linux" -*-
rsync -- fast file replication program
Copyright (C) 1992-2001 by Andrew Tridgell <tridge@samba.org>
Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/**
* @file socket.c
*
/*
* Socket functions used in rsync.
*
* This file is now converted to use the new-style getaddrinfo()
* Copyright (C) 1992-2001 Andrew Tridgell <tridge@samba.org>
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
* 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 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.
*/
/* This file is now converted to use the new-style getaddrinfo()
* interface, which supports IPv6 but is also supported on recent
* IPv4-only machines. On systems that don't have that interface, we
* emulate it using the KAME implementation.
**/
* 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>
extern char *bind_address;
extern int default_af_hint;
@@ -58,13 +55,13 @@ static int establish_proxy_connection(int fd, char *host, int port,
proxy_user, ":", proxy_pass, NULL);
len = strlen(buffer);
if ((len*8 + 5) / 6 >= (int)sizeof authbuf) {
if ((len*8 + 5) / 6 >= (int)sizeof authbuf - 3) {
rprintf(FERROR,
"authentication information is too long\n");
return -1;
}
base64_encode(buffer, len, authbuf);
base64_encode(buffer, len, authbuf, 1);
authhdr = "\r\nProxy-Authorization: Basic ";
} else {
*authbuf = '\0';
@@ -98,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') {
@@ -304,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 " : "",
@@ -333,9 +366,9 @@ static int *open_socket_in(int type, int port, const char *bind_addr,
int af_hint)
{
int one = 1;
int s, *socks, maxs, i;
int s, *socks, maxs, i, ecnt;
struct addrinfo hints, *all_ai, *resp;
char portbuf[10];
char portbuf[10], **errmsgs;
int error;
memset(&hints, 0, sizeof hints);
@@ -353,17 +386,25 @@ static int *open_socket_in(int type, int port, const char *bind_addr,
/* Count max number of sockets we might open. */
for (maxs = 0, resp = all_ai; resp; resp = resp->ai_next, maxs++) {}
if (!(socks = new_array(int, maxs + 1)))
socks = new_array(int, maxs + 1);
errmsgs = new_array(char *, maxs);
if (!socks || !errmsgs)
out_of_memory("open_socket_in");
/* We may not be able to create the socket, if for example the
* machine knows about IPv6 in the C library, but not in the
* kernel. */
for (resp = all_ai, i = 0; resp; resp = resp->ai_next) {
for (resp = all_ai, i = ecnt = 0; resp; resp = resp->ai_next) {
s = socket(resp->ai_family, resp->ai_socktype,
resp->ai_protocol);
if (s == -1) {
int r = asprintf(&errmsgs[ecnt++],
"socket(%d,%d,%d) failed: %s\n",
(int)resp->ai_family, (int)resp->ai_socktype,
(int)resp->ai_protocol, strerror(errno));
if (r < 0)
out_of_memory("open_socket_in");
/* See if there's another address that will work... */
continue;
}
@@ -385,6 +426,11 @@ static int *open_socket_in(int type, int port, const char *bind_addr,
/* Now we've got a socket - we need to bind it. */
if (bind(s, resp->ai_addr, resp->ai_addrlen) < 0) {
/* Nope, try another */
int r = asprintf(&errmsgs[ecnt++],
"bind() failed: %s (address-family %d)\n",
strerror(errno), (int)resp->ai_family);
if (r < 0)
out_of_memory("open_socket_in");
close(s);
continue;
}
@@ -396,6 +442,15 @@ static int *open_socket_in(int type, int port, const char *bind_addr,
if (all_ai)
freeaddrinfo(all_ai);
/* Only output the socket()/bind() messages if we were totally
* 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]), 0);
free(errmsgs[s]);
}
free(errmsgs);
if (!i) {
rprintf(FERROR,
"unable to bind any inbound sockets on port %d\n",
@@ -648,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
@@ -55,7 +55,7 @@ EOT
foreach my $opt (sort keys %long_opt) {
my $val = $long_opt{$opt};
$val = 1 if $opt =~ /^max-/;
$val = 1 if $opt =~ /^(max-|min-)/;
$val = 3 if $opt eq 'files-from';
$val = '$ro ? -1 : ' . $val if $opt =~ /^remove-/;
print " '$opt' => $val,\n";

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) {

173
support/file-attr-restore Executable file
View File

@@ -0,0 +1,173 @@
#!/usr/bin/perl
# This script will parse the output of "find ARG [ARG...] -ls" and
# apply (at your discretion) the permissions, owner, and group info
# it reads onto any existing files and dirs (it doesn't try to affect
# symlinks). Run this with --help (-h) for a usage summary.
use strict;
use Getopt::Long;
our($p_opt, $o_opt, $g_opt, $map_file, $dry_run, $verbosity, $help_opt);
&Getopt::Long::Configure('bundling');
&usage if !&GetOptions(
'all|a' => sub { $p_opt = $o_opt = $g_opt = 1 },
'perms|p' => \$p_opt,
'owner|o' => \$o_opt,
'groups|g' => \$g_opt,
'map|m=s' => \$map_file,
'dry-run|n' => \$dry_run,
'help|h' => \$help_opt,
'verbose|v+' => \$verbosity,
) || $help_opt;
our(%uid_hash, %gid_hash);
$" = ', '; # How to join arrays referenced in double-quotes.
&parse_map_file($map_file) if defined $map_file;
my $detail_line = qr{
^ \s* \d+ \s+ # ignore inode
\d+ \s+ # ignore size
([-bcdlps]) # 1. File type
( [-r][-w][-xsS] # 2. user-permissions
[-r][-w][-xsS] # group-permissions
[-r][-w][-xtT] ) \s+ # other-permissions
\d+ \s+ # ignore number of links
(\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]+) $ # 5. name
}x;
while (<>) {
my($type, $perms, $owner, $group, $name) = /$detail_line/;
die "Invalid input line $.:\n$_" unless defined $name;
die "A filename is not properly escaped:\n$_" unless $name =~ /^[^"\\]*(\\(\d\d\d|\D)[^"\\]*)*$/;
my $fn = $name;
$fn =~ s/\\(\d+|.)/ eval "\"\\$1\"" /eg;
if ($type eq '-') {
undef $type unless -f $fn;
} elsif ($type eq 'd') {
undef $type unless -d $fn;
} elsif ($type eq 'b') {
undef $type unless -b $fn;
} elsif ($type eq 'c') {
undef $type unless -c $fn;
} elsif ($type eq 'p') {
undef $type unless -p $fn;
} elsif ($type eq 's') {
undef $type unless -S $fn;
} else {
if ($verbosity) {
if ($type eq 'l') {
$name =~ s/ -> .*//;
$type = 'symlink';
} else {
$type = "type '$type'";
}
print "Skipping $name ($type ignored)\n";
}
next;
}
if (!defined $type) {
my $reason = -e _ ? "types don't match" : 'missing';
print "Skipping $name ($reason)\n";
next;
}
my($cur_mode, $cur_uid, $cur_gid) = (stat(_))[2,4,5];
$cur_mode &= 07777;
my $highs = join('', $perms =~ /..(.)..(.)..(.)/);
$highs =~ tr/-rwxSTst/00001111/;
$perms =~ tr/-STrwxst/00011111/;
my $mode = $p_opt ? oct('0b' . $highs . $perms) : $cur_mode;
my $uid = $o_opt ? $uid_hash{$owner} : $cur_uid;
if (!defined $uid) {
if ($owner =~ /^\d+$/) {
$uid = $owner;
} else {
$uid = getpwnam($owner);
}
$uid_hash{$owner} = $uid;
}
my $gid = $g_opt ? $gid_hash{$group} : $cur_gid;
if (!defined $gid) {
if ($group =~ /^\d+$/) {
$gid = $group;
} else {
$gid = getgrnam($group);
}
$gid_hash{$group} = $gid;
}
my @changes;
if ($mode != $cur_mode) {
push(@changes, 'permissions');
if (!$dry_run && !chmod($mode, $fn)) {
warn "chmod($mode, \"$name\") failed: $!\n";
}
}
if ($uid != $cur_uid || $gid != $cur_gid) {
push(@changes, 'owner') if $uid != $cur_uid;
push(@changes, 'group') if $gid != $cur_gid;
if (!$dry_run) {
if (!chown($uid, $gid, $fn)) {
warn "chown($uid, $gid, \"$name\") failed: $!\n";
}
if (($mode & 06000) && !chmod($mode, $fn)) {
warn "post-chown chmod($mode, \"$name\") failed: $!\n";
}
}
}
if (@changes) {
print "$name: changed @changes\n";
} elsif ($verbosity) {
print "$name: OK\n";
}
}
exit;
sub parse_map_file
{
my($fn) = @_;
open(IN, $fn) or die "Unable to open $fn: $!\n";
while (<IN>) {
if (/^user\s+(\S+)\s+(\S+)/) {
$uid_hash{$1} = $2;
} elsif (/^group\s+(\S+)\s+(\S+)/) {
$gid_hash{$1} = $2;
} else {
die "Invalid line #$. in mapfile `$fn':\n$_";
}
}
close IN;
}
sub usage
{
die <<EOT;
Usage: file-attr-restore [OPTIONS] FILE [FILE...]
-a, --all Restore all the attributes (-pog)
-p, --perms Restore the permissions
-o, --owner Restore the ownership
-g, --groups Restore the group
-m, --map=FILE Read user/group mappings from FILE
-n, --dry-run Don't actually make the changes
-v, --verbose Increase verbosity
-h, --help Show this help text
The FILE arg(s) should have been created by running the "find"
program with "-ls" as the output specifier.
The input file for the --map option must be in this format:
user FROM TO
group FROM TO
The "FROM" should be an user/group mentioned in the input, and the TO
should be either a uid/gid number, or a local user/group name.
EOT
}

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,19 +48,21 @@ 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 = 'CDHIKLORSWbcdglnoprtuvxz'; # 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:
# 0 = the option has no arg; 1 = the arg doesn't need any checking; 2 = only
# check the arg when receiving; and 3 = always check the arg.
our %long_opt = (
'append' => 0,
'backup-dir' => 2,
'bwlimit' => 1,
'checksum-seed' => 1,
'compare-dest' => 2,
'compress-level' => 1,
'copy-dest' => 2,
'copy-unsafe-links' => 0,
'daemon' => 0,
@@ -68,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,
@@ -75,6 +78,7 @@ our %long_opt = (
'force' => 0,
'from0' => 0,
'fuzzy' => 0,
'iconv' => 1,
'ignore-errors' => 0,
'ignore-existing' => 0,
'inplace' => 0,
@@ -83,19 +87,27 @@ our %long_opt = (
'log-format' => 1,
'max-delete' => 1,
'max-size' => 1,
'min-size' => 1,
'modify-window' => 1,
'no-i-r' => 0,
'no-implied-dirs' => 0,
'no-r' => 0,
'no-relative' => 0,
'no-specials' => 0,
'numeric-ids' => 0,
'only-write-batch' => 1,
'partial' => 0,
'partial-dir' => 2,
'remove-sent-files' => $ro ? -1 : 0,
'remove-source-files' => $ro ? -1 : 0,
'safe-links' => 0,
'sender' => 0,
'server' => 0,
'size-only' => 0,
'skip-compress' => 1,
'specials' => 0,
'suffix' => 1,
'super' => 0,
'temp-dir' => 2,
'timeout' => 1,
);
@@ -127,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

@@ -52,9 +52,22 @@ if ($only_section) {
line: while (<LOG>) {
my $syslog_prefix = '\w\w\w +\d+ \d\d:\d\d:\d\d \S+ rsyncd';
my $rsyncd_prefix = '\d\d\d\d/\d\d/\d\d \d\d:\d\d:\d\d ';
next unless ($day,$time,$op,$host,$module,$file,$bytes)
= m#^ (\d+/\d\d/\d\d)\s+(\d\d:\d\d:\d\d)\s+\[\d+\]\s+(send|recv|[<>]f\S+)\s+
(\S+)\s+\[\d+\.\d+\.\d+\.\d+\]\s+(\S+)\s+\(\S*\)\s+(.*)\s+(\d+) $ #x;
= m{^
( \w\w\w\s+\d+ | \d+/\d\d/\d\d ) \s+ # day
(\d\d:\d\d:\d\d) \s+ # time
[^[]* \[\d+\]:? \s+ # pid (ignored)
(send|recv|[<>]f\S+) \s+ # op (%o or %i)
(\S+) \s+ # host
\[\d+\.\d+\.\d+\.\d+\] \s+ # IP (ignored)
(\S+) \s+ # module
\(\S*\) \s+ # user (ignored)
(.*) \s+ # file name
(\d+) # file length in bytes
$ }x;
# TODO actually divide the data by into send/recv categories
if ($op =~ /^>/) {

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

@@ -1,28 +1,24 @@
/*
Copyright (C) Andrew Tridgell 1998
Copyright (C) 2002 by Martin Pool
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/**
* @file syscall.c
*
/*
* Syscall wrappers to ensure that nothing gets done in dry_run mode
* and to handle system peculiarities.
**/
*
* Copyright (C) 1998 Andrew Tridgell
* Copyright (C) 2002 Martin Pool
* 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 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"
@@ -31,6 +27,7 @@
#endif
extern int dry_run;
extern int am_root;
extern int read_only;
extern int list_only;
extern int preserve_perms;
@@ -78,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);
@@ -90,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)
@@ -168,10 +175,10 @@ void trim_trailing_slashes(char *name)
/* Some BSD systems cannot make a directory if the name
* contains a trailing slash.
* <http://www.opensource.apple.com/bugs/X/BSD%20Kernel/2734739.html> */
/* Don't change empty string; and also we can't improve on
* "/" */
l = strlen(name);
while (l > 1) {
if (name[--l] != '/')
@@ -184,7 +191,7 @@ int do_mkdir(char *fname, mode_t mode)
{
if (dry_run) return 0;
RETURN_ERROR_IF_RO_OR_LO;
trim_trailing_slashes(fname);
trim_trailing_slashes(fname);
return mkdir(fname, mode);
}

View File

@@ -1,37 +1,34 @@
/* -*- c-file-style: "linux" -*-
*
* Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
*
* This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "rsync.h"
/**
* @file t_stub.c
*
/*
* This file contains really simple implementations for rsync global
* functions, so that module test harnesses can run standalone.
**/
*
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
* 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 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"
int modify_window = 0;
int module_id = -1;
int relative_paths = 0;
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, ...)
@@ -67,18 +64,22 @@ 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;
return NULL;
}
BOOL lp_use_chroot(UNUSED(int mod))
{
return 0;
return 0;
}
char *lp_path(UNUSED(int mod))
const char *who_am_i(void)
{
return NULL;
return "tester";
}

View File

@@ -1,36 +1,35 @@
/*
* Copyright (C) 2002 by Martin Pool
*
* Test harness for unsafe_symlink(). Not linked into rsync itself.
*
* Copyright (C) 2002 Martin Pool
* 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,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, visit the http://fsf.org website.
*/
/**
* @file
*
* Test harness for unsafe_symlink(). Not linked into @c rsync itself.
*
* Prints either "safe" or "unsafe" depending on the two arguments.
* Always returns 0 unless something extraordinary happens.
**/
/* Prints either "safe" or "unsafe" depending on the two arguments.
* Always returns 0 unless something extraordinary happens. */
#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
main(int argc, char **argv)
{
@@ -41,6 +40,6 @@ main(int argc, char **argv)
printf("%s\n",
unsafe_symlink(argv[1], argv[2]) ? "unsafe" : "safe");
return 0;
}

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,14 +29,43 @@ 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" "$fromdir/foo"
touch "$fromdir/bar"
checkit "$RSYNC -avv '$fromdir/' '$checkdir/'" "$fromdir" "$checkdir"
chmod o+x "$fromdir"/bar
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
# for the purposes of the second application of the incoming chmod.
build_rsyncd_conf
cat >>"$scratchdir/test-rsyncd.conf" <<EOF
[test-incoming-chmod]
path = $todir
read only = no
incoming chmod = Fo-x
EOF
RSYNC_CONNECT_PROG="$RSYNC --config=$conf --daemon"
export RSYNC_CONNECT_PROG
rm -r "$todir"
makepath "$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

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