pax_global_header 0000666 0000000 0000000 00000000064 13737671777 0014543 g ustar 00root root 0000000 0000000 52 comment=dcb672942e4094849ff035506729a998b340e7e3
rsync-bpc-3.1.3.0/ 0000775 0000000 0000000 00000000000 13737671777 0013605 5 ustar 00root root 0000000 0000000 rsync-bpc-3.1.3.0/COPYING 0000664 0000000 0000000 00000104513 13737671777 0014644 0 ustar 00root root 0000000 0000000 GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc.
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
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
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 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 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.
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.
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.
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.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"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.
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.
A "covered work" means either the unmodified Program or a work based
on the Program.
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.
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.
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.
1. Source Code.
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.
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.
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 "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.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
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.
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 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.
13. Use with the GNU Affero General Public License.
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.
14. Revised Versions of this License.
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 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.
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.
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.
15. Disclaimer of Warranty.
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.
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
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
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.
Copyright (C)
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, see .
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
Copyright (C)
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, 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 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
.
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
.
rsync-bpc-3.1.3.0/Doxyfile 0000664 0000000 0000000 00000015756 13737671777 0015331 0 ustar 00root root 0000000 0000000 # Doxyfile 1.2.15
#---------------------------------------------------------------------------
# General configuration options
#---------------------------------------------------------------------------
PROJECT_NAME = rsync
PROJECT_NUMBER = HEAD
OUTPUT_DIRECTORY = dox
OUTPUT_LANGUAGE = English
EXTRACT_ALL = YES
EXTRACT_PRIVATE = YES
EXTRACT_STATIC = YES
EXTRACT_LOCAL_CLASSES = YES
HIDE_UNDOC_MEMBERS = NO
HIDE_UNDOC_CLASSES = NO
BRIEF_MEMBER_DESC = YES
REPEAT_BRIEF = YES
ALWAYS_DETAILED_SEC = NO
INLINE_INHERITED_MEMB = NO
FULL_PATH_NAMES = NO
STRIP_FROM_PATH = *source
INTERNAL_DOCS = YES
STRIP_CODE_COMMENTS = NO
CASE_SENSE_NAMES = YES
SHORT_NAMES = NO
HIDE_SCOPE_NAMES = YES
VERBATIM_HEADERS = YES
SHOW_INCLUDE_FILES = YES
JAVADOC_AUTOBRIEF = YES
INHERIT_DOCS = YES
INLINE_INFO = YES
SORT_MEMBER_DOCS = NO
DISTRIBUTE_GROUP_DOC = NO
TAB_SIZE = 8
GENERATE_TODOLIST = YES
GENERATE_TESTLIST = YES
GENERATE_BUGLIST = YES
ALIASES =
ENABLED_SECTIONS =
MAX_INITIALIZER_LINES = 30
OPTIMIZE_OUTPUT_FOR_C = YES
OPTIMIZE_OUTPUT_JAVA = NO
SHOW_USED_FILES = YES
#---------------------------------------------------------------------------
# configuration options related to warning and progress messages
#---------------------------------------------------------------------------
QUIET = NO
WARNINGS = NO
WARN_IF_UNDOCUMENTED = NO
WARN_FORMAT = "$file:$line: $text"
WARN_LOGFILE =
#---------------------------------------------------------------------------
# configuration options related to the input files
#---------------------------------------------------------------------------
INPUT = .
FILE_PATTERNS = *.c \
*.h
RECURSIVE = YES
EXCLUDE = proto.h \
zlib \
popt
EXCLUDE_SYMLINKS = NO
EXCLUDE_PATTERNS =
EXAMPLE_PATH =
EXAMPLE_PATTERNS =
EXAMPLE_RECURSIVE = NO
IMAGE_PATH =
INPUT_FILTER =
FILTER_SOURCE_FILES = NO
#---------------------------------------------------------------------------
# configuration options related to source browsing
#---------------------------------------------------------------------------
SOURCE_BROWSER = YES
INLINE_SOURCES = YES
REFERENCED_BY_RELATION = YES
REFERENCES_RELATION = YES
#---------------------------------------------------------------------------
# configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
ALPHABETICAL_INDEX = YES
COLS_IN_ALPHA_INDEX = 3
IGNORE_PREFIX =
#---------------------------------------------------------------------------
# configuration options related to the HTML output
#---------------------------------------------------------------------------
GENERATE_HTML = YES
HTML_OUTPUT = html
HTML_FILE_EXTENSION = .html
HTML_HEADER =
HTML_FOOTER =
HTML_STYLESHEET =
HTML_ALIGN_MEMBERS = YES
GENERATE_HTMLHELP = NO
GENERATE_CHI = NO
BINARY_TOC = NO
TOC_EXPAND = NO
DISABLE_INDEX = NO
ENUM_VALUES_PER_LINE = 3
GENERATE_TREEVIEW = NO
TREEVIEW_WIDTH = 250
#---------------------------------------------------------------------------
# configuration options related to the LaTeX output
#---------------------------------------------------------------------------
GENERATE_LATEX = NO
LATEX_OUTPUT = latex
LATEX_CMD_NAME = latex
MAKEINDEX_CMD_NAME = makeindex
COMPACT_LATEX = NO
PAPER_TYPE = a4wide
EXTRA_PACKAGES =
LATEX_HEADER =
PDF_HYPERLINKS = YES
USE_PDFLATEX = YES
LATEX_BATCHMODE = YES
#---------------------------------------------------------------------------
# configuration options related to the RTF output
#---------------------------------------------------------------------------
GENERATE_RTF = NO
RTF_OUTPUT = rtf
COMPACT_RTF = NO
RTF_HYPERLINKS = NO
RTF_STYLESHEET_FILE =
RTF_EXTENSIONS_FILE =
#---------------------------------------------------------------------------
# configuration options related to the man page output
#---------------------------------------------------------------------------
GENERATE_MAN = NO
MAN_OUTPUT = man
MAN_EXTENSION = .3
MAN_LINKS = NO
#---------------------------------------------------------------------------
# configuration options related to the XML output
#---------------------------------------------------------------------------
GENERATE_XML = NO
#---------------------------------------------------------------------------
# configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
GENERATE_AUTOGEN_DEF = NO
#---------------------------------------------------------------------------
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
ENABLE_PREPROCESSING = NO
MACRO_EXPANSION = NO
EXPAND_ONLY_PREDEF = NO
SEARCH_INCLUDES = YES
INCLUDE_PATH =
INCLUDE_FILE_PATTERNS =
PREDEFINED =
EXPAND_AS_DEFINED =
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
# Configuration::addtions related to external references
#---------------------------------------------------------------------------
TAGFILES =
GENERATE_TAGFILE =
ALLEXTERNALS = NO
EXTERNAL_GROUPS = YES
PERL_PATH = /usr/bin/perl
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
CLASS_DIAGRAMS = YES
HAVE_DOT = YES
CLASS_GRAPH = YES
COLLABORATION_GRAPH = YES
TEMPLATE_RELATIONS = YES
HIDE_UNDOC_RELATIONS = YES
INCLUDE_GRAPH = YES
INCLUDED_BY_GRAPH = YES
GRAPHICAL_HIERARCHY = YES
DOT_IMAGE_FORMAT = png
DOT_PATH =
DOTFILE_DIRS =
MAX_DOT_GRAPH_WIDTH = 1024
MAX_DOT_GRAPH_HEIGHT = 1024
GENERATE_LEGEND = YES
DOT_CLEANUP = YES
#---------------------------------------------------------------------------
# Configuration::addtions related to the search engine
#---------------------------------------------------------------------------
SEARCHENGINE = NO
CGI_NAME = search.cgi
CGI_URL =
DOC_URL =
DOC_ABSPATH =
BIN_ABSPATH = /usr/local/bin/
EXT_DOC_PATHS =
rsync-bpc-3.1.3.0/INSTALL 0000664 0000000 0000000 00000004703 13737671777 0014642 0 ustar 00root root 0000000 0000000 To build and install rsync:
$ ./configure
$ make
# make install
You may set the installation directory and other parameters by options
to ./configure. To see them, use:
$ ./configure --help
Configure tries to figure out if the local system uses group "nobody" or
"nogroup" by looking in the /etc/group file. (This is only used for the
default group of an rsync daemon, which attempts to run with "nobody"
user and group permissions.) You can change the default user and group
for the daemon by editing the NOBODY_USER and NOBODY_GROUP defines in
config.h, or just override them in your /etc/rsyncd.conf file.
As of 2.4.7, rsync uses Eric Troan's popt option-parsing library. A
cut-down copy of a recent release is included in the rsync distribution,
and will be used if there is no popt library on your build host, or if
the --with-included-popt option is passed to ./configure.
If you configure using --enable-maintainer-mode, then rsync will try
to pop up an xterm on DISPLAY=:0 if it crashes. You might find this
useful, but it should be turned off for production builds.
MAKE COMPATIBILITY
------------------
Note that Makefile.in has a rule that uses a wildcard in a prerequisite. If
your make has a problem with this rule, you will see an error like this:
Don't know how to make ./*.c
You can change the "proto.h-tstamp" target in Makefile.in to list all the *.c
filenames explicitly in order to avoid this issue.
RPM NOTES
---------
Under packaging you will find .spec files for several distributions.
The .spec file in packaging/lsb can be used for Linux systems that
adhere to the Linux Standards Base (e.g., RedHat and others).
HP-UX NOTES
-----------
The HP-UX 10.10 "bundled" C compiler seems not to be able to cope with
ANSI C. You may see this error message in config.log if ./configure
fails:
(Bundled) cc: "configure", line 2162: error 1705: Function prototypes are an ANSI feature.
Install gcc or HP's "ANSI/C Compiler".
MAC OSX NOTES
-------------
Some versions of Mac OS X (Darwin) seem to have an IPv6 stack, but do
not completely implement the "New Sockets" API.
says that Apple started to support
IPv6 in 10.2 (Jaguar). If your build fails, try again after running
configure with --disable-ipv6.
IBM AIX NOTES
-------------
IBM AIX has a largefile problem with mkstemp. See IBM PR-51921.
The workaround is to append the below to config.h
#ifdef _LARGE_FILES
#undef HAVE_SECURE_MKSTEMP
#endif
rsync-bpc-3.1.3.0/Makefile.in 0000664 0000000 0000000 00000015164 13737671777 0015661 0 ustar 00root root 0000000 0000000 # Makefile for rsync_bpc. This is processed by configure to produce the final
# Makefile
prefix=@prefix@
datarootdir=@datarootdir@
exec_prefix=@exec_prefix@
stunnel4=@STUNNEL4@
bindir=@bindir@
mandir=@mandir@
LIBS=@LIBS@
CC=@CC@
CFLAGS=@CFLAGS@
CPPFLAGS=@CPPFLAGS@
EXEEXT=@EXEEXT@
LDFLAGS=@LDFLAGS@
LIBOBJDIR=lib/
INSTALLCMD=@INSTALL@
INSTALLMAN=@INSTALL@
srcdir=@srcdir@
MKDIR_P=@MKDIR_P@
VPATH=$(srcdir)
SHELL=/bin/sh
VERSION=@RSYNC_VERSION@
.SUFFIXES:
.SUFFIXES: .c .o
GENFILES=configure.sh aclocal.m4 config.h.in proto.h proto.h-tstamp
HEADERS=byteorder.h config.h errcode.h proto.h rsync.h ifuncs.h itypes.h inums.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@
zlib_OBJS=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
BPCOBJ=bpc_sysCalls.o backuppc/bpc_attrib.o backuppc/bpc_dirOps.o backuppc/bpc_hashtable.o backuppc/bpc_poolWrite.o \
backuppc/bpc_attribCache.o backuppc/bpc_fileDigest.o backuppc/bpc_fileZIO.o backuppc/bpc_lib.o backuppc/bpc_refCount.o
OBJS1=flist.o rsync.o generator.o receiver.o cleanup.o sender.o exclude.o \
util.o util2.o main.o checksum.o match.o syscall.o log.o backup.o delete.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) $(BPCOBJ) @BUILD_ZLIB@ @BUILD_POPT@
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_bpc$(EXEEXT) tls$(EXEEXT) getgroups$(EXEEXT) getfsdev$(EXEEXT) \
testrun$(EXEEXT) trimslash$(EXEEXT) t_unsafe$(EXEEXT) wildtest$(EXEEXT)
CHECK_SYMLINKS =
# Objects for CHECK_PROGS to clean
CHECK_OBJS=tls.o testrun.o getgroups.o getfsdev.o t_stub.o t_unsafe.o trimslash.o wildtest.o
# note that the -I. is needed to handle config.h when using VPATH
.c.o:
@OBJ_SAVE@
$(CC) -I. -I$(srcdir) $(CFLAGS) $(CPPFLAGS) -c $< @CC_SHOBJ_FLAG@
@OBJ_RESTORE@
all: Makefile rsync_bpc$(EXEEXT)
install: all
-${MKDIR_P} ${DESTDIR}${bindir}
${INSTALLCMD} ${INSTALL_STRIP} -m 755 rsync_bpc$(EXEEXT) ${DESTDIR}${bindir}
install-all: install
install-strip:
$(MAKE) INSTALL_STRIP='-s' install
rsync_bpc$(EXEEXT): $(OBJS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
$(BPCOBJ): backuppc/backuppc.h
$(OBJS): $(HEADERS)
$(CHECK_OBJS): $(HEADERS)
flist.o: rounding.h
rounding.h: rounding.c rsync.h proto.h
@for r in 0 1 3; do \
if $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -o rounding -DEXTRA_ROUNDING=$$r -I. $(srcdir)/rounding.c >rounding.out 2>&1; then \
echo "#define EXTRA_ROUNDING $$r" >rounding.h; \
if test -f "$$HOME/build_farm/build_test.fns"; then \
echo "EXTRA_ROUNDING is $$r" >&2; \
fi; \
break; \
fi; \
done
@rm -f rounding
@if test -f rounding.h; then : ; else \
cat rounding.out 1>&2; \
echo "Failed to create rounding.h!" 1>&2; \
exit 1; \
fi
@rm -f rounding.out
tls$(EXEEXT): $(TLS_OBJ)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(TLS_OBJ) $(LIBS)
testrun$(EXEEXT): testrun.o
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ testrun.o
getgroups$(EXEEXT): getgroups.o
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ getgroups.o $(LIBS)
getfsdev$(EXEEXT): getfsdev.o
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ getfsdev.o $(LIBS)
TRIMSLASH_OBJ = trimslash.o syscall.o lib/compat.o lib/snprintf.o
trimslash$(EXEEXT): $(TRIMSLASH_OBJ)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(TRIMSLASH_OBJ) $(LIBS)
T_UNSAFE_OBJ = t_unsafe.o syscall.o util.o util2.o t_stub.o lib/compat.o lib/snprintf.o lib/wildmatch.o
t_unsafe$(EXEEXT): $(T_UNSAFE_OBJ)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(T_UNSAFE_OBJ) $(LIBS)
gen: conf proto.h
conf:
cd $(srcdir) && $(MAKE) -f prepare-source.mak conf
reconfigure: configure.sh
./config.status --recheck
./config.status
configure.sh: configure.ac
autoconf configure.ac > configure.sh
Makefile: Makefile.in config.status configure.sh config.h.in
@if test -f Makefile; then cp -p Makefile Makefile.old; else touch Makefile.old; fi
@./config.status
@if diff Makefile Makefile.old >/dev/null 2>&1; then \
echo "Makefile is unchanged."; \
rm Makefile.old; \
else \
if test "$(MAKECMDGOALS)" = reconfigure; then \
echo 'Continuing with "make reconfigure".'; \
else \
echo "Makefile updated -- rerun your make command."; \
exit 1; \
fi \
fi
proto: proto.h-tstamp
proto.h: proto.h-tstamp
@if test -f proto.h; then :; else cp -p $(srcdir)/proto.h .; fi
proto.h-tstamp: $(srcdir)/*.c $(srcdir)/lib/compat.c config.h
perl $(srcdir)/mkproto.pl $(srcdir)/*.c $(srcdir)/lib/compat.c
man:
rsync.1: rsync.yo
yodl2man -o rsync.1 $(srcdir)/rsync.yo
-$(srcdir)/tweak_manpage rsync.1
rsyncd.conf.5: rsyncd.conf.yo
yodl2man -o rsyncd.conf.5 $(srcdir)/rsyncd.conf.yo
-$(srcdir)/tweak_manpage rsyncd.conf.5
clean: cleantests
rm -f *~ $(OBJS) $(CHECK_PROGS) $(CHECK_OBJS) $(CHECK_SYMLINKS) \
rounding rounding.h *.old
cleantests:
rm -rf ./testtmp*
# We try to delete built files from both the source and build
# directories, just in case somebody previously configured things in
# the source directory.
distclean: clean
rm -f Makefile config.h config.status
rm -f lib/dummy popt/dummy zlib/dummy backuppc/dummy
rm -f $(srcdir)/Makefile $(srcdir)/config.h $(srcdir)/config.status
rm -f $(srcdir)/lib/dummy $(srcdir)/popt/dummy $(srcdir)/zlib/dummy $(srcdir)/backuppc/dummy
rm -f config.cache config.log
rm -f $(srcdir)/config.cache $(srcdir)/config.log
rm -f shconfig $(srcdir)/shconfig
rm -f $(GENFILES)
rm -rf autom4te.cache
# this target is really just for my use. It only works on a limited
# range of machines and is used to produce a list of potentially
# dead (ie. unused) functions in the code. (tridge)
finddead:
nm *.o */*.o |grep 'U ' | awk '{print $$2}' | sort -u > nmused.txt
nm *.o */*.o |grep 'T ' | awk '{print $$3}' | sort -u > nmfns.txt
comm -13 nmused.txt nmfns.txt
wildtest.o: wildtest.c lib/wildmatch.c rsync.h config.h
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)
# TODO: Add 'dist' target; need to know which files will be included
# Run the SPLINT (Secure Programming Lint) tool.
.PHONY: splint
splint:
splint +unixlib +gnuextensions -weak rsync.c
doxygen:
cd $(srcdir) && rm dox/html/* && doxygen
rsync-bpc-3.1.3.0/NEWS 0000664 0000000 0000000 00000005005 13737671777 0014304 0 ustar 00root root 0000000 0000000 NEWS for rsync-bpc 3.1.3
3.1.3.0 released 7 Oct 2020:
- default buffer size in bpc_strBuf now 2048
- pool files are chmod to 0444
- couple of tweaks to debug messages
3.1.3beta1 released 20 June 2020:
- Initial version based on rsync 3.1.3
NEWS for rsync 3.1.3 (28 Jan 2018)
Protocol: 31 (unchanged)
Changes since 3.1.2:
SECURITY FIXES:
- Fixed a buffer overrun in the protocol's handling of xattr names and
ensure that the received name is null terminated.
- Fix an issue with --protect-args where the user could specify the arg in
the protected-arg list and short-circuit some of the arg-sanitizing code.
BUG FIXES:
- Don't output about a new backup dir without appropriate info verbosity.
- Fixed some issues with the sort functions in support/rsyncstats script.
- Added a way to specify daemon config lists (e.g. users, groups, etc) that
contain spaces (see "auth users" in the latest rsyncd.conf manpage).
- If a backup fails (e.g. full disk) rsync exits with an error.
- Fixed a problem with a doubled --fuzzy option combined with --link-dest.
- Avoid invalid output in the summary if either the start or end time had
an error.
- We don't allow a popt alias to affect the --daemon or --server options.
- Fix daemon exclude code to disallow attribute changes in addition to
disallowing transfers.
- Don't force nanoseconds to match if a non-transferred, non-checksummed
file only passed the quick-check w/o comparing nanosecods.
ENHANCEMENTS:
- Added the ability for rsync to compare nanosecond times in its file-check
comparisons, and added support nanosecond times on Mac OS X.
- Added a short-option (-@) for --modify-window.
- Added the --checksum-choice=NAME[,NAME] option to choose the checksum
algorithms.
- Added hashing of xattr names (with using -X) to improve the handling of
files with large numbers of xattrs.
- Added a way to filter xattr names using include/exclude/filter rules (see
the --xattrs option in the manpage for details).
- Added "daemon chroot|uid|gid" to the daemon config (in addition to the
old chroot|uid|gid settings that affect the daemon's transfer process).
- Added "syslog tag" to the daemon configuration.
- Some manpage improvements.
DEVELOPER RELATED:
- Tweak the "make" output when yodl isn't around to create the man pages.
- Changed an obsolete autoconf compile macro.
- Support newer yodl versions when converting man pages.
rsync-bpc-3.1.3.0/OLDNEWS 0000664 0000000 0000000 00000501276 13737671777 0014656 0 ustar 00root root 0000000 0000000 NEWS for rsync 3.1.2 (21 Dec 2015)
Protocol: 31 (unchanged)
Changes since 3.1.1:
SECURITY FIXES:
- Make sure that all transferred files use only path names from inside the
transfer. This makes it impossible for a malicious sender to try to make
the receiver use an unsafe destination path for a transferred file, such
as a just-sent symlink.
BUG FIXES:
- Change the checksum seed order in the per-block checksums. This prevents
someone from trying to create checksum blocks that match in sum but not
content.
- Fixed a with the per-dir filter files (using -FF) that could trigger an
assert failure.
- Only skip set_modtime() on a transferred file if the time is exactly
right.
- Don't create an empty backup dir for a transferred file that doesn't
exist yet.
- Fixed a bug where --link-dest and --xattrs could cause rsync to exit if
a filename had a matching dir of the same name in the alt-dest area.
- Allow more than 32 group IDs per user in the daemon's gid=LIST config.
- Fix the logging of %b & %c via --log-file (daemon logging was already
correct, as was --out-format='%b/%c').
- Fix erroneous acceptance of --info=5 & --debug=5 (an empty flag name is
not valid).
ENHANCEMENTS:
- Added "(DRY RUN)" info to the --debug=exit output line.
- Use usleep() for our msleep() function if it is available.
- Added a few extra long-option names to rrsync script, which will make
BackupPC happier.
- Made configure choose to use linux xattrs on netbsd (rather than not
supporting xattrs).
- Added -wo (write-only) option to rrsync support script.
- Misc. manpage tweaks.
DEVELOPER RELATED:
- Fixed a bug with the Makefile's use of INSTALL_STRIP.
- Improve a test in the suite that could get an erroneous timestamp error.
- Tweaks for newer versions of git in the packaging tools.
- Improved the m4 generation rules and some autoconf idioms.
NEWS for rsync 3.1.1 (22 Jun 2014)
Protocol: 31 (unchanged)
Changes since 3.1.0:
BUG FIXES:
- If the receiver gets bogus filenames from the sender (an unexpected
leading slash or a ".." infix dir), exit with an error. This prevents a
malicious sender from trying to inject filenames that would affect an
area outside the destination directories.
- Fixed a failure to remove the partial-transfer temp file when interrupted
(and rsync is not saving the partial files).
- Changed the chown/group/xattr-set order to avoid losing some security-
related xattr info (that would get cleared by a chown).
- Fixed a bug in the xattr-finding code that could make a non-root-run
receiver not able to find some xattr numbers.
- Fixed a bug in the early daemon protocol where a timeout failed to be
honored (e.g. if the remote side fails to send us the initial protocol
greeting).
- Fixed unintended inclusion of commas in file numbers in the daemon log.
- We once again send the 'f' sub-flag (of -e) to the server side so it
knows that we can handle incremental-recursion directory errors properly
in older protocols.
- Fixed an issue with too-aggressive keep-alive messages causing a problem
for older rsync versions early in the transfer.
- Fixed an incorrect message about backup-directory-creation when using
--dry-run and the backup dir is not an absolute path.
- Fixed a bug where a failed deletion and/or a failed sender-side removal
would not affect the exit code.
- Fixed a bug that caused a failure when combining --delete-missing-args
with --xattrs and/or --acls.
- Fixed a strange dir_depth assertion error that was caused by empty-dir
removals and/or duplicate files in the transfer.
- Fixed a problem with --info=progress2's output stats where rsync would
only update the stats at the end of each file's transfer. It now uses
the data that is flowing for the current file, making the stats more
accurate and less jumpy.
- Fixed an itemize bug that affected the combo of --link-dest, -X, and -n.
- Fixed a problem with delete messages not appearing in the log file when
the user didn't use --verbose.
- Improve chunked xattr reading for OS X.
- Removed an attempted hard-link xattr optimization that was causing a
transfer failure. This removal is flagged in the compatibility code, so
if a better fix can be discovered, we have a way to flip it on again.
- Fixed a bug when the receiver is not configured to be able to hard link
symlimks/devices/special-file items but the sender sent some of these
items flagged as hard-linked.
- We now generate a better error if the buffer overflows in do_mknod().
- Fixed a problem reading more than 16 ACLs on some OSes.
- Fixed the reading of the secrets file to avoid an infinite wait when
the username is missing.
- Fixed a parsing problem in the --usermap/--groupmap options when using
MIN-MAX numbers.
- Switched Cygwin back to using socketpair "pipes" to try to speed it up.
- Added knowledge of a few new options to rrsync.
ENHANCEMENTS:
- Tweaked the temp-file naming when --temp-dir=DIR is used: the temp-file
names will not get a '.' prepended.
- Added support for a new-compression idiom that does not compress all the
matching data in a transfer. This can help rsync to use less cpu when a
transfer has a lot of matching data, and also makes rsync compatible with
a non-bundled zlib. See the --new-compress and --old-compress options in
the manpage.
- Added the support/rsync-no-vanished wrapper script.
- Made configure more prominently mention when we failed to find yodl (in
case the user wants to be able to generate manpages from *.yo files).
- Have manpage mention how a daemon's max-verbosity setting affects info
and debug options. Also added more clarification on backslash removals
for excludes that contain wildcards.
- Have configure check if for the attr lib (for getxattr) for those systems
that need to link against it explicitly.
- Change the early dir-creation logic to only use that idiom in an
inc-recursive copy that is preserving directory times. e.g. using
--omit-dir-times will avoid these early directories being created.
- Fix a bug in cmp_time() that would return a wrong result if the 2 times
differed by an amount greater than what a time_t can hold.
DEVELOPER RELATED:
- We now include an example systemd file (in packaging/systemd).
- Tweaked configure to make sure that any intended use of the included popt
and/or zlib code is put early in the CFLAGS.
NEWS for rsync 3.1.0 (28 Sep 2013)
Protocol: 31 (changed)
Changes since 3.0.9:
OUTPUT CHANGES:
- Output numbers in 3-digit groups by default (e.g. 1,234,567). See the
--human-readable option for a way to turn it off. See also the daemon's
"log format" parameter and related command-line options (including
--out-format) for a modifier that can be used to request digit-grouping
or human-readable output in log escapes. (Note that log output is
unchanged by default.)
- The --list-only option is now affected by the --human-readable setting.
It will display digit groupings by default, and unit suffixes if higher
levels of readability are requested. Also, the column width for the size
output has increased from 11 to 14 characters when human readability is
enabled. Use --no-h to get the old-style output and column size.
- The output of the --progress option has changed: the string "xfer" was
shortened to "xfr", and the string "to-check" was shortened to "to-chk",
both designed to make room for the (by default) wider display of file
size numbers without making the total line-length longer. Also, when
incremental recursion is enabled, the string "ir-chk" will be used
instead of "to-chk" up until the incremental-recursion scan is done,
letting you know that the value to check and the total value will still
be increasing as new files are found.
- Enhanced the --stats output: 1) to mention how many files were created
(protocol >= 28), 2) to mention how many files were deleted (a new line
for protocol 31, but only output when --delete is in effect), and 3) to
follow the file-count, created-count, and deleted-count with a subcount
list that shows the counts by type. The wording of the transferred count
has also changed so that it is clearer that it is only a count of regular
files.
BUG FIXES:
- Fixed a bug in the iconv code when EINVAL or EILSEQ is returned with a
full output buffer.
- Fixed some rare bugs in --iconv processing that might cause a multibyte
character to get translated incorrectly.
- Fixed a bogus "vanished file" error if some files were specified with
"./" prefixes and others were not.
- Fixed a bug in --sparse where an extra gap could get inserted after a
partial write.
- Changed the way --progress overwrites its prior output in order to make
it nearly impossible for the progress to get overwritten by an error.
- Improved the propagation of abnormal-exit error messages. This should
help the client side to receive errors from the server when it is exiting
abnormally, and should also avoid dying with an "connection unexpectedly
closed" exit when the closed connection is really expected.
- The sender now checks each file it plans to remove to ensure that it
hasn't changed from the first stat's info. This helps to avoid losing
file data when the user is not using the option in a safe manner.
- Fixed a data-duplication bug in the compress option that made compression
less efficient. This improves protocol 31 onward, while behaving in a
compatible (buggy) manner with older rsync protocols.
- When creating a temp-file, rsync is now a bit smarter about it dot-char
choices, which can fix a problem on OS X with names that start with "..".
- Rsync now sets a cleanup flag for --inplace and --append transfers that
will flush the write buffer if the transfer aborts. This ensures that
more received data gets written out to the disk on an aborted transfer
(which is quite helpful on a slow, flaky connection).
- The reads that map_ptr() now does are aligned on 1K boundaries. This
helps some filesystems and/or files that don't like unaligned reads.
- Fix an issue in the msleep() function if time jumps backwards.
- Fix daemon-server module-name splitting bug where an arg would get split
even if --protect-args was used.
ENHANCEMENTS:
- Added the --remote-option=OPT (-M OPT) command-line option that is useful
for things like sending a remote --log-file=FILE or --fake-super option.
- Added the --info=FLAGS and --debug=FLAGS options to allow finer-grained
control over what is output. Added an extra type of --progress output
using --info=progress2.
- The --msgs2stderr option can help with debugging rsync by allowing the
debug messages to get output to stderr rather than travel via the socket
protocol.
- Added the --delete-missing-args and --ignore-missing-args options to
either delete or ignore user-specified files on the receiver that are
missing on the sender (normally the absence of user-specified files
generates an error).
- Added a "T" (terabyte) category to the --human-readable size suffixes.
- Added the --usermap/--groupmap/--chown options for manipulating file
ownership during the copy.
- Added the "%C" escape to the log-output handling, which will output the
MD5 checksum of any transferred file, or all files if --checksum was
specified (when protocol 30 or above is in effect).
- Added the "reverse lookup" parameter to the rsync daemon config file to
allow reverse-DNS lookups to be disabled.
- Added a forward-DNS lookup for the daemon's hosts allow/deny config. Can
be disabled via "forward lookup" parameter (defaults to enabled).
- Added a way for more than one group to be specified in the daemon's
config file, including a way to specify that you want all of the
specified user's groups without having to name them. Also changed the
daemon to complain about an inability to set explicitly-specified uid/gid
values, even when not run by a super-user.
- The daemon now tries to send the user the error messages from the
pre-xfer exec script when it fails.
- Improved the use of alt-dest options into an existing hierarchy of files:
If a match is found in an alt-dir, it takes precedence over an existing
file. (We'll need to wait for a future version before attribute-changes
on otherwise unchanged files are safe when using an existing hierarchy.)
- Added per-user authorization options and group-authorization support to
the daemon's "auth users" parameter.
- Added a way to reference environment variables in a daemon's config file
(using %VAR% references).
- When replacing a non-dir with a symlink/hard-link/device/special-file,
the update should now be done in an atomic manner.
- Avoid re-sending xattr info for hard-linked files w/the same xattrs
(protocol 31).
- The backup code was improved to use better logic maintaining the backup
directory hierarchy. Also, when a file is being backed up, rsync tries
to hard-link it into place so that the upcoming replacement of the
destination file will be atomic (for the normal, non-inplace logic).
- Added the ability to synchronize nano-second modified times.
- Added a few more default suffixes for the "dont compress" settings.
- Added the checking of the RSYNC_PROTECT_ARGS environment variable to allow
the default for the --protect-args command-line option to be overridden.
- Added the --preallocate command-line option.
- Allow --password-file=- to read the password from stdin (filename "-").
- Rsync now comes packaged with an rsync-ssl helper script that can be
used to contact a remote rsync daemon using a piped-stunnel command.
It also includes an stunnel config file to run the server side to
support ssl daemon connections. See the packaging/lsb/rsync.spec
file for one way to package the resulting files. (Suggestions for
how to make this even easier to install & use are welcomed.)
- Improved the speed of some --inplace updates when there are lots of
identical checksum blocks that end up being unusable.
- Added the --outbuf=N|L|B option for choosing the output buffering.
- Repeating the --fuzzy option now causes the code to look for fuzzy
matches inside alt-dest directories too.
- The --chmod option now supports numeric modes, e.g. --chmod=644,D755
- Added some Solaris xattr code.
- Made an rsync daemon (the listening process) exit with a 0 status when
it was signaled to die. This helps launchd.
- Improved the RSYNC_* environment variables for the pre-xfer exec script:
when a daemon is sent multiple request args, they are now joined into a
single return value (separated by spaces) so that the RSYNC_REQUEST
environment variable is accurate for any "pre-xfer exec". The values in
RSYNC_ARG# vars are no longer truncated at the "." arg (prior to the
request dirs/files), so that all the requested values are also listed
(separately) in RSYNC_ARG# variables.
EXTRAS:
- Added an "instant-rsyncd" script to the support directory, which makes
it easy to configure a simple rsync daemon in the current directory.
- Added the "mapfrom" and "mapto" scripts to the support directory, which
makes it easier to do user/group mapping in a local transfer based on
passwd/group files from another machine.
- There's a new, improved version of the lsh script in the support dir:
it's written in perl and supports -u without resorting to using sudo
(when run as root). The old shell version is now named lsh.sh.
- There is a helper script named rsync-slash-strip in the support directory
for anyone that wants to change the way rsync handles args with trailing
slashes. (e.g. arg/ would get stripped to arg while arg/. would turn into
arg/).
INTERNAL:
- The I/O code was rewritten to be simpler and do bigger buffered reads
over the socket. The I/O between the receiver and the generator was
changed to be standard multiplexed-I/O (like that over the socket).
- The sender tries to use any dead time while the generator is looking for
files to transfer in order to do sender-side directory scanning in a more
parallel manner.
- A daemon can now inform a client about a daemon-configured timeout value
so that the client can assist in the keep-alive activity (protocol 31).
- The filter code received some refactoring to make it more extendible, to
read better, and do better sanity checking.
- Really big numbers are now output using our own big-num routine rather
than casting them to a double and using a %.0f conversion.
- The pool_alloc library has received some minor improvements in alignment
handling.
- Added init_stat_x() function to avoid duplication of acl/xattr init code.
- The included zlib was upgraded from 1.2.3 to 1.2.8.
- Rsync can now be compiled to use an unmodified zlib library instead of
the tweaked one that is included with rsync. This will eventually
become the default, at which point we'll start the countdown to removing
the included zlib. Until then, feel free to configure using:
./configure --with-included-zlib=no
DEVELOPER RELATED:
- Added more conditional debug output.
- Fixed some build issues for android and minix.
NEWS for rsync 3.0.9 (23 Sep 2011)
Protocol: 30 (unchanged)
Changes since 3.0.8:
BUG FIXES:
- Fix a crash bug in checksum scanning when --inplace is used.
- Fix a hang if a hard-linked file cannot be opened by the sender (e.g.
if it has no read permission).
- Fix preservation of a symlink's system xattrs (e.g. selinux) on Linux.
- Fix a memory leak in the xattr code.
- Fixed a bug with --delete-excluded when a filter merge file has a rule
that specifies a receiver-only side restriction.
- Fix a bug with the modifying of unwritable directories.
- Fix --fake-super's interaction with --link-dest same-file comparisons.
- Fix the updating of the curr_dir buffer to avoid a duplicate slash.
- Fix the directory permissions on an implied dot-dir when using --relative
(e.g. /outside/path/././send/path).
- Fixed some too-long sleeping instances when using --bwlimit.
- Fixed when symlink ownership difference-checking gets compiled into
unchanged_attrs().
- Improved the socket-error reporting when multiple protocols fail.
- Fixed a case where a socket error could reference just-freed memory.
- Failing to use a password file that was specified on the command-line is
now a fatal error.
- Fix the non-root updating of directories that don't have the read and/or
execute permission.
- Make daemon-excluded file errors more error-like.
- Fix a compilation issue on older C compilers (due to a misplaced var
declaration).
- Make configure avoid finding socketpair on cygwin.
- Avoid trying to reference SO_BROADCAST if the OS doesn't support it.
- Fix some issues with the post-processing of the man pages.
- Fixed the user home-dir handling in the support/lsh script.
- Some minor manpage improvements.
NEWS for rsync 3.0.8 (26 Mar 2011)
Protocol: 30 (unchanged)
Changes since 3.0.7:
BUG FIXES:
- Fixed two buffer-overflow issues: one where a directory path that is
exactly MAXPATHLEN was not handled correctly, and one handling a
--backup-dir that is extra extra large.
- Fixed a data-corruption issue when preserving hard-links without
preserving file ownership, and doing deletions either before or during
the transfer (CVE-2011-1097). This fixes some assert errors in the
hard-linking code, and some potential failed checksums (via -c) that
should have matched.
- Fixed a potential crash when an rsync daemon has a filter/exclude list
and the transfer is using ACLs or xattrs.
- Fixed a hang if a really large file is being processed by an rsync that
can't handle 64-bit numbers. Rsync will now complain about the file
being too big and skip it.
- For devices and special files, we now avoid gathering useless ACL and/or
xattr information for files that aren't being copied. (The un-copied
files are still put into the file list, but there's no need to gather
data that is not going to be used.) This ensures that if the user uses
--no-D, that rsync can't possibly complain about being unable to gather
extended information from special files that are in the file list (but
not in the transfer).
- Properly handle requesting remote filenames that start with a dash. This
avoids a potential error where a filename could be interpreted as a
(usually invalid) option.
- Fixed a bug in the comparing of upper-case letters in file suffixes for
--skip-compress.
- If an rsync daemon has a module configured without a path setting, rsync
will now disallow access to that module.
- If the destination arg is an empty string, it will be treated as a
reference to the current directory (as 2.x used to do).
- If rsync was compiled with a newer time-setting function (such as
lutimes), rsync will fall-back to an older function (such as utimes) on a
system where the newer function is not around. This helps to make the
rsync binary more portable in mixed-OS-release situations.
- Fixed a batch-file writing bug that would not write out the full set of
compatibility flags that the transfer was using. This fixes a potential
protocol problem for a batch file that contains a sender-side I/O error:
it would have been sent in a way that the batch-reader wasn't expecting.
- Some improvements to the hard-linking code to ensure that device-number
hashing is working right, and to supply more information if the hard-link
code fails.
- The --inplace code was improved to not search for an impossible checksum
position. The quadruple-verbose chunk[N] message will now mention when
an inplace chunk was handled by a seek rather than a read+write.
- Improved ACL mask handling, e.g. for Solaris.
- Fixed a bug that prevented --numeric-ids from disabling the translation
of user/group IDs for ACLs.
- Fixed an issue where an xattr and/or ACL transfer that used an alt-dest
option (e.g. --link-dest) could output an error trying to itemize the
changes against the alt-dest directory's xattr/ACL info but was instead
trying to access the not-yet-existing new destination directory.
- Improved xattr system-error messages to mention the full path to the
file.
- The --link-dest checking for identical symlinks now avoids considering
attribute differences that cannot be changed on the receiver.
- Avoid trying to read/write xattrs on certain file types for certain OSes.
Improved configure to set NO_SYMLINK_XATTRS, NO_DEVICE_XATTRS, and/or
NO_SPECIAL_XATTRS defines in config.h.
- Improved the unsafe-symlink errors messages.
- Fixed a bug setting xattrs on new files that aren't user writable.
- Avoid re-setting xattrs on a hard-linked file w/the same xattrs.
- Fixed a bug with --fake-super when copying files and dirs that aren't
user writable.
- Fixed a bug where a sparse file could have its last sparse block turned
into a real block when rsync sets the file size (requires ftruncate).
- If a temp-file name is too long, rsync now avoids truncating the name in
the middle of adjacent high-bit characters. This prevents a potential
filename error if the filesystem doesn't allow a name to contain an
invalid multi-byte sequence.
- If a muli-protocol socket connection fails (i.e., when contacting a
daemon), we now report all the failures, not just the last one. This
avoids losing a relevant error (e.g. an IPv4 connection-refused error)
that happened before the final error (e.g. an IPv6 protocol-not-supported
error).
- Generate a transfer error if we try to call chown with a -1 for a uid or
a gid (which is not settable).
- Fixed the working of --force when used with --one-file-system.
- Fix the popt arg parsing so that an option that doesn't take an arg will
reject an attempt to supply one (can configure --with-included-popt if
your system's popt library doesn't yet have this fix).
- A couple minor option tweaks to the support/rrsync script, and also some
regex changes that make vim highlighting happier.
- Fixed some issues in the support/mnt-excl script.
- Various manpage improvements.
ENHANCEMENTS:
- Added ".hg/" to the default cvs excludes (see -C & --cvs-exclude).
DEVELOPER RELATED:
- Use lchmod() whenever it is available (not just on symlinks).
- A couple fixes to the socketpair_tcp() routine.
- Updated the helper scripts in the packaging subdirectory.
- Renamed configure.in to configure.ac.
- Fixed configure's checking for iconv routines for newer OS X versions.
- Fixed the testsuite/xattrs.test script on OS X.
NEWS for rsync 3.0.7 (31 Dec 2009)
Protocol: 30 (unchanged)
Changes since 3.0.6:
BUG FIXES:
- Fixed a bogus free when using --xattrs with --backup.
- Avoid an error when --dry-run was trying to stat a prior hard-link file
that hasn't really been created.
- Fixed a problem with --compress (-z) where the receiving side could
return the error "inflate (token) returned -5".
- Fixed a bug where --delete-during could delete in a directory before it
noticed that the sending side sent an I/O error for that directory (both
sides of the transfer must be at least 3.0.7).
- Improved --skip-compress's error handling of bad character-sets and got
rid of a lingering debug fprintf().
- Fixed the daemon's conveyance of io_error value from the sender.
- An rsync daemon use seteuid() (when available) if it used setuid().
- Get the permissions right on a --fake-super transferred directory that
needs more owner permissions to emulate root behavior.
- An absolute-path filter rule (i.e. with a '/' modifier) no longer loses
its modifier when sending the filter rules to the remote rsync.
- Improved the "--delete does not work without -r or -d" message.
- Improved rsync's handling of --timeout to avoid a weird timeout case
where the sender could timeout even though it has recently written data
to the socket (but hasn't read data recently, due to the writing).
- Some misc manpage improvements.
- Fixed the chmod-temp-dir testsuite on a system without /var/tmp.
- Make sure that a timeout specified in the daemon's config is used as a
maximum timeout value when the user also specifies a timeout.
- Improved the error-exit reporting when rsync gets an error trying to
cleanup after an error: the initial error is reported.
- Improved configure's detection of IPv6 for solaris and cygwin.
- The AIX sysacls routines will now return ENOSYS if ENOTSUP is missing.
- Made our (only used if missing) getaddrinfo() routine use inet_pton()
(which we also provide) instead of inet_aton().
- The exit-related debug messages now mention the program's role so it is
clear who output what message.
DEVELOPER RELATED:
- Got rid of type-punned compiler warnings output by newer gcc versions.
- The Makefile now ensures that proto.h will be rebuilt if config.h changes.
- The testsuite no longer uses "id -u", so it works better on solaris.
NEWS for rsync 3.0.6 (8 May 2009)
Protocol: 30 (unchanged)
Changes since 3.0.5:
BUG FIXES:
- Fixed a --read-batch hang when rsync is reading a batch file that was
created from an incremental-recursion transfer.
- Fixed the daemon's socket code to handle the simultaneous arrival of
multiple connections.
- Fix --safe-links/--copy-unsafe-links to properly handle symlinks that
have consecutive slashes in the value.
- Fixed the parsing of an [IPv6_LITERAL_ADDR] when a USER@ is prefixed.
- The sender now skips a (bogus) symlink that has a 0-length value, which
avoids a transfer error in the receiver.
- Fixed a case where the sender could die with a tag-0 error if there was
an I/O during the sending of the file list.
- Fixed the rrsync script to avoid a server-side problem when -e is at the
start of the short options.
- Fixed a problem where a vanished directory could turn into an exit code
23 instead of the proper exit code 24.
- Fixed the --iconv conversion of symlinks when doing a local copy.
- Fixed a problem where --one-file-system was not stopping deletions on the
receiving side when a mount-point directory did not match a directory in
the transfer.
- Fixed the dropping of an ACL mask when no named ACL values were present.
- Fixed an ACL/xattr corruption issue where the --backup option could cause
rsync to associate the wrong ACL/xattr information with received files.
- Fixed the use of --xattrs with --only-write-batch.
- Fixed the use of --dry-run with --read-batch.
- Fixed configure's erroneous use of target.
- Fixed configure's --disable-debug option.
- Fixed a run-time issue for systems that can't find iconv_open() by adding
the --disable-iconv-open configure option.
- Complain and die if the user tries to combine --remove-source-files (or
the deprecated --remove-sent-files) with --read-batch.
- Fixed an failure transferring special files from Solaris to Linux.
NEWS for rsync 3.0.5 (28 Dec 2008)
Protocol: 30 (unchanged)
Changes since 3.0.4:
BUG FIXES:
- Initialize xattr data in a couple spots in the hlink code, which avoids a
crash when the xattr pointer's memory happens to start out non-zero.
Also fixed the itemizing of an alt-dest file's xattrs when hard-linking.
- Don't send a bogus "-" option to an older server if there were no short
options specified.
- Fixed skipping of unneeded updates in a batch file when incremental
recursion is active. Added a test for this. Made batch-mode handle
"redo" files properly (and without hanging).
- Fix the %P logfile escape when the daemon logs from inside a chroot.
- Fixed the use of -s (--protect-args) when used with a remote source or
destination that had an empty path (e.g. "host:"). Also fixed a problem
when -s was used when accessing a daemon via a remote-shell.
- Fixed the use of a dot-dir path (e.g. foo/./bar) inside a --files-from
file when the root of the transfer isn't the current directory.
- Fixed a bug with "-K --delete" removing symlinks to directories when
incremental recursion is active.
- Fixed a hard to trigger hang when using --remove-source-files.
- Got rid of an annoying delay when accessing a daemon via a remote-shell.
- Properly ignore (superfluous) source args on a --read-batch command.
- Improved the manpage's description of the '*' wildcard to remove the
confusing "non-empty" qualifier.
- Fixed reverse lookups in the compatibility-library version of
getnameinfo().
- Fixed a bug when using --sparse on a sparse file that has over 2GB of
consecutive sparse data.
- Avoid a hang when using at least 3 --verbose options on a transfer with a
client sender (which includes local copying).
- Fixed a problem with --delete-delay reporting an error when it was ready
to remove a directory that was now gone.
- Got rid of a bunch of "warn_unused_result" compiler warnings.
- If an ftruncate() on a received file fails, it now causes a partial-
transfer warning.
- Allow a path with a leading "//" to be preserved (CYGWIN only).
ENHANCEMENTS:
- Made the support/atomic-rsync script able to perform a fully atomic
update of the copied hierarchy when the destination is setup using a
particular symlink idiom.
NEWS for rsync 3.0.4 (6 Sep 2008)
Protocol: 30 (unchanged)
Changes since 3.0.3:
BUG FIXES:
- Fixed a bug in the hard-linking code where it would sometimes try to
allocate 0 bytes of memory (which fails on some OSes, such as AIX).
- Fixed the hard-linking of files from a device that has a device number
of 0 (which seems to be a common device number on NetBSD).
- Fixed the handling of a --partial-dir that cannot be created. This
particularly impacts the --delay-updates option (since the files cannot
be delayed without a partial-dir), and was potentially destructive if
the --remove-source-files was also specified.
- Fixed a couple issues in the --fake-super handling of xattrs when the
destination files have root-level attributes (e.g. selinux values) that
a non-root copy can't affect.
- Improved the keep-alive check in the generator to fire consistently in
incremental-recursion mode when --timeout is enabled.
- The --iconv option now converts the content of a symlink too, instead
of leaving it in the wrong character-set (requires 3.0.4 on both sides
of the transfer).
- When using --iconv, if a filename fails to convert on the receiving side,
this no longer makes deletions in the root-dir of the transfer fail
silently (the user now gets a warning about deletions being disabled
due to IO error as long as --ignore-errors was not specified).
- When using --iconv, if a server-side receiver can't convert a filename,
the error message sent back to the client no longer mangles the name
with the wrong charset conversion.
- Fixed a potential alignment issue in the IRIX ACL code when allocating
the initial "struct acl" object. Also, cast mallocs to avoid warnings.
- Changed some errors that were going to stdout to go to stderr.
- Made human_num() and human_dnum() able to output a negative number
(rather than outputting a cryptic string of punctuation).
ENHANCEMENTS:
- Rsync will avoid sending an -e option to the server if an older protocol
is requested (and thus the option would not be useful). This lets the
user specify the --protocol=29 option to access an overly-restrictive
server that is rejecting the protocol-30 use of -e to the server.
- Improved the message output for an RERR_PARTIAL exit.
DEVELOPER RELATED:
- The Makefile will not halt for just a timestamp change on the Makefile
or the configure files, only for actual changes in content.
- Changed some commands in the testsuite's xattrs.test that called "rsync"
instead of "$RSYNC".
- Enhanced the release scripts to be able to handle a branch release and
to do even more consistency checks on the files.
NEWS for rsync 3.0.3 (29 Jun 2008)
Protocol: 30 (unchanged)
Changes since 3.0.2:
BUG FIXES:
- Fixed a wildcard matching problem in the daemon when a module has
"use chroot" enabled.
- Fixed a crash bug in the hard-link code.
- Fixed the sending of xattr directory information when the code finds a
--link-dest or --copy-dest directory with unchanged xattrs -- the
destination directory now gets these unchanged xattrs properly applied.
- Fixed an xattr-sending glitch that could cause an "Internal abbrev"
error.
- Fixed the combination of --xattrs and --backup.
- The generator no longer allows a '.' dir to be excluded by a daemon-
exclude rule.
- Fixed deletion handling when copying a single, empty directory (with no
files) to a differently named, non-existent directory.
- Fixed the conversion of spaces into dashes in the %M log escape.
- Fixed several places in the code that were not returning the right
errno when a function failed.
- Fixed the backing up of a device or special file into a backup dir.
- Moved the setting of the socket options prior to the connect().
- If rsync exits in the middle of a --progress output, it now outputs a
newline to help prevent the progress line from being overwritten.
- Fixed a problem with how a destination path with a trailing slash or
a trailing dot-dir was compared against the daemon excludes.
- Fixed the sending of large (size > 16GB) files when talking to an older
rsync (protocols < 30): we now use a compatible block size limit.
- If a file's length is so huge that we overflow a checksum buffer count
(i.e. several hundred TB), warn the user and avoid sending an invalid
checksum struct over the wire.
- If a source arg is excluded, --relative no longer adds the excluded
arg's implied dirs to the transfer. This fix also made the exclude
check happen in the better place in the sending code.
- Use the overflow_exit() function for overflows, not out_of_memory().
- Improved the code to better handle a system that has only 32-bit file
offsets.
ENHANCEMENTS:
- The rsyncd.conf manpage now consistently refers to the parameters in
the daemon config file as "parameters".
- The description of the --inplace option was improved.
EXTRAS:
- Added a new script in the support directory, deny-rsync, which allows
an admin to (temporarily) replace the rsync command with a script that
sends an error message to the remote client via the rsync protocol.
DEVELOPER RELATED:
- Fixed a testcase failure if the tests are run as root and made some
compatibility improvements.
- Improved the daemon tests, including checking module comments, the
listing of files, and the ensuring that daemon excludes can't affect
a dot-dir arg.
- Improved some build rules for those that build in a separate directory
from the source, including better install rules for the man pages, and
the fixing of a proto.h-tstamp rule that could make the binaries get
rebuild without cause.
- Improved the testsuite to work around a problem with some utilities
(e.g. cp -p & touch -r) rounding sub-second timestamps.
- Ensure that the early patches don't cause any generated-file hunks to
bleed-over into patches that follow.
NEWS for rsync 3.0.2 (8 Apr 2008)
Protocol: 30 (unchanged)
Changes since 3.0.1:
BUG FIXES:
- Fixed a potential buffer overflow in the xattr code.
ENHANCEMENTS:
- None.
DEVELOPER RELATED:
- The RPM spec file was improved to install more useful files.
- A few developer-oriented scripts were moved from the support dir
to the packaging dir.
NEWS for rsync 3.0.1 (3 Apr 2008)
Protocol: 30 (unchanged)
Changes since 3.0.0:
NOTABLE CHANGES IN BEHAVIOR:
- Added the 'c'-flag to the itemizing of non-regular files so that the
itemized output doesn't get hidden if there were no attribute changes,
and also so that the itemizing of a --copy-links run will distinguish
between copying an identical non-regular file and the creation of a
revised version with a new value (e.g. a changed symlink referent, a
new device number, etc.).
BUG FIXES:
- Fixed a crash bug when a single-use rsync daemon (via remote shell) was
run without specifying a --config=FILE option.
- Fixed a crash when backing up a directory that has a default ACL.
- Fixed a bug in the handling of xattr values that could cause rsync to
not think that a file's extended attributes are up-to-date.
- Fixed the working of --fake-super with --link-dest and --xattrs.
- Fixed a hang when combining --dry-run with --remove-source-files.
- Fixed a bug with --iconv's handling of files that cannot be converted:
a failed name can no longer cause a transfer failure.
- Fixed the building of the rounding.h file on systems that need custom
CPPFLAGS to be used. Also improved the error reporting if the building
of rounding.h fails.
- Fixed the use of the --protect-args (-s) option when talking to a daemon.
- Fixed the --ignore-existing option's protection of files on the receiver
that are non-regular files on the sender (e.g. if a symlink or a dir on
the sender is trying to replace a file on the receiver). The reverse
protection (protecting a dir/symlink/device from being replaced by a
file) was already working.
- Fixed an assert failure if --hard-links is combined with an option that
can skip a file in a set of hard-linked files (i.e. --ignore-existing,
--append, etc.), without skipping all the files in the set.
- Avoid setting the modify time on a directory that already has the right
modify time set. This avoids tweaking the dir's ctime.
- Improved the daemon-exclude handling to do a better job of applying the
exclude rules to path entries. It also sends the user an error just as
if the files were actually missing (instead of silently ignoring the
user's args), and avoids sending the user the filter-action messages
for these non-user-initiated rules.
- Fixed some glitches with the dry-run code's missing-directory
handling, including a problem when combined with --fuzzy.
- Fixed some glitches with the skipped-directory handling.
- Fixed the 'T'-flag itemizing of symlinks when --time isn't preserved.
- Fixed a glitch in the itemizing of permissions with the -E option.
- The --append option's restricting of transfers to those that add data no
longer prevents the updating of non-content changes to otherwise up-to-
date files (i.e. those with the same content but differing permissions,
ownership, xattrs, etc.).
- Don't allow --fake-super to be specified with -XX (double --xattrs)
because the options conflict. If a daemon has "fake super" enabled,
it automatically downgrades a -XX request to -X.
- Fixed a couple bugs in the parsing of daemon-config excludes that could
make a floating exclude rule get treated as matching an absolute path.
- A daemon doesn't try to auto-refuse the "iconv" option if iconv-support
wasn't compiled in to the daemon (avoiding a warning in the logs).
- Fixed the inclusion of per-dir merge files from implied dirs.
- Fixed the support/rrsync script to work with the latest options that
rsync sends (including its flag-specifying use of -e to the server).
ENHANCEMENTS:
- Added the --old-dirs (--old-d) option to make it easier for a user to
ask for file-listings with older rsync versions (this is easier than
having to type "-r --exclude='/*/*'" manually).
- When getting an error while asking an older rsync daemon for a file
listing, rsync will try to notice if the error is a rejection of the
--dirs (-d) option and let the user know how to work around the issue.
- Added a few more --no-OPTION overrides.
- Improved the documentation of the --append option.
- Improved the documentation of the filter/exclude/include daemon
parameters.
INTERNAL:
- Fixed a couple minor bugs in the included popt library (ones which I
sent to the official popt project for inclusion in the 1.14 release).
- Fixed a stat() call that should have been do_stat() so that the proper
normal/64-bit stat() function gets called. (Was in an area that should
not have caused problems, though.)
- Changed the file-glob code to do a directory scan without using the
"glob" and "glob.h". This lets us do the globbing with less memory
churn, and also avoid adding daemon-excluded items to the returned
args.
DEVELOPER RELATED:
- The configure script tries to get the user's compiler to not warn about
unused function parameters if the build is not including one or more of
the ACL/xattrs/iconv features.
- The configure script now has better checks for figuring out if the
included popt code should be used or not.
- Fixed two testsuite glitches: avoid a failure if someone's "cd" command
outputs the current directory when cd-ing to a relative path, and made
the itemized test query how rsync was built to determine if it should
expect hard-linked symlinks or not.
- Updated the testsuite to verify that various bug fixes remain fixed.
- The RPM spec file was updated to have: (1) comments for how to use the
rsync-patch tar file, and (2) an /etc/xinetd.d/rsync file.
- Updated the build scripts to work with a revised FTP directory
structure.
NEWS for rsync 3.0.0 (1 Mar 2008)
Protocol: 30 (changed)
Changes since 2.6.9:
NOTABLE CHANGES IN BEHAVIOR:
- The handling of implied directories when using --relative has changed to
send them as directories (e.g. no implied dir is ever sent as a symlink).
This avoids unexpected behavior and should not adversely affect most
people. If you're one of those rare individuals 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.)
Also, exclude rules no longer have a partial effect on implied dirs.
- Requesting a remote file-listing 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.
- In --dry-run mode, the last line of the verbose summary text is output
with a "(DRY RUN)" suffix to help remind you that no updates were made.
Similarly, --only-write-batch outputs "(BATCH ONLY)".
- A writable rsync daemon with "use chroot" disabled now defaults to a
symlink-munging behavior designed to make symlinks safer while also
allowing absolute symlinks to be stored and retrieved. This also has
the effect of making symlinks unusable while they're in the daemon's
hierarchy. See the daemon's "munge symlinks" parameter for details.
- Starting up an extra copy of an rsync daemon will not clobber the pidfile
for the running daemon -- if the pidfile exists, the new daemon will exit
with an error. This means that your wrapper script that starts the rsync
daemon should be made to handle lock-breaking (if you want any automatic
breaking of locks to be done).
BUG FIXES:
- A daemon with "use chroot = no" and excluded items listed in the daemon
config file now properly checks an absolute-path arg specified for these
options: --compare-dest, --link-dest, --copy-dest, --partial-dir,
--backup-dir, --temp-dir, and --files-from.
- A daemon can now be told to disable all user- and group-name translation
on a per-module basis. This avoids a potential problem with a writable
daemon module that has "use chroot" enabled -- if precautions weren't
taken, a user could try to add a missing library and get rsync to use
it. This makes rsync safer by default, and more configurable when id-
translation is not desired. See the daemon's "numeric ids" parameter
for full details.
- A chroot daemon can now indicate which part of its path should affect the
chroot call, and which part should become an inside-chroot path for the
module. This allows you to have outside-the-transfer paths (such as for
libraries) even when you enable chroot protection. The idiom used in the
rsyncd.conf file is: path = /chroot/dirs/./dirs/inside
- If a file's data arrived successfully on the receiving side but the
rename of the temporary file to the destination file failed AND the
--remove-source-files (or the deprecated --remove-sent-files) option
was specified, rsync no longer erroneously removes the associated
source file.
- Fixed the output of -ii when combined with one of the --*-dest options:
it now itemizes all the items, not just the changed ones.
- Made the output of all file types consistent when using a --*-dest
option. Prior versions would output too many creation events for
matching items.
- 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.
- A negated filter rule (i.e. with a '!' modifier) no longer loses the
negation when sending the filter rules to the remote rsync.
- Fixed a problem with the --out-format (aka --log-format) option %f: it
no longer outputs superfluous directory info for a non-daemon rsync.
- Fixed a problem with -vv (double --verbose) and --stats when "pushing"
files (which includes local copies). Version 2.6.9 would complete the
copy, but exit with an error when the receiver output its memory stats.
- If --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.
- Make sure that directory permissions of a newly-created destination
directory are handled right when --perms is left off.
- The itemized output of a newly-created destination directory is now
output as a creation event, not a change event.
- Improved --hard-link so that more corner cases are handled correctly
when combined with options such as --link-dest and/or --ignore-existing.
- The --append option no longer updates a file that has the same size.
- Fixed a bug when combining --backup and --backup-dir with --inplace:
any missing backup directories are now created.
- Fixed a bug when using --backup and --inplace with --whole-file or
--read-batch: backup files are actually created now.
- The daemon pidfile is checked and created sooner in the startup sequence.
- If a daemon module's "path" value is not an absolute pathname, the code
now makes it absolute internally (making it work properly).
- Ensure that a temporary file always has owner-write permission while we
are writing to it. This avoids problems with some network filesystems
when transfering read-only files.
- Any errors output about password-file reading no longer cause an error at
the end of the run about a partial transfer.
- The --read-batch option for protocol 30 now ensures that several more
options are set correctly for the current batch file: --iconv, --acls,
--xattrs, --inplace, --append, and --append-verify.
- Using --only-write-batch to a daemon receiver now works properly (older
versions would update some files while writing the batch).
- Avoid outputting a "file has vanished" message when the file is a broken
symlink and --copy-unsafe-links or --copy-dirlinks is used (the code
already handled this for --copy-links).
- Fixed the combination of --only-write-batch and --dry-run.
- Fixed rsync's ability to remove files that are not writable by the file's
owner when rsync is running as the same user.
- When transferring large files, the sender's hashtable of checksums is
kept at a more reasonable state of fullness (no more than 80% full) so
that the scanning of the hashtable will not bog down as the number of
blocks increases.
ENHANCEMENTS:
- 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.
- Lowered memory use in the non-incremental-recursion algorithm for typical
option values (usually saving from 21-29 bytes per file).
- The default --delete algorithm is now --delete-during when talking to a
3.x rsync. This is a faster scan than using --delete-before (which is
the default when talking to older rsync versions), and is compatible with
the new incremental recursion mode.
- 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 an empty one
(e.g. empty: :file1 or ::module/file2). For example, this means that
local use of brace expansion now works: rsync -av host:dir/{f1,f2} .
- Added the --protect-args (-s) option, that tells rsync to send most of
the command-line args at the start of the transfer rather than as args
to the remote-shell command. This protects them from space-splitting,
and only interprets basic wildcard special shell characters (*?[).
- Added the --delete-delay option, which is a more efficient way to delete
files at the end of the transfer without needing a separate delete pass.
- Added the --acls (-A) option to preserve Access Control Lists. This is
an improved version of the prior patch that was available, and it even
supports OS X ACLs. If you need to have backward compatibility with old,
ACL-patched versions of rsync, apply the acls.diff file from the patches
dir.
- Added the --xattrs (-X) option to preserve extended attributes. This is
an improved version of the prior patch that was available, and it even
supports OS X xattrs (which includes their resource fork data). If you
need to have backward compatibility with old, xattr-patched versions of
rsync, apply the xattrs.diff file from the patches dir.
- Added the --fake-super option that allows a non-super user to preserve
all attributes of a file by using a special extended-attribute idiom.
It even supports the storing of foreign ACL data on your backup server.
There is also an analogous "fake super" parameter for an rsync daemon.
- Added the --iconv option, which allows rsync to convert filenames from
one character-set to another during the transfer. The default is to
make this feature available as long as your system has iconv_open().
If compilation fails, specify --disable-iconv to configure, and then
rebuild. If you want rsync to perform character-set conversions by
default, you can specify --enable-iconv=CONVERT_STRING with the default
value for the --iconv option that you wish to use. For example,
"--enable-iconv=." is a good choice. See the rsync manpage for an
explanation of the --iconv option's settings.
- A new daemon config parameter, "charset", lets you control the character-
set that is used during an --iconv transfer to/from a daemon module. You
can also set your daemon to refuse "no-iconv" if you want to force the
client to use an --iconv transfer (requiring an rsync 3.x client).
- Added the --skip-compress=LIST option to override the default list of
file suffixes that will not be compressed when using --compress (-z).
- The daemon's default for "dont compress" was extended to include:
*.7z *.mp[34] *.mov *.avi *.ogg *.jpg *.jpeg
The name-matching routine was also optimized to run more quickly.
- The --max-delete option now outputs a warning if it skipped any file
deletions, including a count of how many deletions were skipped. (Older
versions just silently stopped deleting things.)
- You may specify --max-delete=0 to a 3.0.0 client to request that it warn
about extraneous files without deleting anything. If you're not sure
what version the client is, you can use the less-obvious --max-delete=-1,
as both old and new versions will treat that as the same request (though
older versions don't warn).
- The --hard-link option now uses less memory on both the sending and
receiving side for all protocol versions. For protocol 30, the use of a
hashtable on the sending side allows us to more efficiently convey to the
receiver what files are linked together. This reduces the amount of data
sent over the socket by a considerable margin (rather than adding more
data), and limits the in-memory storage of the device+inode information
to just the sending side for the new protocol 30, or to the receiving
side when speaking an older protocol (note that older rsync versions kept
the device+inode information on both sides).
- The filter rules now support a perishable ("p") modifier that marks rules
that should not have an effect in a directory that is being deleted. e.g.
-f '-p .svn/' would only affect "live" .svn directories.
- Rsync checks all the alternate-destination args for validity (e.g.
--link-dest). This lets the user know when they specified a directory
that does not exist.
- If we get an ENOSYS error setting the time on a symlink, we don't
complain about it anymore (for those systems that even support the
setting of the modify-time on a symlink).
- Protocol 30 now uses MD5 checksums instead of MD4.
- Changed the --append option to not checksum the existing data in the
destination file, which speeds up file appending.
- Added the --append-verify option, which works like the older --append
option (verifying the existing data in the destination file). For
compatibility with older rsync versions, any use of --append that is
talking protocol 29 or older will revert to the --append-verify method.
- Added the --contimeout=SECONDS option that lets the user specify a
connection timeout for rsync daemon access.
- Documented and extended the support for the RSYNC_CONNECT_PROG variable
that can be used to enhance the client side of a daemon connection.
- Improved the dashes and double-quotes in the nroff manpage output.
- Rsync now supports a lot more --no-OPTION override options.
INTERNAL:
- 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 is also faster
than the glibc version of qsort() and mergesort().
- Rsync now supports the transfer of 64-bit timestamps (time_t values).
- Made the file-deletion code use a little less stack when recursing
through a directory hierarchy of extraneous files.
- Fixed a build problem with older (2.x) versions of gcc.
- Added some isType() functions that make dealing with signed characters
easier without forcing variables via casts.
- Changed strcat/strcpy/sprintf function calls to use safer versions.
- Upgraded the included popt version to 1.10.2 and improved its use of
string-handling functions.
- Added missing prototypes for compatibility functions from the lib dir.
- Configure determines if iconv() has a const arg, allowing us to avoid a
compiler warning.
- Made the sending of some numbers more efficient for protocol 30.
- Make sure that a daemon process doesn't mind if the client was weird and
omitted the --server option.
- There are more internal logging categories available in protocol 30 than
the age-old FINFO and FERROR, including FERROR_XFER and FWARN. These new
categories allow some errors and warnings to go to stderr without causing
an erroneous end-of-run warning about some files not being able to be
transferred.
- Improved the use of "const" on pointers.
- Improved J.W.'s pool_alloc routines to add a way of incrementally freeing
older sections of a pool's memory.
- The getaddrinfo.c compatibility code in the "lib" dir was replaced with
some new code (derived from samba, derived from PostgreSQL) that has a
better license than the old code.
DEVELOPER RELATED:
- Rsync is now licensed under the GPLv3 or later.
- Rsync is now being maintained in a "git" repository instead of CVS
(though the old CVS repository still exists for historical access).
Several maintenance scripts were updated to work with git.
- Generated files are no longer committed into the source repository. The
autoconf and autoheader commands are now automatically run during the
normal use of "configure" and "make". The latest dev versions of all
generated files can also be copied from the samba.org web site (see the
prepare-source script's fetch option).
- The "patches" directory of diff files is now built from branches in the
rsync git repository (branch patch/FOO creates file patches/FOO.diff).
This directory is now distributed in a separate separate tar file named
rsync-patches-VERSION.tar.gz instead of the main rsync-VERSION.tar.gz.
- The proto.h file is now built using a simple perl script rather than a
complex awk script, which proved to be more widely compatible.
- 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,
but another filesystem does).
- 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 safer 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).
- The csprotocol.txt file was updated to mention the daemon protocol change
in the 3.0.0 release.
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 high in clean_flist() was wrong for an empty list.
This could cause flist_find() to crash in certain rare circumstances
(e.g. if just the right directory setup was around when --fuzzy was
combined with --link-dest).
- The outputting of hard-linked files when verbosity was > 1 was not right:
(1) Without -i it would output the name of each hard-linked file as
though it had been changed; it now outputs a "is hard linked" message for
the file. (2) With -i it would output all dots for the unchanged
attributes of a hard-link; it now changes those dots to spaces, as is
done for other totally unchanged items.
- When backing up a changed symlink or device, get rid of any old backup
item so that we don't get an "already exists" error.
- A couple places that were comparing a local and a remote modification-
time were not honoring the --modify-window option.
- Fixed a bug where the 'p' (permissions) itemized-changes flag might get
set too often (if some non-significant mode bits differed).
- Fixed a really old, minor bug that could cause rsync to warn about being
unable to mkdir() a path that ends in "/." because it just created the
directory (required --relative, --no-implied-dirs, a source path that
ended in either a trailing slash or a trailing "/.", and a non-existing
destination dir to tickle the bug in a recent version).
ENHANCEMENTS:
- Made the "max verbosity" setting in the rsyncd.conf file settable on a
per-module basis (which now matches the documentation).
- The support/rrsync script has been upgraded to verify the args of options
that take args (instead of rejecting any such options). The script was
also changed to try to be more secure and to fix a problem in the parsing
of a pull operation that has multiple sources.
- Improved the documentation that explains the difference between a
normal daemon transfer and a daemon-over remote-shell transfer.
- Some of the diffs supplied in the patches dir were fixed and/or
improved.
BUILD CHANGES:
- Made configure define NOBODY_USER (currently hard-wired to "nobody") and
NOBODY_GROUP (set to either "nobody" or "nogroup" depending on what we
find in the /etc/group file).
- Added a test to the test suite, itemized.test, that tests the output of
-i (log-format w/%i) and some double-verbose messages.
NEWS for rsync 2.6.5 (1 Jun 2005)
Protocol: 29 (unchanged)
Changes since 2.6.4:
OUTPUT CHANGES:
- Non-printable chars in filenames are now output using backslash-
escaped characters rather than '?'s. Any non-printable character is
output using 3 digits of octal (e.g. "\n" -> "\012"), and a backslash
is now output as "\\". Rsync also uses your locale setting, which
can make it treat fewer high-bit characters as non-printable.
- If rsync received an empty file-list when pulling files, it would
output a "nothing to do" message and exit with a 0 (success) exit
status, even if the remote rsync returned an error (it did not do
this under the same conditions when pushing files). This was changed
to make the pulling behavior the same as the pushing behavior: we
now do the normal end-of-run outputting (depending on options) and
exit with the appropriate exit status.
BUG FIXES:
- A crash bug was fixed when a daemon had its "path" set to "/", did
not have chroot enabled, and used some anchored excludes in the
rsyncd.conf file.
- Fixed a bug in the transfer of a single file when -H is specified
(rsync would either infinite loop or perhaps crash).
- Fixed a case where the generator might try (and fail) to tweak the
write-permissions of a read-only directory in list-only mode (this
only caused an annoying warning message).
- If --compare-dest or --link-dest uses a locally-copied file as the
basis for an updated version, log this better when --verbose or -i
is in effect.
- Fixed the accidental disabling of --backup during the --delete-after
processing.
- Restored the ability to use the --address option in client mode (in
addition to its use in daemon mode).
- Make sure that some temporary progress information from the delete
processing does not get left on the screen when it is followed by a
newline.
- When --existing skips a directory with extra verbosity, refer to it
as a "directory", not a "file".
- When transferring a single file to a different-named file, any
generator messages that are source-file related no longer refer to
the file by the destination filename.
- Fixed a bug where hard-linking a group of files might fail if the
generator hasn't created a needed destination directory yet.
- Fixed a bug where a hard-linked group of files that is newly-linked
to a file in a --link-dest dir doesn't link the files from the rest
of the cluster.
- When deleting files with the --one-file-system (-x) option set, rsync
no longer tries to remove files from inside a mount-point on the
receiving side. Also, we don't complain about being unable to remove
the mount-point dir.
- Fixed a compatibility problem when using --cvs-ignore (-C) and
sending files to an older rsync without using --delete.
- Make sure that a "- !" or "+ !" include/exclude pattern does not
trigger the list-clearing action that is reserved for "!".
- Avoid a timeout in the generator when the sender/receiver aren't
handling the generator's checksum output quickly enough.
- Fixed the omission of some directories in the delete processing when
--relative (-R) was combined with a source path that had a trailing
slash.
- Fixed a case where rsync would erroneously delete some files and then
re-transfer them when the options --relative (-R) and --recursive
(-r) were both enabled (along with --delete) and a source path had a
trailing slash.
- Make sure that --max-size doesn't affect a device or a symlink.
- Make sure that a system with a really small MAXPATHLEN does not cause
the buffers in readfd_unbuffered() to be too small to receive normal
messages. (This mainly affected Cygwin.)
- If a source pathname ends with a filename of "..", treat it as if
"../" had been specified (so that we don't copy files to the parent
dir of the destination).
- If --delete is combined with a file-listing rsync command (i.e. no
transfer is happening), avoid outputting a warning that we couldn't
delete anything.
- If --stats is specified with --delete-after, ensure that all the
"deleting" messages are output before the statistics.
- Improved one "if" in the deletion code that was only checking errno
for ENOTEMPTY when it should have also been checking for EEXIST (for
compatibility with OS variations).
ENHANCEMENTS:
- Added the --only-write-batch=FILE option that may be used (instead
of --write-batch=FILE) to create a batch file without doing any
actual updating of the destination. This allows you to divert all
the file-updating data away from a slow data link (as long as you
are pushing the data to the remote server when creating the batch).
- When the generator is taking a long time to fill up its output buffer
(e.g. if the transferred files are few, small, or missing), it now
periodically flushes the output buffer so that the sender/receiver
can get started on the files sooner rather than later.
- Improved the keep-alive code to handle a long silence between the
sender and the receiver that can occur when the sender is receiving
the checksum data for a large file.
- Improved the auth-errors that are logged by the daemon to include
some information on why the authorization failed: wrong user,
password mismatch, etc. (The client-visible message is unchanged!)
- Improved the client's handling of an "@ERROR" from a daemon so that
it does not complain about an unexpectedly closed socket (since we
really did expect the socket to close).
- If the daemon can't open the log-file specified in rsyncd.conf, fall
back to using syslog and log an appropriate warning. This is better
than what was typically a totally silent (and fatal) failure (since a
daemon is not usually run with the --no-detach option that was
necessary to see the error on stderr).
- The man pages now consistently refer to an rsync daemon as a "daemon"
instead of a "server" (to distinguish it from the server process in a
non-daemon transfer).
- Made a small change to the rrsync script (restricted rsync -- in the
support dir) to make a read-only server reject all --remove-* options
when sending files (to future-proof it against the possibility of
other similar options being added at some point).
INTERNAL:
- Rsync now calls setlocale(LC_CTYPE, ""). This enables isprint() to
better discern which filename characters need to be escaped in
messages (which should result in fewer escaped characters in some
locales).
- Improved the naming of the log-file open/reopen/close functions.
- Removed some protocol-compatibility code that was only needed to help
someone running a pre-release of 2.6.4.
BUILD CHANGES:
- Added configure option "--disable-locale" to disable any use of
setlocale() in the binary.
- Fixed a bug in the SUPPORT{,_HARD}_LINKS #defines which prevented
rsync from being built without symlink or hard-link support.
- Only #define HAVE_REMSH if it is going to be set to 1.
- Configure now disables the use of mkstemp() under HP-UX (since they
refuse to fix its broken handling of large files).
- Configure now explicitly checks for the lseek64() function so that
the code can use HAVE_LSEEK64 instead of inferring lseek64()'s
presence based on the presence of the off64_t type.
- Configure no longer mentions the change in the default remote-shell
(from rsh to ssh) that occurred for the 2.6.0 release.
- Some minor enhancements to the test scripts.
- Added a few new *.diff files to the patches dir, including a patch
that enables the optional copying of extended attributes.
NEWS for rsync 2.6.4 (30 March 2005)
Protocol: 29 (changed)
Changes since 2.6.3:
OUTPUT CHANGES:
- When rsync deletes a directory and outputs a verbose message about
it, it now appends a trailing slash to the name instead of (only
sometimes) outputting a preceding "directory " string.
- The --stats output will contain file-list time-statistics if both
sides are 2.6.4, or if the local side is 2.6.4 and the files are
being pushed (since the stats come from the sending side).
(Requires protocol 29 for a pull.)
- The "%o" (operation) log-format escape now has a third value (besides
"send" and "recv"): "del." (with trailing dot to make it 4 chars).
This changes the way deletions are logged in the daemon's log file.
- When the --log-format option is combined with --verbose, rsync now
avoids outputting the name of the file twice in most circumstances.
As long as the --log-format item does not refer to any post-transfer
items (such as %b or %c), the --log-format message is output prior to
the transfer, so --verbose is now the equivalent of a --log-format of
'%n%L' (which outputs the name and any link info). If the log output
must occur after the transfer to be complete, the only time the name
is also output prior to the transfer is when --progress was specified
(so that the name will precede the progress stats, and the full
--log-format output will come after).
- Non-printable characters in filenames are replaced with a '?' to
avoid corrupting the screen or generating empty lines in the output.
BUG FIXES:
- Restore the list-clearing behavior of "!" in a .cvsignore file (2.6.3
was only treating it as a special token in an rsync include/exclude
file).
- The combination of --verbose and --dry-run now mentions the full list
of changes that would be output without --dry-run.
- Avoid a mkdir warning when removing a directory in the destination
that already exists in the --backup-dir.
- An OS that has a binary mode for its files (such as cygwin) needed
setmode(fd, O_BINARY) called on the temp-file we opened with
mkstemp(). (Fix derived from cygwin's 2.6.3 rsync package.)
- Fixed a potential hang when verbosity is high, the client side is
the sender, and the file-list is large.
- Fixed a potential protocol-corrupting bug where the generator could
merge a message from the receiver into the middle of a multiplexed
packet of data if only part of that data had been written out to the
socket when the message from the generator arrived.
- We now check if the OS doesn't support using mknod() for creating
FIFOs and sockets, and compile-in some compatibility code using
mkfifo() and socket() when necessary.
- Fixed an off-by-one error in the handling of --max-delete=N. Also,
if the --max-delete limit is exceeded during a run, we now output a
warning about this at the end of the run and exit with a new error
code (25).
- One place in the code wasn't checking if fork() failed.
- The "ignore nonreadable" daemon parameter used to erroneously affect
readable symlinks that pointed to a non-existent file.
- If the OS does not have lchown() and a chown() of a symlink will
affect the referent of a symlink (as it should), we no longer try
to set the user and group of a symlink.
- The generator now properly runs the hard-link loop and the dir-time
rewriting loop after we're sure that the redo phase is complete.
- When --backup was specified with --partial-dir=DIR, where DIR is a
relative path, the backup code was erroneously trying to backup a
file that was put into the partial-dir.
- If a file gets resent in a single transfer and the --backup option is
enabled along with --inplace, rsync no longer performs a duplicate
backup (it used to overwrite the first backup with the failed file).
- One call to flush_write_file() was not being checked for an error.
- The --no-relative option was not being sent from the client to a
server sender.
- If an rsync daemon specified "dont compress = ..." for a file and the
client tried to specify --compress, the libz code was not handling a
compression level of 0 properly. This could cause a transfer failure
if the block-size for a file was large enough (e.g. rsync might have
exited with an error for large files).
- Fixed a bug that would sometimes surface when using --compress and
sending a file with a block-size larger than 64K (either manually
specified, or computed due to the file being really large). Prior
versions of rsync would sometimes fail to decompress the data
properly, and thus the transferred file would fail its verification.
- If a daemon can't open the specified log file (i.e. syslog is not
being used), die without crashing. We also output an error about
the failure on stderr (which will only be seen if --no-detach was
specified) and exit with a new error code (6).
- A local transfer no longer duplicates all its include/exclude options
(since the forked process already has a copy of the exclude list,
there's no need to send them a set of duplicates).
- The output of the items that are being updated by the generator (dirs,
symlinks, devices) is now intermingled in the proper order with the
output from the items that the receiver is updating (regular files)
when pulling. This misordering was particularly bad when --progress
was specified. (Requires protocol 29.)
- When --timeout is specified, lulls that occur in the transfer while
the generator is doing work that does not generate socket traffic
(looking for changed files, deleting files, doing directory-time
touch-ups, etc.) will cause a new keep-alive packet to be sent that
should keep the transfer going as long as the generator continues to
make progress. (Requires protocol 29.)
- The stat size of a device is not added to the total file size of the
items in the transfer (the size might be undefined on some OSes).
- Fixed a problem with refused-option messages sometimes not making it
back to the client side when a remote --files-from was in effect and
the daemon was the receiver.
- The --compare-dest option was not updating a file that differed in
(the preserved) attributes from the version in the compare-dest DIR.
- When rsync is copying files into a write-protected directory, fixed
the change-report output for the directory so that we don't report
an identical directory as changed.
ENHANCEMENTS:
- Rsync now supports popt's option aliases, which means that you can
use /etc/popt and/or ~/.popt to create your own option aliases.
- Added the --delete-during (--del) option which will delete files
from the receiving side incrementally as each directory in the
transfer is being processed. This makes it more efficient than the
default, before-the-transfer behavior, which is now also available as
--delete-before (and is still the default --delete-WHEN option that
will be chosen if --delete or --delete-excluded is specified without
a --delete-WHEN choice). All the --del* options infer --delete, so
an rsync daemon that refuses "delete" will still refuse to allow any
file-deleting options (including the new --remove-sent-files option).
- All the --delete-WHEN options are now more memory efficient:
Previously an duplicate set of file-list objects was created on the
receiving side for the entire destination hierarchy. The new
algorithm only creates one directory of objects at a time (for files
inside the transfer).
- Added the --copy-dest option, which works like --link-dest except
that it locally copies identical files instead of hard-linking them.
- Added support for specifying multiple --compare-dest, --copy-dest, or
--link-dest options, but only of a single type. (Promoted from the
patches dir and enhanced.) (Requires protocol 29.)
- Added the --max-size option. (Promoted from the patches dir.)
- The daemon-mode options are now separated from the normal rsync
options so that they can't be mixed together. This makes it
impossible to start a daemon that has improper default option values
(which could cause problems when a client connects, such as hanging
or crashing).
- The --bwlimit option may now be used in combination with --daemon
to specify both a default value for the daemon side and a value
that cannot be exceeded by a user-specified --bwlimit option.
- Added the "port" parameter to the rsyncd.conf file. (Promoted from
the patches dir.) Also added "address". The command-line options
take precedence over a config-file option, as expected.
- In _exit_cleanup(): when we are exiting with a partially-received
file, we now flush any data in the write-cache before closing the
partial file.
- The --inplace support was enhanced to work with --compare-dest,
--link-dest, and (the new) --copy-dest options. (Requires protocol
29.)
- Added the --dirs (-d) option for an easier way to copy directories
without recursion. Any directories that are encountered are created
on the destination. Specifying a directory with a trailing slash
copies its immediate contents to the destination.
- The --files-from option now implies --dirs (-d).
- Added the --list-only option, which is mainly a way for the client to
put the server into listing mode without needing to resort to any
internal option kluges (e.g. the age-old use of "-r --exclude="/*/*"
for a non-recursive listing). This option is used automatically
(behind the scenes) when a modern rsync speaks to a modern daemon,
but may also be specified manually if you want to force the use of
the --list-only option over a remote-shell connection.
- Added the --omit-dir-times (-O) option, which will avoid updating
the modified time for directories when --times was specified. This
option will avoid an extra pass through the file-list at the end of
the transfer (to tweak all the directory times), which may provide
an appreciable speedup for a really large transfer. (Promoted from
the patches dir.)
- Added the --filter (-f) option and its helper option, -F. Filter
rules are an extension to the existing include/exclude handling
that also supports nested filter files as well as per-directory
filter files (like .cvsignore, but with full filter-rule parsing).
This new option was chosen in order to ensure that all existing
include/exclude processing remained 100% compatible with older
versions. Protocol 29 is needed for full filter-rule support, but
backward-compatible rules work with earlier protocol versions.
(Promoted from the patches dir and enhanced.)
- Added the --delay-updates option that puts all updated files into
a temporary directory (by default ".~tmp~", but settable via the
--partial-dir=DIR option) until the end of the transfer. This
makes the updates a little more atomic for a large transfer.
- If rsync is put into the background, any output from --progress is
reduced.
- Documented the "max verbosity" setting for rsyncd.conf. (This
setting was added a couple releases ago, but left undocumented.)
- The sender and the generator now double-check the file-list index
they are given, and refuse to try to do a file transfer on a
non-file index (since that would indicate that something had gone
very wrong).
- Added the --itemize-changes (-i) option, which is a way to output a
more detailed list of what files changed and in what way. The effect
is the same as specifying a --log-format of "%i %n%L" (see both the
rsync and rsyncd.conf manpages). Works with --dry-run too.
- Added the --fuzzy (-y) option, which attempts to find a basis file
for a file that is being created from scratch. The current algorithm
only looks in the destination directory for the created file, but it
does attempt to find a match based on size/mod-time (in case the file
was renamed with no other changes) as well as based on a fuzzy
name-matching algorithm. This option requires protocol 29 because it
needs the new file-sorting order. (Promoted from patches dir and
enhanced.) (Requires protocol 29.)
- Added the --remove-sent-files option, which lets you move files
between systems.
- The hostname in HOST:PATH or HOST::PATH may now be an IPv6 literal
enclosed in '[' and ']' (e.g. "[::1]"). (We already allowed IPv6
literals in the rsync://HOST:PORT/PATH format.)
- When rsync recurses to build the file list, it no longer keeps open
one or more directory handles from the dir's parent dirs.
- When building under windows, the default for --daemon is now to
avoid detaching, requiring the new --detach option to force rsync
to detach.
- The --dry-run option can now be combined with either --write-batch or
--read-batch, allowing you to run a do-nothing test command to see
what would happen without --dry-run.
- The daemon's "read only" config item now sets an internal read_only
variable that makes extra sure that no write/delete calls on the
read-only side can succeed.
- The log-format % escapes can now have a numeric field width in
between the % and the escape letter (e.g. "%-40n %08p").
- Improved the option descriptions in the --help text.
SUPPORT FILES:
- Added atomic-rsync to the support dir: a perl script that will
transfer some files using rsync, and then move the updated files into
place all at once at the end of the transfer. Only works when
pulling, and uses --link-dest and a parallel hierarchy of files to
effect its update.
- Added mnt-excl to the support dir: a perl script that takes the
/proc/mounts file and translates it into a set of excludes that will
exclude all mount points (even mapped mounts to the same disk). The
excludes are made relative to the specified source dir and properly
anchored.
- Added savetransfer.c to the support dir: a C program that can make
a copy of all the data that flows over the wire. This lets you test
for data corruption (by saving the data on both the sending side and
the receiving side) and provides one way to debug a protocol error.
- Added rrsync to the support dir: this is an updated version of Joe
Smith's restricted rsync perl script. This helps to ensure that only
certain rsync commands can be run by an ssh invocation.
INTERNAL:
- Added better checking of the checksum-header values that come over
the socket.
- Merged a variety of file-deleting functions into a single function so
that it is easier to maintain.
- Improved the type of some variables (particularly blocksize vars) for
consistency and proper size.
- Got rid of the uint64 type (which we didn't need).
- Use a slightly more compatible set of core #include directives.
- Defined int32 in a way that ensures that the build dies if we can't
find a variable with at least 32 bits.
PROTOCOL DIFFERENCES FOR VERSION 29:
- A 16-bit flag-word is transmitted after every file-list index. This
indicates what is changing between the sender and the receiver. The
generator now transmits an index and a flag-word to indicate when
dirs and symlinks have changed (instead of producing a message),
which makes the outputting of the information more consistent and
less prone to screen corruption (because the local receiver/sender is
now outputting all the file-change info messages).
- If a file is being hard-linked, the ITEM_XNAME_FOLLOWS bit is enabled
in the flag-word and the name of the file that was linked immediately
follows in vstring format (see below).
- If a file is being transferred with an alternate-basis file, the
ITEM_BASIS_TYPE_FOLLOWS bit is enabled in the flag-word and a single
byte follows, indicating what type of basis file was chosen. If that
indicates that a fuzzy-match was selected, the ITEM_XNAME_FOLLOWS bit
is set in the flag-word and the name of the match in vstring format
follows the basis byte. A vstring is a variable length string that
has its size written prior to the string, and no terminating null.
If the string is from 1-127 bytes, the length is a single byte. If
it is from 128-32767 bytes, the length is written as ((len >> 8) |
0x80) followed by (len % 0x100).
- The sending of exclude names is done using filter-rule syntax. This
means that all names have a prefixed rule indicator, even excludes
(which used to be sent as a bare pattern, when possible). The -C
option will include the per-dir .cvsignore merge file in the list of
filter rules so it is positioned correctly (unlike in some older
transfer scenarios).
- Rsync sorts the filename list in a different way: it sorts the subdir
names after the non-subdir names for each dir's contents, and it
always puts a dir's contents immediately after the dir's name in the
list. (Previously an item named "foo.txt" would sort in between
directory "foo/" and "foo/bar".)
- When talking to a protocol 29 rsync daemon, a list-only request
is able to note this before the options are sent over the wire and
the new --list-only option is included in the options.
- When the --stats bytes are sent over the wire (or stored in a batch),
they now include two elapsed-time values: one for how long it took to
build the file-list, and one for how long it took to send it over the
wire (each expressed in thousandths of a second).
- When --delete-excluded is specified with some filter rules (AKA
excludes), a client sender will now initiate a send of the rules to
the receiver (older protocols used to omit the sending of excludes in
this situation since there were no receiver-specific rules that
survived --delete-excluded back then). Note that, as with all the
filter-list sending, only items that are significant to the other
side will actually be sent over the wire, so the filter-rule list
that is sent in this scenario is often empty.
- An index equal to the file-list count is sent as a keep-alive packet
from the generator to the sender, which then forwards it on to the
receiver. This normally invalid index is only a valid keep-alive
packet if the 16-bit flag-word that follows it contains a single bit
(ITEM_IS_NEW, which is normally an illegal flag to appear alone).
- A protocol-29 batch file includes a bit for the setting of the --dirs
option and for the setting of the --compress option. Also, the shell
script created by --write-batch will use the --filter option instead
of --exclude-from to capture any filter rules.
BUILD CHANGES:
- Handle an operating system that use mkdev() in place of makedev().
- Improved configure to better handle cross-compiling.
NEWS for rsync 2.6.3 (30 Sep 2004)
Protocol: 28 (unchanged)
Changes since 2.6.2:
SECURITY FIXES:
- A bug in the sanitize_path routine (which affects a non-chrooted
rsync daemon) could allow a user to craft a pathname that would get
transformed into an absolute path for certain options (but not for
file-transfer names). If you're running an rsync daemon with chroot
disabled, *please upgrade*, ESPECIALLY if the user privs you run
rsync under is anything above "nobody".
OUTPUT CHANGES (ATTN: those using a script to parse the verbose output):
- Please note that the 2-line footer (output when verbose) now uses the
term "sent" instead of "wrote" and "received" instead of "read". If
you are not parsing the numeric values out of this footer, a script
would be better off using the empty line prior to the footer as the
indicator that the verbose output is over.
- The output from the --stats option was similarly affected to change
"written" to "sent" and "read" to "received".
- Rsync ensures that a filename that contains a newline gets mentioned
with each newline transformed into a question mark (which prevents a
filename from causing an empty line to be output).
- The "backed up ..." message that is output when at least 2 --verbose
options are specified is now the same both with and without the
--backup-dir option.
BUG FIXES:
- Fixed a crash bug that might appear when --delete was used and
multiple source directories were specified.
- Fixed a 32-bit truncation of the file length when generating the
checksums.
- The --backup code no longer attempts to create some directories
over and over again (generating warnings along the way).
- Fixed a bug in the reading of the secrets file (by the daemon) and
the password file (by the client): the files no longer need to be
terminated by a newline for their content to be read in.
- If a file has a read error on the sending side or the reconstructed
data doesn't match the expected checksum (perhaps due to the basis
file changing during the transfer), the receiver will no longer
retain the resulting file unless the --partial option was specified.
(Note: for the read-error detection to work, neither side can be
older than 2.6.3 -- older receivers will always retain the file, and
older senders don't tell the receiver that the file had a read
error.)
- If a file gets resent in a single transfer and the --backup option
is enabled, rsync no longer performs a duplicate backup (it used to
overwrite the original file in the backup area).
- Files specified in the daemon's "exclude" or "exclude from" config
items are now excluded from being uploaded (assuming that the module
allows uploading at all) in addition to the old download exclusion.
- Got rid of a potential hang in the receiver when near the end of a
phase.
- When using --backup without a --backup-dir, rsync no longer preserves
the modify time on directories. This avoids confusing NFS.
- When --copy-links (-L) is specified, we now output a separate error
for a symlink that has no referent instead of claiming that a file
"vanished".
- The --copy-links (-L) option no longer has the side-effect of telling
the receiving side to follow symlinks. See the --keep-dirlinks
option (mentioned below) for a way to specify that behavior.
- Error messages from the daemon server's option-parsing (such as
refused options) are now successfully transferred back to the client
(the server used to fail to send the message because the socket
wasn't in the right state for the message to get through).
- Most transfer errors that occur during a daemon transfer are now
returned to the user in addition to being logged (some messages are
intended to be daemon-only and are not affected by this).
- Fixed a bug in the daemon authentication code when using one of the
batch-processing options.
- We try to work around some buggy IPv6 implementations that fail to
implement IPV6_V6ONLY. This should fix the "address in use" error
that some daemons get when running on an OS with a buggy IPv6
implementation. Also, if the new code gets this error, we might
suggest that the user specify --ipv4 or --ipv6 (if we think it will
help).
- When the remote rsync dies, make a better effort to recover any error
messages it may have sent before dying (the local rsync used to just
die with a socket-write error).
- When using --delete and a --backup-dir that contains files that are
hard-linked to their destination equivalents, rsync now makes sure
that removed files really get removed (avoids a really weird rename()
behavior).
- Avoid a bogus run-time complaint about a lack of 64-bit integers when
the int64 type is defined as an off_t and it actually has 64-bits.
- Added a configure check for open64() without mkstemp64() so that we
can avoid using mkstemp() when such a combination is encountered.
This bypasses a problem writing out large temp files on OSes such as
AIX and HP-UX.
- Fixed an age-old crash problem with --read-batch on a local copy
(rsync was improperly assuming --whole-file for the local copy).
- When --dry-run (-n) is used and the destination directory does not
exist, rsync now produces a correct report of files that would be
sent instead of dying with a chdir() error.
- Fixed a bug that could cause a slow-to-connect rsync daemon to die
with an error instead of waiting for the connection to finish.
- Fixed an ssh interaction that could cause output to be lost when the
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
(temporarily) put a partially transferred file (instead of over-
writing the destination file). E.g. --partial-dir=.rsync-partial
Also added support for the RSYNC_PARTIAL_DIR environment variable
that, when found, transforms a regular --partial option (such as
the convenient -P option) into one that also specifies a directory.
- Added --keep-dirlinks (-K), which allows you to symlink a directory
onto another partition on the receiving side and have rsync treat it
as matching a normal directory from the sender.
- Added the --inplace option that tells rsync to write each destination
file without using a temporary file. The matching of existing data
in the destination file can be severely limited by this, but there
are also cases where this is more efficient (such as appending data).
Use only when needed (see the man page for more details).
- Added the "write only" option for the daemon's config file.
- Added long-option names for -4 and -6 (namely --ipv4 and --ipv6)
and documented all these options in the man page.
- Improved the handling of the --bwlimit option so that it's less
bursty, more accurate, and works properly over a larger range of
values.
- The rsync daemon-over-ssh code now looks for SSH_CONNECTION and
SSH2_CLIENT in addition to SSH_CLIENT to figure out the IP address.
- Added the --checksum-seed=N option for advanced users.
- Batch writing/reading has a brand-new implementation that is simpler,
fixes a few weird problems with the old code (such as no longer
sprinkling the batch files into different dirs or even onto different
systems), and is much less intrusive into the code (making it easier
to maintain for the future). The new code generates just one data
file instead of three, which makes it possible to read the batch on
stdin via a remote shell. Also, the old requirement of forcing the
same fixed checksum-seed for all batch processing has been removed.
- If an rsync daemon has a module set with "list = no" (which hides its
presence in the list of available modules), a user that fails to
authenticate gets the same "unknown module" error that they would get
if the module were actually unknown (while still logging the real
error to the daemon's log file). This prevents fishing for module
names.
- The daemon's "refuse options" config item now allows you to match
option names using wildcards and/or the single-letter option names.
- Each transferred file now gets its permissions and modified-time
updated before the temp-file gets moved into place. Previously, the
finished file would have a very brief window where its permissions
disallowed all group and world access.
- Added the ability to parse a literal IPv6 address in an "rsync:" URL
(e.g. rsync://[2001:638:500:101::21]:873/module/dir).
- The daemon's wildcard expanding code can now handle more than 1000
filenames (it's now limited by memory instead of having a hard-wired
limit).
INTERNAL:
- Some cleanup in the exclude code has saved some per-exclude memory
and made the code easier to maintain.
- Improved the argv-overflow checking for a remote command that has a
lot of args.
- Use rsyserr() in the various places that were still calling rprintf()
with strerror() as an arg.
- If an rsync daemon is listening on multiple sockets (to handle both
IPv4 and IPv6 to a single port), we now close all the unneeded file
handles after we accept a connection (we used to close just one of
them).
- Optimized the handling of larger block sizes (rsync used to slow to a
crawl if the block size got too large).
- Optimized away a loop in hash_search().
- Some improvements to the sanitize_path() and clean_fname() functions
makes them more efficient and produce better results (while still
being compatible with the file-name cleaning that gets done on both
sides when sending the file-list).
- Got rid of alloc_sanitize_path() after adding a destination-buffer
arg to sanitize_path() made it possible to put all the former's
functionality into the latter.
- The file-list that is output when at least 4 verbose options are
specified reports the uid value on the sender even when rsync is
not running as root (since we might be sending to a root receiver).
BUILD CHANGES:
- Added a "gen" target to rebuild most of the generated files,
including configure, config.h.in, the man pages, and proto.h.
- If "make proto" doesn't find some changes in the prototypes, the
proto.h file is left untouched (its time-stamp used to always be
updated).
- The variable $STRIP (that is optionally set by the install-strip
target's rule) was changed to $INSTALL_STRIP because some systems
have $STRIP already set in the environment.
- Fixed a build problem when SUPPORT_HARD_LINKS isn't defined.
- When cross-compiling, the gettimeofday() function is now assumed to
be a modern version that takes two-args (since we can't test it).
DEVELOPER RELATED:
- The scripts in the testsuite dir were cleaned up a bit and a few
new tests added.
- Some new diffs were added to the patches dir, and some accepted
ones were removed.
NEWS for rsync 2.6.2 (30 Apr 2004)
Protocol: 28 (unchanged)
Changes since 2.6.1:
BUG FIXES:
- Fixed a major bug in the sorting of the filenames when --relative
is used for some sources (just sources such as "/" and "/*" were
affected). This fix ensures that we ask for the right file-list
item when requesting changes from the sender.
- Rsync now checks the return value of the close() function to
better report disk-full problems on an NFS file system.
- Restored the old daemon-server behavior of logging error messages
rather than returning them to the user. (A better long-term fix
will be sought in the future.)
- An obscure uninitialized-variable bug was fixed in the uid/gid
code. (This bug probably had no ill effects.)
BUILD CHANGES:
- Got rid of the configure check for sys/sysctl.h (it wasn't used
and was causing a problem on some systems). Also improved the
broken-largefile-locking test to try to avoid failure due to an
NFS build-dir.
- Fixed a compile problem on systems that don't define
AI_NUMERICHOST.
- Fixed a compile problem in the popt source for compilers that
don't support __attribute__.
DEVELOPER RELATED:
- Improved the testsuite's "merge" test to work on OSF1.
- Two new diffs were added to the patches dir.
NEWS for rsync 2.6.1 (26 Apr 2004)
Protocol: 28 (changed)
Changes since 2.6.0:
SECURITY FIXES:
- Paths sent to an rsync daemon are more thoroughly sanitized when
chroot is not used. If you're running a non-read-only rsync
daemon with chroot disabled, *please upgrade*, ESPECIALLY if the
user privs you run rsync under is anything above "nobody".
ENHANCEMENTS:
- Lower memory use, more optimal transfer of data over the socket,
and lower CPU usage (see the INTERNAL section for details).
- The RSYNC_PROXY environment variable can now contain a
"USER:PASS@" prefix before the "HOST:PORT" information.
(Bardur Arantsson)
- The --progress output now mentions how far along in the transfer
we are, including both a count of files transferred and a
percentage of the total file-count that we've processed. It also
shows better current-rate-of-transfer and remaining-transfer-time
values.
- Documentation changes now attempt to describe some often mis-
understood features more clearly.
BUG FIXES:
- When -x (--one-file-system) is combined with -L (--copy-links) or
--copy-unsafe-links, no symlinked files are skipped, even if the
referent file is on a different filesystem.
- The --link-dest code now works properly for a non-root user when
(1) the UIDs of the source and destination differ and -o was
specified, or (2) when the group of the source can't be used on
the destination and -g was specified.
- Fixed a bug in the handling of -H (hard-links) that might cause
the expanded PATH/NAME value of the current item to get
overwritten (due to an expanded-name caching bug).
- We now reset the "new data has been sent" flag at the start of
each file we send. This makes sure that an interrupted transfer
with the --partial option set doesn't keep a shorter temp file
than the current basis file when no new data has been transferred
over the wire for that file.
- Fixed a byte-order problem in --batch-mode on big-endian machines.
(Jay Fenlason)
- When using --cvs-exclude, the exclude items we get from a
per-directory's .cvsignore file once again only affect that one
directory (not all following directories too). The items are also
now properly word-split and parsed without any +/- prefix parsing.
- When specifying the USER@HOST: prefix for a file, the USER part
can now contain an '@', if needed (i.e. the last '@' is used to
find the HOST, not the first).
- Fixed some bugs in the handling of group IDs for non-root users:
(1) It properly handles a group that the sender didn't have a name
for (it would previously skip changing the group on any files in
that group). (2) If --numeric-ids is used, rsync no longer
attempts to set groups that the user doesn't have the permission
to set.
- Fixed the "refuse options" setting in the rsyncd.conf file.
- Improved the -x (--one-file-system) flag's handling of any mount-
point directories we encounter. It is both more optimal (in that
it no longer does a useless scan of the contents of the mount-
point dirs) and also fixes a bug where a remapped mount of the
original filesystem could get discovered in a subdir we should be
ignoring.
- Rsync no longer discards a double-slash at the start of a filename
when trying to open the file. It also no longer constructs names
that start with a double slash (unless the user supplied them).
- Path-specifying options to a daemon should now work the same with
or without chroot turned on. Previously, such a option (such as
--link-dest) would get its absolute path munged into a relative
one if chroot was not on, making that setting fairly useless.
Rsync now transforms the path into one that is based on the
module's base dir when chroot is not enabled.
- Fixed a compatibility problem interacting with older rsync
versions that might send us an empty --suffix value without
telling us that --backup-dir was specified.
- The "hosts allow" option for a daemon-over-remote-shell process
now has improved support for IPv6 addresses and a fix for systems
that have a length field in their socket structs.
- Fixed the ability to request an empty backup --suffix when sending
files to an rsync daemon.
- 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
speedup when running under MS Windows. (Craig Barratt)
- Optimizations to the name-handling/comparing code have made some
significant reductions in user-CPU time for large file sets.
- Some cleanup of the variable types make the code more consistent.
- Reduced memory requirements of hard link preservation.
(J.W. Schultz)
- Implemented a new algorithm for hard-link handling that speeds up
the code significantly. (J.W. Schultz and Wayne Davison)
- The --hard-link option now uses the first existing file in the
group of linked files as the basis for the transfer. This
prevents the sub-optimal transfer of a file's data when a new
hardlink is added on the sending side and it sorts alphabetically
earlier in the list than the files that are already present on the
receiving side.
- Dropped support for protocol versions less than 20 (2.3.0 released
15 Mar 1999) and activated warnings for protocols less than 25
(2.5.0 released 23 Aug 2001). (Wayne Davison and J.W. Schultz,
severally)
- More optimal data transmission for --hard-links (protocol 28).
- More optimal data transmission for --checksum (protocol 28).
- Less memory is used when --checksum is specified.
- Less memory is used in the file list (a per-file savings).
- The generator is now better about not modifying the file list
during the transfer in order to avoid a copy-on-write memory
bifurcation (on systems where fork() uses shared memory).
Previously, rsync's shared memory would slowly become unshared,
resulting in real memory usage nearly doubling on the receiving
side by the end of the transfer. Now, as long as permissions
are being preserved, the shared memory should remain that way
for the entire transfer.
- Changed hardlink info and file_struct + strings to use allocation
pools. This reduces memory use for large file-sets and permits
freeing memory to the OS. (J.W. Schultz)
- The 2 pipes used between the receiver and generator processes
(which are forked on the same machine) were reduced to 1 pipe and
the protocol improved so that (1) it is now impossible to have the
"redo" pipe fill up and hang rsync, and (2) trailing messages from
the receiver don't get lost on their way through the generator
over to the sender (which mainly affected hard-link messages and
verbose --stats output).
- Improved the internal uid/gid code to be more portable and a
little more optimized.
- The device numbers sent when using --devices are now sent as
separate major/minor values with 32-bit accuracy (protocol 28).
Previously, the copied devices were sent as a single 32-bit
number. This will make inter-operation of 64-bit binaries more
compatible with their 32-bit brethren (with both ends of the
connection are using protocol 28). Note that optimizations in the
binary protocol for sending the device numbers often results in
fewer bytes being used than before, even though more precision is
now available.
- Some cleanup of the exclude/include structures and its code made
things clearer (internally), simpler, and more efficient.
- The reading & writing of the file-list in batch-mode is now
handled by the same code that sends & receives the list over the
wire. This makes it much easier to maintain. (Note that the
batch code is still considered to be experimental.)
BUILD CHANGES:
- The configure script now accepts --with-rsyncd-conf=PATH to
override the default value of the /etc/rsyncd.conf file.
- Fixed configure bug when running "./configure --disable-ipv6".
- Fixed compilation problem on Tru64 Unix (having to do with
sockaddr.sa_len and sockaddr.sin_len).
DEVELOPER RELATED:
- Fixed "make test" bug when build dir is not the source dir.
- Added a couple extra diffs in the "patches" dir, removed the ones
that got applied, and rebuilt the rest.
NEWS for rsync 2.6.0 (1 Jan 2004)
Protocol: 27 (changed)
Changes since 2.5.7:
ENHANCEMENTS:
* "ssh" is now the default remote shell for rsync. If you want to
change this, configure like this: "./configure --with-rsh=rsh".
* Added --files-from, --no-relative, --no-implied-dirs, and --from0.
Note that --from0 affects the line-ending character for all the
files read by the --*-from options. (Wayne Davison)
* Length of csum2 is now per-file starting with protocol version
27. (J.W. Schultz)
* Per-file dynamic block size is now sqrt(file length). The
per-file checksum size is determined according to an algorithm
provided by Donovan Baarda which reduces the probability of rsync
algorithm corrupting data and falling back using the whole md4
checksums. (J.W. Schultz, Donovan Baarda)
* The --stats option no longer includes the (debug) malloc summary
unless the verbose option was specified at least twice.
* Added a new error/warning code for when files vanish from the
sending side. Made vanished source files not interfere with the
file-deletion pass when --delete-after was specified.
* Various trailing-info sections are now preceded by a newline.
BUG FIXES:
* Fixed several exclude/include matching bugs when using wild-cards.
This has a several user-visible effects, all of which make the
matching more consistent and intuitive. This should hopefully not
cause anyone problems since it makes the matching work more like
what people are expecting. (Wayne Davison)
- A pattern with a "**" no longer causes a "*" to match slashes.
For example, with "/*/foo/**", "foo" must be 2 levels deep.
[If your string has BOTH "*" and "**" wildcards, changing the
"*" wildcards to "**" will provide the old behavior in all
versions.]
- "**/foo" now matches at the base of the transfer (like /foo
does). [Use "/**/foo" to get the old behavior in all versions.]
- A non-anchored wildcard term floats to match beyond the base of
the transfer. E.g. "CVS/R*" matches at the end of the path,
just like the non-wildcard term "CVS/Root" does. [Use "/CVS/R*"
to get the old behavior in all versions.]
- Including a "**" in the match term causes it to be matched
against the entire path, not just the name portion, even if
there aren't any interior slashes in the term. E.g. "foo**bar"
would exclude "/path/foo-bar" (just like before) as well as
"/foo-path/baz-bar" (unlike before). [Use "foo*bar" to get the
old behavior in all versions.]
* The exclude list specified in the daemon's config file is now
properly applied to the pulled items no matter how deep the
user's file-args are in the source tree. (Wayne Davison)
* For protocol version >= 27, mdfour_tail() is called when the
block size (including checksum_seed) is a multiple of 64.
Previously it was not called, giving the wrong MD4 checksum.
(Craig Barratt)
* For protocol version >= 27, a 64 bit bit counter is used in
mdfour.c as required by the RFC. Previously only a 32 bit bit
counter was used, causing incorrect MD4 file checksums for
file sizes >= 512MB - 4. (Craig Barratt)
* Fixed a crash bug when interacting with older rsync versions and
multiple files of the same name are destined for the same dir.
(Wayne Davison)
* Keep tmp names from overflowing MAXPATHLEN.
* Make --link-dest honor the absence of -p, -o, and -g.
* Made rsync treat a trailing slash in the destination in a more
consistent manner.
* Fixed file I/O error detection. (John Van Essen)
* Fixed bogus "malformed address {hostname}" message in rsyncd log
when checking IP address against hostnames from "hosts allow"
and "hosts deny" parameters in config file.
* Print heap statistics when verbose >= 2 instead of when >= 1.
* Fixed a compression (-z) bug when syncing a mostly-matching file
that contains already-compressed data. (Yasuoka Masahiko and
Wayne Davison)
* Fixed a bug in the --backup code that could cause deleted files
to not get backed up.
* When the backup code makes new directories, create them with mode
0700 instead of 0755 (since the directory permissions in the
backup tree are not yet copied from the main tree).
* Call setgroups() in a more portable manner.
* Improved file-related error messages to better indicate exactly
what pathname failed. (Wayne Davison)
* Fixed some bugs in the handling of --delete and --exclude when
using the --relative (-R) option. (Wayne Davison)
* Fixed bug that prevented regular files from replacing
special files and caused a directory in --link-dest or
--compare-dest to block the creation of a file with the
same path. A directory still cannot be replaced by a
regular file unless --delete specified. (J.W. Schultz)
* Detect and report when open or opendir succeed but read and
readdir fail caused by network filesystem issues and truncated
files. (David Norwood, Michael Brown, J.W. Schultz)
* Added a fix that should give ssh time to restore the tty settings
if the user presses Ctrl-C at an ssh password prompt.
INTERNAL:
* Eliminated vestigial support for old versions that we stopped
supporting. (J.W. Schultz)
* Simplified some of the option-parsing code. (Wayne Davison)
* Some cleanup made to the exclude code, as well as some new
defines added to enhance readability. (Wayne Davison)
* Changed the protocol-version code so that it can interact at a
lower protocol level than the maximum supported by both sides.
Added an undocumented option, --protocol=N, to force the value
we advertise to the other side (primarily for testing purposes).
(Wayne Davison)
NEWS for rsync 2.5.7 (4 Dec 2003)
Protocol: 26 (unchanged)
Changes since 2.5.6:
SECURITY FIXES:
* Fix buffer handling bugs. (Andrew Tridgell, Martin Pool, Paul
Russell, Andrea Barisani)
NEWS for rsync 2.5.6, aka "the dwd-between-jobs release" (26 Jan 2003)
Protocol: 26 (unchanged)
Changes since 2.5.5:
ENHANCEMENTS:
* The --delete-after option now implies --delete. (Wayne Davison)
* The --suffix option can now be used with --backup-dir. (Michael
Zimmerman)
* 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)
* The rsync:// syntax for daemon connections is now accepted in the
destination field.
* If the file name given to --include-from or --exclude-from is "-",
rsync will read from standard input. (J.W. Schultz)
* New option --link-dest which is like --compare-dest except that
unchanged files are hard-linked in to the destination directory.
(J.W. Schultz)
* Don't report an error if an excluded file disappears during an
rsync run. (Eugene Chupriyanov and Bo Kersey)
* Added .svn to --cvs-exclude list to support subversion. (Jon
Middleton)
* Properly support IPv6 addresses in the rsyncd.conf "hosts allow"
and "hosts deny" fields. (Hideaki Yoshifuji)
* Changed exclude file handling to permit DOS or MAC style line
terminations. (J.W. Schultz)
* Ignore errors from chmod when -p/-a/--preserve-perms is not set.
(Dave Dykstra)
BUG FIXES:
* Fix "forward name lookup failed" errors on AIX 4.3.3. (John
L. Allen, Martin Pool)
* Generate each file's rolling-checksum data as we send it, not
in a separate (memory-eating) pass before hand. This prevents
timeout errors on really large files. (Stefan Nehlsen)
* Fix compilation on Tru64. (Albert Chin, Zoong Pham)
* Better handling of some client-server errors. (Martin Pool)
* Fixed a crash that would occur when sending a list of files that
contains a duplicate name (if it sorts to the end of the file
list) and using --delete. (Wayne Davison)
* Fixed the file-name duplicate-removal code when dealing with multiple
dups in a row. (Wayne Davison)
* Fixed a bug that caused rsync to lose the exit status of its child
processes and sometimes return an exit code of 0 instead of showing
an error. (David R. Staples, Dave Dykstra)
* Fixed bug in --copy-unsafe-links that caused it to be completely
broken. (Dave Dykstra)
* Prevent infinite recursion in cleanup code under certain circumstances.
(Sviatoslav Sviridov and Marc Espie)
* Fixed a bug that prevented rsync from creating intervening directories
when --relative-paths/-R is set. (Craig Barratt)
* Prevent "Connection reset by peer" messages from Cygwin. (Randy O'Meara)
INTERNAL:
* Many code cleanups and improved internal documentation. (Martin
Pool, Nelson Beebe)
* Portability fixes. (Dave Dykstra and Wayne Davison)
* More test cases. (Martin Pool)
* Some test-case fixes. (Brian Poole, Wayne Davison)
* Updated included popt to the latest vendor drop, version 1.6.4.
(Jos Backus)
* Updated config.guess and config.sub to latest versions; this
means rsync should build on more platforms. (Paul Green)
NEWS for rsync 2.5.5, aka Snowy River (2 Apr 2002)
Protocol: 26 (unchanged)
Changes since 2.5.4:
ENHANCEMENTS:
* With --progress, when a transfer is complete show the time taken;
otherwise show expected time to complete. (Cameron Simpson)
* Make "make install-strip" works properly, and "make install"
accepts a DESTDIR variable for help in building binary packages.
(Peter Breitenlohner, Greg Louis)
* If configured with --enable-maintainer-mode, then on receipt of
a fatal signal rsync will try to open an xterm running gdb,
similarly to Samba's "panic action" or GNOME's bug-buddy.
(Martin Pool)
BUG FIXES:
* Fix situation where failure to fork (e.g. because out of process
slots) would cause rsync to kill all processes owned by the
current user. Yes, really! (Paul Haas, Martin Pool)
* Fix test suite on Solaris. (Jos Backus, Martin Pool)
* Fix minor memory leak in socket code. (Dave Dykstra, Martin
Pool.)
* Fix --whole-file problem that caused it to be the default even
for remote connections. (Martin Pool, Frank Schulz)
* Work around bug in Mac OS X mkdir(2), which cannot handle
trailing slashes.
(Martin Pool)
* Improved network error handling. (Greg A. Woods)
NEWS for rsync 2.5.4, aka "Imitation lizard skin" (13 Mar 2002)
Protocol: 26 (unchanged)
Changes since 2.5.3:
BUG FIXES:
* Additional fix for zlib double-free bug. (Martin Pool, Andrew
Tridgell) (CVE CAN-2002-0059)
ENHANCEMENTS:
* Merge in changes from zlib 1.1.3 to zlib 1.1.4. (Jos Backus)
(Note that rsync still uses a custom version of zlib; you can
not just link against a system library. See zlib/README.rsync)
* Additional test cases for --compress. (Martin Pool)
NEWS for rsync 2.5.3, aka "Happy 26" (11 Mar 2002)
Protocol: 26 (unchanged)
Changes since 2.5.2:
SECURITY FIXES:
* Make sure that supplementary groups are removed from a server
process after changing uid and gid. (Ethan Benson) (Debian bug
#132272, CVE CAN-2002-0080)
BUG FIXES:
* Fix zlib double-free bug. (Owen Taylor, Mark J Cox) (CVE
CAN-2002-0059)
* Fixed problem that in many cases caused the error message
unexpected read size of 0 in map_ptr
and resulted in the wrong data being copied.
* Fixed compilation errors on some systems caused by the use of
"unsigned int64" in rsync.h.
* Fixed problem on systems such as Sunos4 that do not support realloc
on a NULL pointer; error was "out of memory in flist_expand".
* Fix for rsync server processes hanging around after the client
unexpectedly disconnects. (Colin Walters) (Debian bug #128632)
* Cope with BSD systems on which mkdir() will not accept a trailing
slash.
ENHANCEMENTS:
* Merge in changes from zlib 1.1.2 to zlib 1.1.3. (Note that
rsync still uses a custom version of zlib; you can not just link
against a system library. See zlib/README.rsync)
* Command to initiate connections is only shown with -vv, rather
than -v as in 2.5.2. Output from plain -v is more similar to
what was historically used so as not to break scripts that try
to parse the output.
* Added --no-whole-file and --no-blocking-io options (Dave Dykstra)
* Made the --write-batch and --read-batch options actually work
and added documentation in the man page (Jos Backus)
* If the daemon is unable to fork a child to accept a connection,
print an error message. (Colin Walters)
NEWS for rsync 2.5.2 (26 Jan 2002)
Protocol: 26 (changed)
Changes since 2.5.1:
SECURITY FIXES:
* Signedness security patch from Sebastian Krahmer
-- in some cases we were not sufficiently
careful about reading integers from the network.
BUG FIXES:
* Fix possible string mangling in log files.
* Fix for setting local address of outgoing sockets.
* Better handling of hardlinks and devices on platforms with
64-bit dev_t or ino_t.
* Name resolution on machines supporting IPv6 is improved.
* Fix for device nodes. (dann frazier) (Debian #129135)
ENHANCEMENTS:
* With -v, rsync now shows the command used to initiate an ssh/rsh
connection.
* --statistics now shows memory heap usage on platforms that
support mallinfo().
* "The Ted T'so school of program optimization": make progress
visible and people will think it's faster. (With --progress,
rsync will show you how many files it has seen as it builds the
file_list, giving some indication that it has not hung.)
* Improvements to batch mode support. This is still experimental
but testing would be welcome. (Jos Backus)
* New --ignore-existing option, patch previously distributed with
Vipul's Razor. (Debian #124286)
NEWS for rsync 2.5.1 (3 Jan 2002)
Protocol: 25 (unchanged)
Changes since 2.5.0:
BUG FIXES:
* Fix for segfault in --daemon mode configuration parser. (Paul
Mackerras)
* Correct string<->address parsing for both IPv4 and 6.
(YOSHIFUJI Hideaki, SUMIKAWA Munechika and Jun-ichiro "itojun"
Hagino)
* Various fixes for IPv6 support. (Dave Dykstra)
* rsync.1 typo fix. (Matt Kraai)
* Test suite typo fixes. (Tom Schmidt)
* rsync.1 grammar and clarity improvements. (Edward
Welbourne)
* Correction to ./configure tests for inet_ntop. (Jeff Garzik)
ENHANCEMENTS:
* --progress and -P now show estimated data transfer rate (in a
multiple of bytes/s) and estimated time to completion. (Rik
Faith)
* --no-detach option, required to run as a W32 service and also
useful when running on Unix under daemontools, AIX's SRC, or a
debugger. (Max Bowsher, Jos Backus)
* Clearer error messages for some conditions.
NEWS for rsync 2.5.0 (30 Nov 2001)
Protocol: 25 (changed)
Changes since 2.4.6:
ANNOUNCEMENTS
* Martin Pool is now a co-maintainer.
NEW FEATURES
* Support for LSB-compliant packaging
* Shell wildcards are allowed in "auth users" lines.
* Merged UNC rsync+ patch to support creation of standalone patch
sets. By Bert J. Dempsey and Debra Weiss, updated by Jos
Backus.
* IPv6 support based on a patch from KAME.net, on systems
including modern versions of Linux, Solaris, and HP-UX. Also
includes IPv6 compatibility functions for old OSs by the
Internet Software Consortium, Paul Vixie, the OpenSSH
portability project, and OpenBSD.
ENHANCEMENTS
* Include/exclude cluestick: with -vv, print out whether files are
included or excluded and why.
* Many error messages have more friendly explanations and more
details.
* Manual page improvements plus scanty protocol documentation.
* When running as --daemon in the background and using a "log
file" rsyncd.conf directive, close the log file every time it is
open when going to sleep on the socket. This allows the log
file to get cleaned out by another process.
* Change to using libpopt rather than getopt for processing
options. This makes the code cleaner and the behaviour more
consistent across platforms. popt is included and built if not
installed on the platform.
* More details in --version, including note about whether 64-bit
files, symlinks and hardlinks are supported.
* MD4 code may use less CPU cycles.
* Use mkstemp on systems where it is secure. If we use mktemp,
explain that we do it in a secure way.
* --whole-file is the default when source and target are on the
local machine.
BUG FIXES:
* Fix for various bugs causing rsync to hang.
* Attempt to fix Large File Summit support on AIX.
* Attempt to fix error handling lockup bug.
* Give a non-0 exit code if *any* of the files we have been asked
to transfer fail to transfer.
* For log messages containing ridiculously long strings that might
overflow a buffer rsync no longer aborts, but rather prints an
ellipsis at the end of the string. (Patch from Ed Santiago.)
PLATFORMS:
* Improved support for UNICOS (tested on Cray T3E and Cray SV1)
* autoconf2.52 (or later) is now required to rebuild the autoconf
scripts. It is not required to simply build rsync.
* Platforms thought to work in this release:
Cray SV1 UNICOS 10.0.0.8 cc
Debian Linux 2.2 UltraSparc gcc
Debian Linux testing/unstable ARM gcc
FreeBSD 3.3-RELEASE i386 cc
FreeBSD 4.1.1-RELEASE i386 cc
FreeBSD 4.3-STABLE i386 cc
HP PA-RISC HP-UX 10.20 gcc
HP PA-RISC HP-UX 11.11 cc
IRIX 6.5 MIPS cc
IRIX 6.5 MIPS gcc
Mac OS X PPC (--disable-ipv6) cc
NetBSD 1.5 i386 gcc
NetBSD Current i386 cc
OpenBSD 2.5 Sparc gcc
OpenBSD 2.9 i386 cc
OpenBSD Current i386 cc
RedHat 6.2 i386 gcc
RedHat 6.2 i386 insure++
RedHat 7.0 i386 gcc
RedHat 7.1 i386 (Kernel 2.4.10) gcc
Slackware 8.0 i686 (Kernel 2.4.10)
Solaris 8 UltraSparc cc
Solaris 8 UltraSparc gcc
Solaris 8 i386 gcc
SuSE 7.1 i386 gcc2.95.2
SuSE 7.1 ppc gcc2.95.2
i386-pc-sco3.2v5.0.5 cc
i386-pc-sco3.2v5.0.5 gcc
powerpc-ibm-aix4.3.3.0 cc
i686-unknown-sysv5UnixWare7.1.0 gcc
i686-unknown-sysv5UnixWare7.1.0 cc
TESTING:
* The existing test.sh script by Phil Hands has been merged into a
test framework that works from both "make check" and the Samba
build farm.
Partial Protocol History
RELEASE DATE VER. DATE OF COMMIT* PROTOCOL
28 Jan 2018 3.1.3 31
21 Dec 2015 3.1.2 31
22 Jun 2014 3.1.1 31
28 Sep 2013 3.1.0 31 Aug 2008 31
23 Sep 2011 3.0.9 30
26 Mar 2011 3.0.8 30
31 Dec 2009 3.0.7 30
08 May 2009 3.0.6 30
28 Dec 2008 3.0.5 30
06 Sep 2008 3.0.4 30
29 Jun 2008 3.0.3 30
08 Apr 2008 3.0.2 30
03 Apr 2008 3.0.1 30
01 Mar 2008 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
30 Sep 2004 2.6.3 28
30 Apr 2004 2.6.2 28
26 Apr 2004 2.6.1 08 Jan 2004 28
01 Jan 2004 2.6.0 10 Apr 2003 27 (MAX=40)
04 Dec 2003 2.5.7 26
26 Jan 2003 2.5.6 26
02 Apr 2002 2.5.5 26
13 Mar 2002 2.5.4 26
11 Mar 2002 2.5.3 26
26 Jan 2002 2.5.2 11 Jan 2002 26
03 Jan 2002 2.5.1 25
30 Nov 2001 2.5.0 23 Aug 2001 25
06 Sep 2000 2.4.6 24
19 Aug 2000 2.4.5 24
29 Jul 2000 2.4.4 24
09 Apr 2000 2.4.3 24
30 Mar 2000 2.4.2 24
30 Jan 2000 2.4.1 29 Jan 2000 24
29 Jan 2000 2.4.0 28 Jan 2000 23
25 Jan 2000 2.3.3 23 Jan 2000 22
08 Nov 1999 2.3.2 26 Jun 1999 21
06 Apr 1999 2.3.1 20
15 Mar 1999 2.3.0 15 Mar 1999 20
25 Nov 1998 2.2.1 19
03 Nov 1998 2.2.0 19
09 Sep 1998 2.1.1 19
20 Jul 1998 2.1.0 19
17 Jul 1998 2.0.19 19
18 Jun 1998 2.0.17 19
01 Jun 1998 2.0.16 19
27 May 1998 2.0.13 27 May 1998 19
26 May 1998 2.0.12 18
22 May 1998 2.0.11 18
18 May 1998 2.0.9 18 May 1998 18
17 May 1998 2.0.8 17
15 May 1998 2.0.1 17
14 May 1998 2.0.0 17
17 Apr 1998 1.7.4 17
13 Apr 1998 1.7.3 17
05 Apr 1998 1.7.2 17
26 Mar 1998 1.7.1 17
26 Mar 1998 1.7.0 26 Mar 1998 17 (MAX=30)
13 Jan 1998 1.6.9 13 Jan 1998 15 (MAX=20)
* DATE OF COMMIT is the date the protocol change was committed to CVS.
rsync-bpc-3.1.3.0/README 0000664 0000000 0000000 00000011132 13737671777 0014463 0 ustar 00root root 0000000 0000000 WHAT IS RSYNC-BPC?
------------------
Rsync-bpc is a customized version of rsync that is used as part of
BackupPC, an open source backup system.
The main change to rsync is adding a shim layer (in the subdirectory
backuppc, and in bpc_sysCalls.c) that emulates the system calls for
accessing the file system so that rsync can directly read/write files
in BackupPC's format.
Rsync-bpc is fully line-compatible with vanilla rsync, so it can talk
to rsync servers and clients.
Rsync-bpc serves no purpose outside of BackupPC.
WHAT IS RSYNC?
--------------
Rsync is a fast and extraordinarily versatile file copying tool for
both remote and local files.
Rsync uses a delta-transfer algorithm which provides a very fast method
for bringing remote files into sync. It does this by sending just the
differences in the files across the link, without requiring that both
sets of files are present at one of the ends of the link beforehand. At
first glance this may seem impossible because the calculation of diffs
between two files normally requires local access to both files.
A technical report describing the rsync algorithm is included with this
package.
USAGE
-----
Basically you use rsync just like scp, but rsync has many additional
options. To get a complete list of supported options type:
rsync --help
See the manpage for more detailed information.
SETUP
-----
Rsync normally uses ssh or rsh for communication with remote systems.
It does not need to be setuid and requires no special privileges for
installation. You must, however, have a working ssh or rsh system.
Using ssh is recommended for its security features.
Alternatively, rsync can run in `daemon' mode, listening on a socket.
This is generally used for public file distribution, although
authentication and access control are available.
To install rsync, first run the "configure" script. This will create a
Makefile and config.h appropriate for your system. Then type "make".
Note that on some systems you will have to force configure not to use
gcc because gcc may not support some features (such as 64 bit file
offsets) that your system may support. Set the environment variable CC
to the name of your native compiler before running configure in this
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 DAEMONS
-------------
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 an rsync daemon. See the rsync(1) man page for info on how to
connect to an rsync daemon.
WEB SITE
--------
The main rsync web site is here:
http://rsync.samba.org/
You'll find a FAQ list, downloads, resources, HTML versions of the
manpages, etc.
MAILING LISTS
-------------
There is a mailing list for the discussion of rsync and its applications
that is open to anyone to join. New releases are announced on this
list, and there is also an announcement-only mailing list for those that
want official announcements. See the mailing-list page for full
details:
http://rsync.samba.org/lists.html
BUG REPORTS
-----------
To visit this web page for full the details on bug reporting:
http://rsync.samba.org/bugzilla.html
That page contains links to the current bug list, and information on how
to report a bug well. You might also like to try searching the Internet
for the error message you've received, or looking in the mailing list
archives at:
http://mail-archive.com/rsync@lists.samba.org/
To send a bug report, follow the instructions on the bug-tracking
page of the web site.
Alternately, email your bug report to rsync@lists.samba.org .
GIT REPOSITORY
--------------
If you want to get the very latest version of rsync direct from the
source code repository then you can use git:
git clone git://git.samba.org/rsync.git
See the download page for full details on all the ways to grab the
source, including nightly tar files, web-browsing of the git repository,
etc.:
http://rsync.samba.org/download.html
COPYRIGHT
---------
Rsync was originally written by Andrew Tridgell and is currently
maintained by Wayne Davison. It has been improved by many developers
from around the world.
Rsync may be used, modified and redistributed only under the terms of
the GNU General Public License, found in the file COPYING in this
distribution, or at:
http://www.fsf.org/licenses/gpl.html
AVAILABILITY
------------
The main web site for rsync is http://rsync.samba.org/
The main ftp site is ftp://rsync.samba.org/pub/rsync/
This is also available as rsync://rsync.samba.org/rsyncftp/
rsync-bpc-3.1.3.0/TODO 0000664 0000000 0000000 00000036374 13737671777 0014312 0 ustar 00root root 0000000 0000000 -*- indented-text -*-
FEATURES ------------------------------------------------------------
Use chroot only if supported
Allow supplementary groups in rsyncd.conf 2002/04/09
Handling IPv6 on old machines
Other IPv6 stuff
Add ACL support 2001/12/02
proxy authentication 2002/01/23
SOCKS 2002/01/23
FAT support
--diff david.e.sewell 2002/03/15
Add daemon --no-fork option
Create more granular verbosity 2003/05/15
DOCUMENTATION --------------------------------------------------------
Keep list of open issues and todos on the web site
Perhaps redo manual as SGML
LOGGING --------------------------------------------------------------
Memory accounting
Improve error messages
Better statistics Rasmus 2002/03/08
Perhaps flush stdout like syslog
Log child death on signal
verbose output David Stein 2001/12/20
internationalization
DEVELOPMENT --------------------------------------------------------
Handling duplicate names
Use generic zlib 2002/02/25
TDB 2002/03/12
Splint 2002/03/12
PERFORMANCE ----------------------------------------------------------
Traverse just one directory at a time
Allow skipping MD4 file_sum 2002/04/08
Accelerate MD4
TESTING --------------------------------------------------------------
Torture test
Cross-test versions 2001/08/22
Test on kernel source
Test large files
Create mutator program for testing
Create configure option to enable dangerous tests
Create pipe program for testing
Create test makefile target for some tests
RELATED PROJECTS -----------------------------------------------------
rsyncsh
http://rsync.samba.org/rsync-and-debian/
rsyncable gzip patch
rsyncsplit as alternative to real integration with gzip?
reverse rsync over HTTP Range
FEATURES ------------------------------------------------------------
Use chroot only if supported
If the platform doesn't support it, then don't even try.
If running as non-root, then don't fail, just give a warning.
(There was a thread about this a while ago?)
http://lists.samba.org/pipermail/rsync/2001-August/thread.html
http://lists.samba.org/pipermail/rsync/2001-September/thread.html
-- --
Allow supplementary groups in rsyncd.conf 2002/04/09
Perhaps allow supplementary groups to be specified in rsyncd.conf;
then make the first one the primary gid and all the rest be
supplementary gids.
-- --
Handling IPv6 on old machines
The KAME IPv6 patch is nice in theory but has proved a bit of a
nightmare in practice. The basic idea of their patch is that rsync
is rewritten to use the new getaddrinfo()/getnameinfo() interface,
rather than gethostbyname()/gethostbyaddr() as in rsync 2.4.6.
Systems that don't have the new interface are handled by providing
our own implementation in lib/, which is selectively linked in.
The problem with this is that it is really hard to get right on
platforms that have a half-working implementation, so redefining
these functions clashes with system headers, and leaving them out
breaks. This affects at least OSF/1, RedHat 5, and Cobalt, which
are moderately improtant.
Perhaps the simplest solution would be to have two different files
implementing the same interface, and choose either the new or the
old API. This is probably necessary for systems that e.g. have
IPv6, but gethostbyaddr() can't handle it. The Linux manpage claims
this is currently the case.
In fact, our internal sockets interface (things like
open_socket_out(), etc) is much narrower than the getaddrinfo()
interface, and so probably simpler to get right. In addition, the
old code is known to work well on old machines.
We could drop the rather large lib/getaddrinfo files.
-- --
Other IPv6 stuff
Implement suggestions from http://www.kame.net/newsletter/19980604/
and ftp://ftp.iij.ad.jp/pub/RFC/rfc2553.txt
If a host has multiple addresses, then listen try to connect to all
in order until we get through. (getaddrinfo may return multiple
addresses.) This is kind of implemented already.
Possibly also when starting as a server we may need to listen on
multiple passive addresses. This might be a bit harder, because we
may need to select on all of them. Hm.
-- --
Add ACL support 2001/12/02
Transfer ACLs. Need to think of a standard representation.
Probably better not to even try to convert between NT and POSIX.
Possibly can share some code with Samba.
NOTE: there is a patch that implements this in the "patches" subdir.
-- --
proxy authentication 2002/01/23
Allow RSYNC_PROXY to be http://user:pass@proxy.foo:3128/, and do
HTTP Basic Proxy-Authentication.
Multiple schemes are possible, up to and including the insanity that
is NTLM, but Basic probably covers most cases.
-- --
SOCKS 2002/01/23
Add --with-socks, and then perhaps a command-line option to put them
on or off. This might be more reliable than LD_PRELOAD hacks.
-- --
FAT support
rsync to a FAT partition on a Unix machine doesn't work very well at
the moment. I think we get errors about invalid filenames and
perhaps also trying to do atomic renames.
I guess the code to do this is currently #ifdef'd on Windows;
perhaps we ought to intelligently fall back to it on Unix too.
-- --
--diff david.e.sewell 2002/03/15
Allow people to specify the diff command. (Might want to use wdiff,
gnudiff, etc.)
Just diff the temporary file with the destination file, and delete
the tmp file rather than moving it into place.
Interaction with --partial.
Security interactions with daemon mode?
-- --
Add daemon --no-fork option
Very useful for debugging. Also good when running under a
daemon-monitoring process that tries to restart the service when the
parent exits.
-- --
Create more granular verbosity 2003/05/15
Control output with the --report option.
The option takes as a single argument (no whitespace) a
comma delimited lists of keywords.
This would separate debugging from "logging" as well as
fine grained selection of statistical reporting and what
actions are logged.
http://lists.samba.org/archive/rsync/2003-May/006059.html
-- --
DOCUMENTATION --------------------------------------------------------
Keep list of open issues and todos on the web site
-- --
Perhaps redo manual as SGML
The man page is getting rather large, and there is more information
that ought to be added.
TexInfo source is probably a dying format.
Linuxdoc looks like the most likely contender. I know DocBook is
favoured by some people, but it's so bloody verbose, even with emacs
support.
-- --
LOGGING --------------------------------------------------------------
Memory accounting
At exit, show how much memory was used for the file list, etc.
Also we do a wierd exponential-growth allocation in flist.c. I'm
not sure this makes sense with modern mallocs. At any rate it will
make us allocate a huge amount of memory for large file lists.
-- --
Improve error messages
If we hang or get SIGINT, then explain where we were up to. Perhaps
have a static buffer that contains the current function name, or
some kind of description of what we were trying to do. This is a
little easier on people than needing to run strace/truss.
"The dungeon collapses! You are killed." Rather than "unexpected
eof" give a message that is more detailed if possible and also more
helpful.
If we get an error writing to a socket, then we should perhaps
continue trying to read to see if an error message comes across
explaining why the socket is closed. I'm not sure if this would
work, but it would certainly make our messages more helpful.
What happens if a directory is missing -x attributes. Do we lose
our load? (Debian #28416) Probably fixed now, but a test case would
be good.
-- --
Better statistics Rasmus 2002/03/08
hey, how about an rsync option that just gives you the
summary without the list of files? And perhaps gives
more information like the number of new files, number
of changed, deleted, etc. ?
nice idea there is --stats but at the moment it's very
tridge-oriented rather than user-friendly it would be
nice to improve it that would also work well with
--dryrun
-- --
Perhaps flush stdout like syslog
Perhaps flush stdout after each filename, so that people trying to
monitor progress in a log file can do so more easily. See
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=48108
-- --
Log child death on signal
If a child of the rsync daemon dies with a signal, we should notice
that when we reap it and log a message.
-- --
verbose output David Stein 2001/12/20
At end of transfer, show how many files were or were not transferred
correctly.
-- --
internationalization
Change to using gettext(). Probably need to ship this for platforms
that don't have it.
Solicit translations.
Does anyone care? Before we bother modifying the code, we ought to
get the manual translated first, because that's possibly more useful
and at any rate demonstrates desire.
-- --
DEVELOPMENT --------------------------------------------------------
Handling duplicate names
Some folks would like rsync to be deterministic in how it handles
duplicate names that come from mering multiple source directories
into a single destination directory; e.g. the last name wins. We
could do this by switching our sort algorithm to one that will
guarantee that the names won't be reordered. Alternately, we could
assign an ever-increasing number to each item as we insert it into
the list and then make sure that we leave the largest number when
cleaning the file list (see clean_flist()). Another solution would
be to add a hash table, and thus never put any duplicate names into
the file list (and bump the protocol to handle this).
-- --
Use generic zlib 2002/02/25
Perhaps don't use our own zlib.
Advantages:
- will automatically be up to date with bugfixes in zlib
- can leave it out for small rsync on e.g. recovery disks
- can use a shared library
- avoids people breaking rsync by trying to do this themselves and
messing up
Should we ship zlib for systems that don't have it, or require
people to install it separately?
Apparently this will make us incompatible with versions of rsync
that use the patched version of rsync. Probably the simplest way to
do this is to just disable gzip (with a warning) when talking to old
versions.
-- --
Splint 2002/03/12
Build rsync with SPLINT to try to find security holes. Add
annotations as necessary. Keep track of the number of warnings
found initially, and see how many of them are real bugs, or real
security bugs. Knowing the percentage of likely hits would be
really interesting for other projects.
-- --
PERFORMANCE ----------------------------------------------------------
Allow skipping MD4 file_sum 2002/04/08
If we're doing a local transfer, or using -W, then perhaps don't
send the file checksum. If we're doing a local transfer, then
calculating MD4 checksums uses 90% of CPU and is unlikely to be
useful.
We should not allow it to be disabled separately from -W, though
as it is the only thing that lets us know when the rsync algorithm
got out of sync and messed the file up (i.e. if the basis file
changed between checksum generation and reception).
-- --
Accelerate MD4
Perhaps borrow an assembler MD4 from someone?
Make sure we call MD4 with properly-sized blocks whenever possible
to avoid copying into the residue region?
-- --
TESTING --------------------------------------------------------------
Torture test
Something that just keeps running rsync continuously over a data set
likely to generate problems.
-- --
Cross-test versions 2001/08/22
Part of the regression suite should be making sure that we
don't break backwards compatibility: old clients vs new
servers and so on. Ideally we would test both up and down
from the current release to all old versions.
Run current rsync versions against significant past releases.
We might need to omit broken old versions, or versions in which
particular functionality is broken
It might be sufficient to test downloads from well-known public
rsync servers running different versions of rsync. This will give
some testing and also be the most common case for having different
versions and not being able to upgrade.
The new --protocol option may help in this.
-- --
Test on kernel source
Download all versions of kernel; unpack, sync between them. Also
sync between uncompressed tarballs. Compare directories after
transfer.
Use local mode; ssh; daemon; --whole-file and --no-whole-file.
Use awk to pull out the 'speedup' number for each transfer. Make
sure it is >= x.
-- --
Test large files
Sparse and non-sparse
-- --
Create mutator program for testing
Insert bytes, delete bytes, swap blocks, ...
-- --
Create configure option to enable dangerous tests
-- --
Create pipe program for testing
Create pipe program that makes slow/jerky connections for
testing Versions of read() and write() that corrupt the
stream, or abruptly fail
-- --
Create test makefile target for some tests
Separate makefile target to run rough tests -- or perhaps
just run them every time?
-- --
RELATED PROJECTS -----------------------------------------------------
rsyncsh
Write a small emulation of interactive ftp as a Pythonn program
that calls rsync. Commands such as "cd", "ls", "ls *.c" etc map
fairly directly into rsync commands: it just needs to remember the
current host, directory and so on. We can probably even do
completion of remote filenames.
-- --
http://rsync.samba.org/rsync-and-debian/
-- --
rsyncable gzip patch
Exhaustive, tortuous testing
Cleanups?
-- --
rsyncsplit as alternative to real integration with gzip?
-- --
reverse rsync over HTTP Range
Goswin Brederlow suggested this on Debian; I think tridge and I
talked about it previous in relation to rproxy.
Addendum: It looks like someone is working on a version of this:
http://zsync.moria.org.uk/
-- --
rsync-bpc-3.1.3.0/access.c 0000664 0000000 0000000 00000014076 13737671777 0015222 0 ustar 00root root 0000000 0000000 /*
* Routines to authenticate access to a daemon (hosts allow/deny).
*
* Copyright (C) 1998 Andrew Tridgell
* Copyright (C) 2004-2018 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 allow_forward_dns;
extern const char undetermined_hostname[];
static int match_hostname(const char **host_ptr, const char *addr, const char *tok)
{
struct hostent *hp;
unsigned int i;
const char *host = *host_ptr;
if (!host || !*host)
return 0;
/* First check if the reverse-DNS-determined hostname matches. */
if (iwildmatch(tok, host))
return 1;
if (!allow_forward_dns)
return 0;
/* Fail quietly if tok is an address or wildcarded entry, not a simple hostname. */
if (!tok[strspn(tok, ".0123456789")] || tok[strcspn(tok, ":/*?[")])
return 0;
/* Now try forward-DNS on the token (config-specified hostname) and see if the IP matches. */
if (!(hp = gethostbyname(tok)))
return 0;
for (i = 0; hp->h_addr_list[i] != NULL; i++) {
if (strcmp(addr, inet_ntoa(*(struct in_addr*)(hp->h_addr_list[i]))) == 0) {
/* If reverse lookups are off, we'll use the conf-specified
* hostname in preference to UNDETERMINED. */
if (host == undetermined_hostname) {
if (!(*host_ptr = strdup(tok)))
*host_ptr = undetermined_hostname;
}
return 1;
}
}
return 0;
}
static int match_binary(const char *b1, const char *b2, const char *mask, int addrlen)
{
int i;
for (i = 0; i < addrlen; i++) {
if ((b1[i] ^ b2[i]) & mask[i])
return 0;
}
return 1;
}
static void make_mask(char *mask, int plen, int addrlen)
{
int w, b;
w = plen >> 3;
b = plen & 0x7;
if (w)
memset(mask, 0xff, w);
if (w < addrlen)
mask[w] = 0xff & (0xff<<(8-b));
if (w+1 < addrlen)
memset(mask+w+1, 0, addrlen-w-1);
return;
}
static int match_address(const char *addr, const char *tok)
{
char *p;
struct addrinfo hints, *resa, *rest;
int gai;
int ret = 0;
int addrlen = 0;
#ifdef HAVE_STRTOL
long int bits;
#else
int bits;
#endif
char mask[16];
char *a = NULL, *t = NULL;
if (!addr || !*addr)
return 0;
p = strchr(tok,'/');
if (p)
*p = '\0';
/* Fail quietly if tok is a hostname, not an address. */
if (tok[strspn(tok, ".0123456789")] && strchr(tok, ':') == NULL) {
if (p)
*p = '/';
return 0;
}
memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
#ifdef AI_NUMERICHOST
hints.ai_flags = AI_NUMERICHOST;
#endif
if (getaddrinfo(addr, NULL, &hints, &resa) != 0) {
if (p)
*p = '/';
return 0;
}
gai = getaddrinfo(tok, NULL, &hints, &rest);
if (p)
*p++ = '/';
if (gai != 0) {
rprintf(FLOG, "error matching address %s: %s\n",
tok, gai_strerror(gai));
freeaddrinfo(resa);
return 0;
}
if (rest->ai_family != resa->ai_family) {
ret = 0;
goto out;
}
switch(resa->ai_family) {
case PF_INET:
a = (char *)&((struct sockaddr_in *)resa->ai_addr)->sin_addr;
t = (char *)&((struct sockaddr_in *)rest->ai_addr)->sin_addr;
addrlen = 4;
break;
#ifdef INET6
case PF_INET6:
{
struct sockaddr_in6 *sin6a, *sin6t;
sin6a = (struct sockaddr_in6 *)resa->ai_addr;
sin6t = (struct sockaddr_in6 *)rest->ai_addr;
a = (char *)&sin6a->sin6_addr;
t = (char *)&sin6t->sin6_addr;
addrlen = 16;
#ifdef HAVE_SOCKADDR_IN6_SCOPE_ID
if (sin6t->sin6_scope_id &&
sin6a->sin6_scope_id != sin6t->sin6_scope_id) {
ret = 0;
goto out;
}
#endif
break;
}
#endif
default:
rprintf(FLOG, "unknown family %u\n", rest->ai_family);
ret = 0;
goto out;
}
bits = -1;
if (p) {
if (inet_pton(resa->ai_addr->sa_family, p, mask) <= 0) {
#ifdef HAVE_STRTOL
char *ep = NULL;
#else
unsigned char *pp;
#endif
#ifdef HAVE_STRTOL
bits = strtol(p, &ep, 10);
if (!*p || *ep) {
rprintf(FLOG, "malformed mask in %s\n", tok);
ret = 0;
goto out;
}
#else
for (pp = (unsigned char *)p; *pp; pp++) {
if (!isascii(*pp) || !isdigit(*pp)) {
rprintf(FLOG, "malformed mask in %s\n", tok);
ret = 0;
goto out;
}
}
bits = atoi(p);
#endif
if (bits == 0) {
ret = 1;
goto out;
}
if (bits < 0 || bits > (addrlen << 3)) {
rprintf(FLOG, "malformed mask in %s\n", tok);
ret = 0;
goto out;
}
}
} else {
bits = 128;
}
if (bits >= 0)
make_mask(mask, bits, addrlen);
ret = match_binary(a, t, mask, addrlen);
out:
freeaddrinfo(resa);
freeaddrinfo(rest);
return ret;
}
static int access_match(const char *list, const char *addr, const char **host_ptr)
{
char *tok;
char *list2 = strdup(list);
if (!list2)
out_of_memory("access_match");
strlower(list2);
for (tok = strtok(list2, " ,\t"); tok; tok = strtok(NULL, " ,\t")) {
if (match_hostname(host_ptr, addr, tok) || match_address(addr, tok)) {
free(list2);
return 1;
}
}
free(list2);
return 0;
}
int allow_access(const char *addr, const char **host_ptr, int i)
{
const char *allow_list = lp_hosts_allow(i);
const char *deny_list = lp_hosts_deny(i);
if (allow_list && !*allow_list)
allow_list = NULL;
if (deny_list && !*deny_list)
deny_list = NULL;
allow_forward_dns = lp_forward_lookup(i);
/* If we match an allow-list item, we always allow access. */
if (allow_list) {
if (access_match(allow_list, addr, host_ptr))
return 1;
/* For an allow-list w/o a deny-list, disallow non-matches. */
if (!deny_list)
return 0;
}
/* If we match a deny-list item (and got past any allow-list
* items), we always disallow access. */
if (deny_list && access_match(deny_list, addr, host_ptr))
return 0;
/* Allow all other access. */
return 1;
}
rsync-bpc-3.1.3.0/aclocal.m4 0000664 0000000 0000000 00000001326 13737671777 0015447 0 ustar 00root root 0000000 0000000 # generated automatically by aclocal 1.15.1 -*- Autoconf -*-
# Copyright (C) 1996-2017 Free Software Foundation, Inc.
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])])
m4_include([m4/have_type.m4])
m4_include([m4/socklen_t.m4])
rsync-bpc-3.1.3.0/acls.c 0000664 0000000 0000000 00000071004 13737671777 0014675 0 ustar 00root root 0000000 0000000 /*
* Handle passing Access Control Lists between systems.
*
* Copyright (C) 1996 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2006-2018 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 "lib/sysacls.h"
#ifdef SUPPORT_ACLS
extern int dry_run;
extern int am_root;
extern int read_only;
extern int list_only;
extern int orig_umask;
extern int numeric_ids;
extern int inc_recurse;
extern int preserve_devices;
extern int preserve_specials;
/* Flags used to indicate what items are being transmitted for an entry. */
#define XMIT_USER_OBJ (1<<0)
#define XMIT_GROUP_OBJ (1<<1)
#define XMIT_MASK_OBJ (1<<2)
#define XMIT_OTHER_OBJ (1<<3)
#define XMIT_NAME_LIST (1<<4)
#define NO_ENTRY ((uchar)0x80) /* Default value of a NON-name-list entry. */
#define NAME_IS_USER (1u<<31) /* Bit used only on a name-list entry. */
/* When we send the access bits over the wire, we shift them 2 bits to the
* left and use the lower 2 bits as flags (relevant only to a name entry).
* This makes the protocol more efficient than sending a value that would
* be likely to have its hightest bits set. */
#define XFLAG_NAME_FOLLOWS 0x0001u
#define XFLAG_NAME_IS_USER 0x0002u
/* === ACL structures === */
typedef struct {
id_t id;
uint32 access;
} id_access;
typedef struct {
id_access *idas;
int count;
} ida_entries;
typedef struct {
char *name;
uchar len;
} idname;
typedef struct rsync_acl {
ida_entries names;
/* These will be NO_ENTRY if there's no such entry. */
uchar user_obj;
uchar group_obj;
uchar mask_obj;
uchar other_obj;
} rsync_acl;
typedef struct {
rsync_acl racl;
SMB_ACL_T sacl;
} acl_duo;
static const rsync_acl empty_rsync_acl = {
{NULL, 0}, NO_ENTRY, NO_ENTRY, NO_ENTRY, NO_ENTRY
};
static item_list access_acl_list = EMPTY_ITEM_LIST;
static item_list default_acl_list = EMPTY_ITEM_LIST;
static size_t prior_access_count = (size_t)-1;
static size_t prior_default_count = (size_t)-1;
/* === Calculations on ACL types === */
static const char *str_acl_type(SMB_ACL_TYPE_T type)
{
switch (type) {
case SMB_ACL_TYPE_ACCESS:
#ifdef HAVE_OSX_ACLS
return "ACL_TYPE_EXTENDED";
#else
return "ACL_TYPE_ACCESS";
#endif
case SMB_ACL_TYPE_DEFAULT:
return "ACL_TYPE_DEFAULT";
default:
break;
}
return "unknown ACL type!";
}
#if 0
static int calc_sacl_entries(const rsync_acl *racl)
{
/* A System ACL always gets user/group/other permission entries. */
return racl->names.count
#ifdef ACLS_NEED_MASK
+ 1
#else
+ (racl->mask_obj != NO_ENTRY)
#endif
+ 3;
}
/* Extracts and returns the permission bits from the ACL. This cannot be
* called on an rsync_acl that has NO_ENTRY in any spot but the mask. */
static int rsync_acl_get_perms(const rsync_acl *racl)
{
return (racl->user_obj << 6)
+ ((racl->mask_obj != NO_ENTRY ? racl->mask_obj : racl->group_obj) << 3)
+ racl->other_obj;
}
#endif
/* Removes the permission-bit entries from the ACL because these
* can be reconstructed from the file's mode. */
static void rsync_acl_strip_perms(stat_x *sxp)
{
rsync_acl *racl = sxp->acc_acl;
racl->user_obj = NO_ENTRY;
if (racl->mask_obj == NO_ENTRY)
racl->group_obj = NO_ENTRY;
else {
int group_perms = (sxp->st.st_mode >> 3) & 7;
if (racl->group_obj == group_perms)
racl->group_obj = NO_ENTRY;
#ifndef HAVE_SOLARIS_ACLS
if (racl->names.count != 0 && racl->mask_obj == group_perms)
racl->mask_obj = NO_ENTRY;
#endif
}
racl->other_obj = NO_ENTRY;
}
/* Given an empty rsync_acl, fake up the permission bits. */
static void rsync_acl_fake_perms(rsync_acl *racl, mode_t mode)
{
racl->user_obj = (mode >> 6) & 7;
racl->group_obj = (mode >> 3) & 7;
racl->other_obj = mode & 7;
}
/* === Rsync ACL functions === */
static rsync_acl *create_racl(void)
{
rsync_acl *racl = new(rsync_acl);
if (!racl)
out_of_memory("create_racl");
*racl = empty_rsync_acl;
return racl;
}
static BOOL ida_entries_equal(const ida_entries *ial1, const ida_entries *ial2)
{
id_access *ida1, *ida2;
int count = ial1->count;
if (count != ial2->count)
return False;
ida1 = ial1->idas;
ida2 = ial2->idas;
for (; count--; ida1++, ida2++) {
if (ida1->access != ida2->access || ida1->id != ida2->id)
return False;
}
return True;
}
static BOOL rsync_acl_equal(const rsync_acl *racl1, const rsync_acl *racl2)
{
return racl1->user_obj == racl2->user_obj
&& racl1->group_obj == racl2->group_obj
&& racl1->mask_obj == racl2->mask_obj
&& racl1->other_obj == racl2->other_obj
&& ida_entries_equal(&racl1->names, &racl2->names);
}
/* Are the extended (non-permission-bit) entries equal? If so, the rest of
* the ACL will be handled by the normal mode-preservation code. This is
* only meaningful for access ACLs! Note: the 1st arg is a fully-populated
* rsync_acl, but the 2nd parameter can be a condensed rsync_acl, which means
* that it might have several of its permission objects set to NO_ENTRY. */
static BOOL rsync_acl_equal_enough(const rsync_acl *racl1,
const rsync_acl *racl2, mode_t m)
{
if ((racl1->mask_obj ^ racl2->mask_obj) & NO_ENTRY)
return False; /* One has a mask and the other doesn't */
/* When there's a mask, the group_obj becomes an extended entry. */
if (racl1->mask_obj != NO_ENTRY) {
/* A condensed rsync_acl with a mask can only have no
* group_obj when it was identical to the mask. This
* means that it was also identical to the group attrs
* from the mode. */
/*
* Craig Barratt notes: with rsync on cygwin, this test
* fails on directories since racl1->group_obj is also
* NO_ENTRY. This causes an extraneous setting via
* lsetxattr() of the ACL, which is benign.
*/
if (racl2->group_obj == NO_ENTRY) {
if (racl1->group_obj != ((m >> 3) & 7))
return False;
} else if (racl1->group_obj != racl2->group_obj)
return False;
}
return ida_entries_equal(&racl1->names, &racl2->names);
}
static void rsync_acl_free(rsync_acl *racl)
{
if (racl->names.idas)
free(racl->names.idas);
*racl = empty_rsync_acl;
}
void free_acl(stat_x *sxp)
{
if (sxp->acc_acl) {
rsync_acl_free(sxp->acc_acl);
free(sxp->acc_acl);
sxp->acc_acl = NULL;
}
if (sxp->def_acl) {
rsync_acl_free(sxp->def_acl);
free(sxp->def_acl);
sxp->def_acl = NULL;
}
}
#if 0
#ifdef SMB_ACL_NEED_SORT
static int id_access_sorter(const void *r1, const void *r2)
{
id_access *ida1 = (id_access *)r1;
id_access *ida2 = (id_access *)r2;
id_t rid1 = ida1->id, rid2 = ida2->id;
if ((ida1->access ^ ida2->access) & NAME_IS_USER)
return ida1->access & NAME_IS_USER ? -1 : 1;
return rid1 == rid2 ? 0 : rid1 < rid2 ? -1 : 1;
}
#endif
#endif
/* === System ACLs === */
#if 0
/* Unpack system ACL -> rsync ACL verbatim. Return whether we succeeded. */
static BOOL unpack_smb_acl(SMB_ACL_T sacl, rsync_acl *racl)
{
static item_list temp_ida_list = EMPTY_ITEM_LIST;
SMB_ACL_ENTRY_T entry;
const char *errfun;
int rc;
errfun = "sys_acl_get_entry";
for (rc = sys_acl_get_entry(sacl, SMB_ACL_FIRST_ENTRY, &entry);
rc == 1;
rc = sys_acl_get_entry(sacl, SMB_ACL_NEXT_ENTRY, &entry)) {
SMB_ACL_TAG_T tag_type;
uint32 access;
id_t g_u_id;
id_access *ida;
if ((rc = sys_acl_get_info(entry, &tag_type, &access, &g_u_id)) != 0) {
errfun = "sys_acl_get_info";
break;
}
/* continue == done with entry; break == store in temporary ida list */
switch (tag_type) {
#ifndef HAVE_OSX_ACLS
case SMB_ACL_USER_OBJ:
if (racl->user_obj == NO_ENTRY)
racl->user_obj = access;
else
rprintf(FINFO, "unpack_smb_acl: warning: duplicate USER_OBJ entry ignored\n");
continue;
case SMB_ACL_GROUP_OBJ:
if (racl->group_obj == NO_ENTRY)
racl->group_obj = access;
else
rprintf(FINFO, "unpack_smb_acl: warning: duplicate GROUP_OBJ entry ignored\n");
continue;
case SMB_ACL_MASK:
if (racl->mask_obj == NO_ENTRY)
racl->mask_obj = access;
else
rprintf(FINFO, "unpack_smb_acl: warning: duplicate MASK entry ignored\n");
continue;
case SMB_ACL_OTHER:
if (racl->other_obj == NO_ENTRY)
racl->other_obj = access;
else
rprintf(FINFO, "unpack_smb_acl: warning: duplicate OTHER entry ignored\n");
continue;
#endif
case SMB_ACL_USER:
access |= NAME_IS_USER;
break;
case SMB_ACL_GROUP:
break;
default:
rprintf(FINFO, "unpack_smb_acl: warning: entry with unrecognized tag type ignored\n");
continue;
}
ida = EXPAND_ITEM_LIST(&temp_ida_list, id_access, -10);
ida->id = g_u_id;
ida->access = access;
}
if (rc) {
rsyserr(FERROR_XFER, errno, "unpack_smb_acl: %s()", errfun);
rsync_acl_free(racl);
return False;
}
/* Transfer the count id_access items out of the temp_ida_list
* into the names ida_entries list in racl. */
if (temp_ida_list.count) {
#ifdef SMB_ACL_NEED_SORT
if (temp_ida_list.count > 1) {
qsort(temp_ida_list.items, temp_ida_list.count,
sizeof (id_access), id_access_sorter);
}
#endif
if (!(racl->names.idas = new_array(id_access, temp_ida_list.count)))
out_of_memory("unpack_smb_acl");
memcpy(racl->names.idas, temp_ida_list.items,
temp_ida_list.count * sizeof (id_access));
} else
racl->names.idas = NULL;
racl->names.count = temp_ida_list.count;
/* Truncate the temporary list now that its idas have been saved. */
temp_ida_list.count = 0;
return True;
}
#endif
/* Synactic sugar for system calls */
#define CALL_OR_ERROR(func,args,str) \
do { \
if (func args) { \
errfun = str; \
goto error_exit; \
} \
} while (0)
#define COE(func,args) CALL_OR_ERROR(func,args,#func)
#define COE2(func,args) CALL_OR_ERROR(func,args,NULL)
#if 0
#ifndef HAVE_OSX_ACLS
/* Store the permissions in the system ACL entry. */
static int store_access_in_entry(uint32 access, SMB_ACL_ENTRY_T entry)
{
if (sys_acl_set_access_bits(entry, access)) {
rsyserr(FERROR_XFER, errno, "store_access_in_entry sys_acl_set_access_bits()");
return -1;
}
return 0;
}
#endif
/* Pack rsync ACL -> system ACL verbatim. Return whether we succeeded. */
static BOOL pack_smb_acl(SMB_ACL_T *smb_acl, const rsync_acl *racl)
{
#ifdef ACLS_NEED_MASK
uchar mask_bits;
#endif
size_t count;
id_access *ida;
const char *errfun = NULL;
SMB_ACL_ENTRY_T entry;
if (!(*smb_acl = sys_acl_init(calc_sacl_entries(racl)))) {
rsyserr(FERROR_XFER, errno, "pack_smb_acl: sys_acl_init()");
return False;
}
#ifndef HAVE_OSX_ACLS
COE( sys_acl_create_entry,(smb_acl, &entry) );
COE( sys_acl_set_info,(entry, SMB_ACL_USER_OBJ, racl->user_obj & ~NO_ENTRY, 0) );
#endif
for (ida = racl->names.idas, count = racl->names.count; count; ida++, count--) {
#ifdef SMB_ACL_NEED_SORT
if (!(ida->access & NAME_IS_USER))
break;
#endif
COE( sys_acl_create_entry,(smb_acl, &entry) );
COE( sys_acl_set_info,
(entry,
ida->access & NAME_IS_USER ? SMB_ACL_USER : SMB_ACL_GROUP,
ida->access & ~NAME_IS_USER, ida->id) );
}
#ifndef HAVE_OSX_ACLS
COE( sys_acl_create_entry,(smb_acl, &entry) );
COE( sys_acl_set_info,(entry, SMB_ACL_GROUP_OBJ, racl->group_obj & ~NO_ENTRY, 0) );
#ifdef SMB_ACL_NEED_SORT
for ( ; count; ida++, count--) {
COE( sys_acl_create_entry,(smb_acl, &entry) );
COE( sys_acl_set_info,(entry, SMB_ACL_GROUP, ida->access, ida->id) );
}
#endif
#ifdef ACLS_NEED_MASK
mask_bits = racl->mask_obj == NO_ENTRY ? racl->group_obj & ~NO_ENTRY : racl->mask_obj;
COE( sys_acl_create_entry,(smb_acl, &entry) );
COE( sys_acl_set_info,(entry, SMB_ACL_MASK, mask_bits, 0) );
#else
if (racl->mask_obj != NO_ENTRY) {
COE( sys_acl_create_entry,(smb_acl, &entry) );
COE( sys_acl_set_info,(entry, SMB_ACL_MASK, racl->mask_obj, 0) );
}
#endif
COE( sys_acl_create_entry,(smb_acl, &entry) );
COE( sys_acl_set_info,(entry, SMB_ACL_OTHER, racl->other_obj & ~NO_ENTRY, 0) );
#endif
#ifdef DEBUG
if (sys_acl_valid(*smb_acl) < 0)
rprintf(FERROR_XFER, "pack_smb_acl: warning: system says the ACL I packed is invalid\n");
#endif
return True;
error_exit:
if (errfun) {
rsyserr(FERROR_XFER, errno, "pack_smb_acl %s()", errfun);
}
sys_acl_free_acl(*smb_acl);
return False;
}
#endif
static int find_matching_rsync_acl(const rsync_acl *racl, SMB_ACL_TYPE_T type,
const item_list *racl_list)
{
static int access_match = -1, default_match = -1;
int *match = type == SMB_ACL_TYPE_ACCESS ? &access_match : &default_match;
size_t count = racl_list->count;
/* If this is the first time through or we didn't match the last
* time, then start at the end of the list, which should be the
* best place to start hunting. */
if (*match == -1)
*match = racl_list->count - 1;
while (count--) {
rsync_acl *base = racl_list->items;
if (rsync_acl_equal(base + *match, racl))
return *match;
if (!(*match)--)
*match = racl_list->count - 1;
}
*match = -1;
return *match;
}
static int get_rsync_acl(const char *fname, rsync_acl *racl,
SMB_ACL_TYPE_T type, mode_t mode)
{
#ifdef SUPPORT_XATTRS
/* --fake-super support: load ACLs from an xattr. */
if (1) {
char *buf;
size_t len;
int cnt;
if ((buf = get_xattr_acl(fname, type == SMB_ACL_TYPE_ACCESS, &len)) == NULL)
return 0;
cnt = (len - 4*4) / (4+4);
if (len < 4*4 || len != (size_t)cnt*(4+4) + 4*4) {
free(buf);
return -1;
}
racl->user_obj = IVAL(buf, 0);
if (racl->user_obj == NO_ENTRY)
racl->user_obj = (mode >> 6) & 7;
racl->group_obj = IVAL(buf, 4);
if (racl->group_obj == NO_ENTRY)
racl->group_obj = (mode >> 3) & 7;
racl->mask_obj = IVAL(buf, 8);
racl->other_obj = IVAL(buf, 12);
if (racl->other_obj == NO_ENTRY)
racl->other_obj = mode & 7;
if (cnt) {
char *bp = buf + 4*4;
id_access *ida;
if (!(ida = racl->names.idas = new_array(id_access, cnt)))
out_of_memory("get_rsync_acl");
racl->names.count = cnt;
for ( ; cnt--; ida++, bp += 4+4) {
ida->id = IVAL(bp, 0);
ida->access = IVAL(bp, 4);
}
}
free(buf);
return 0;
}
#endif
return 0;
}
/* Return the Access Control List for the given filename. */
int get_acl(const char *fname, stat_x *sxp)
{
sxp->acc_acl = create_racl();
if (S_ISREG(sxp->st.st_mode) || S_ISDIR(sxp->st.st_mode)) {
/* Everyone supports this. */
} else if (S_ISLNK(sxp->st.st_mode)) {
return 0;
} else if (IS_SPECIAL(sxp->st.st_mode)) {
#ifndef NO_SPECIAL_ACLS
if (!preserve_specials)
#endif
return 0;
} else if (IS_DEVICE(sxp->st.st_mode)) {
#ifndef NO_DEVICE_ACLS
if (!preserve_devices)
#endif
return 0;
} else if (IS_MISSING_FILE(sxp->st))
return 0;
if (get_rsync_acl(fname, sxp->acc_acl, SMB_ACL_TYPE_ACCESS,
sxp->st.st_mode) < 0) {
free_acl(sxp);
return -1;
}
if (S_ISDIR(sxp->st.st_mode)) {
sxp->def_acl = create_racl();
if (get_rsync_acl(fname, sxp->def_acl, SMB_ACL_TYPE_DEFAULT,
sxp->st.st_mode) < 0) {
free_acl(sxp);
return -1;
}
}
return 0;
}
/* === Send functions === */
/* Send the ida list over the file descriptor. */
static void send_ida_entries(int f, const ida_entries *idal)
{
id_access *ida;
size_t count = idal->count;
write_varint(f, idal->count);
for (ida = idal->idas; count--; ida++) {
uint32 xbits = ida->access << 2;
const char *name;
if (ida->access & NAME_IS_USER) {
xbits |= XFLAG_NAME_IS_USER;
name = numeric_ids ? NULL : add_uid(ida->id);
} else
name = numeric_ids ? NULL : add_gid(ida->id);
write_varint(f, ida->id);
if (inc_recurse && name) {
int len = strlen(name);
write_varint(f, xbits | XFLAG_NAME_FOLLOWS);
write_byte(f, len);
write_buf(f, name, len);
} else
write_varint(f, xbits);
}
}
static void send_rsync_acl(int f, rsync_acl *racl, SMB_ACL_TYPE_T type,
item_list *racl_list)
{
int ndx = find_matching_rsync_acl(racl, type, racl_list);
/* Send 0 (-1 + 1) to indicate that literal ACL data follows. */
write_varint(f, ndx + 1);
if (ndx < 0) {
rsync_acl *new_racl = EXPAND_ITEM_LIST(racl_list, rsync_acl, 1000);
uchar flags = 0;
if (racl->user_obj != NO_ENTRY)
flags |= XMIT_USER_OBJ;
if (racl->group_obj != NO_ENTRY)
flags |= XMIT_GROUP_OBJ;
if (racl->mask_obj != NO_ENTRY)
flags |= XMIT_MASK_OBJ;
if (racl->other_obj != NO_ENTRY)
flags |= XMIT_OTHER_OBJ;
if (racl->names.count)
flags |= XMIT_NAME_LIST;
write_byte(f, flags);
if (flags & XMIT_USER_OBJ)
write_varint(f, racl->user_obj);
if (flags & XMIT_GROUP_OBJ)
write_varint(f, racl->group_obj);
if (flags & XMIT_MASK_OBJ)
write_varint(f, racl->mask_obj);
if (flags & XMIT_OTHER_OBJ)
write_varint(f, racl->other_obj);
if (flags & XMIT_NAME_LIST)
send_ida_entries(f, &racl->names);
/* Give the allocated data to the new list object. */
*new_racl = *racl;
*racl = empty_rsync_acl;
}
}
/* Send the ACL from the stat_x structure down the indicated file descriptor.
* This also frees the ACL data. */
void send_acl(int f, stat_x *sxp)
{
if (!sxp->acc_acl) {
sxp->acc_acl = create_racl();
rsync_acl_fake_perms(sxp->acc_acl, sxp->st.st_mode);
}
/* Avoid sending values that can be inferred from other data. */
rsync_acl_strip_perms(sxp);
send_rsync_acl(f, sxp->acc_acl, SMB_ACL_TYPE_ACCESS, &access_acl_list);
if (S_ISDIR(sxp->st.st_mode)) {
if (!sxp->def_acl)
sxp->def_acl = create_racl();
send_rsync_acl(f, sxp->def_acl, SMB_ACL_TYPE_DEFAULT, &default_acl_list);
}
}
/* === Receive functions === */
static uint32 recv_acl_access(int f, uchar *name_follows_ptr)
{
uint32 access = read_varint(f);
if (name_follows_ptr) {
int flags = access & 3;
access >>= 2;
if (am_root >= 0 && access & ~SMB_ACL_VALID_NAME_BITS)
goto value_error;
if (flags & XFLAG_NAME_FOLLOWS)
*name_follows_ptr = 1;
else
*name_follows_ptr = 0;
if (flags & XFLAG_NAME_IS_USER)
access |= NAME_IS_USER;
} else if (0 && am_root >= 0 && access & ~SMB_ACL_VALID_OBJ_BITS) {
/*
* This error check is disabled because rsync 3.x on cygwin sends
* a mask of 0xff instead of 0x7. I haven't looked into cygwin to
* see why that is.
*/
value_error:
rprintf(FERROR_XFER, "recv_acl_access: value out of range: %x\n",
access);
exit_cleanup(RERR_STREAMIO);
}
return access;
}
static uchar recv_ida_entries(int f, ida_entries *ent)
{
uchar computed_mask_bits = 0;
int i, count = read_varint(f);
if (count) {
if (!(ent->idas = new_array(id_access, count)))
out_of_memory("recv_ida_entries");
} else
ent->idas = NULL;
ent->count = count;
for (i = 0; i < count; i++) {
uchar has_name;
id_t id = read_varint(f);
uint32 access = recv_acl_access(f, &has_name);
if (has_name) {
if (access & NAME_IS_USER)
id = recv_user_name(f, id);
else
id = recv_group_name(f, id, NULL);
} else if (access & NAME_IS_USER) {
if (inc_recurse && am_root && !numeric_ids)
id = match_uid(id);
} else {
if (inc_recurse && (!am_root || !numeric_ids))
id = match_gid(id, NULL);
}
ent->idas[i].id = id;
ent->idas[i].access = access;
computed_mask_bits |= access;
}
return computed_mask_bits & ~NO_ENTRY;
}
static int recv_rsync_acl(int f, item_list *racl_list, SMB_ACL_TYPE_T type, UNUSED(mode_t mode))
{
uchar computed_mask_bits = 0;
acl_duo *duo_item;
uchar flags;
int ndx = read_varint(f);
if (ndx < 0 || (size_t)ndx > racl_list->count) {
rprintf(FERROR_XFER, "recv_acl_index: %s ACL index %d > %d\n",
str_acl_type(type), ndx, (int)racl_list->count);
exit_cleanup(RERR_STREAMIO);
}
if (ndx != 0)
return ndx - 1;
ndx = racl_list->count;
duo_item = EXPAND_ITEM_LIST(racl_list, acl_duo, 1000);
duo_item->racl = empty_rsync_acl;
flags = read_byte(f);
if (flags & XMIT_USER_OBJ)
duo_item->racl.user_obj = recv_acl_access(f, NULL);
if (flags & XMIT_GROUP_OBJ)
duo_item->racl.group_obj = recv_acl_access(f, NULL);
/*
* rsync 3.x on cygwin sends a mask of 0xff, rather than 0x7.
* That gives an error on the client rsync when we do a restore.
* So we mask off the right bits here
*/
if (flags & XMIT_MASK_OBJ)
duo_item->racl.mask_obj = recv_acl_access(f, NULL) & SMB_ACL_VALID_OBJ_BITS;
if (flags & XMIT_OTHER_OBJ)
duo_item->racl.other_obj = recv_acl_access(f, NULL);
if (flags & XMIT_NAME_LIST)
computed_mask_bits |= recv_ida_entries(f, &duo_item->racl.names);
#ifdef HAVE_OSX_ACLS
/* If we received a superfluous mask, throw it away. */
duo_item->racl.mask_obj = NO_ENTRY;
#else
if (duo_item->racl.names.count && duo_item->racl.mask_obj == NO_ENTRY) {
/* Mask must be non-empty with lists. */
if (type == SMB_ACL_TYPE_ACCESS)
computed_mask_bits = (mode >> 3) & 7;
else
computed_mask_bits |= duo_item->racl.group_obj & ~NO_ENTRY;
duo_item->racl.mask_obj = computed_mask_bits;
}
#endif
duo_item->sacl = NULL;
return ndx;
}
/* Receive the ACL info the sender has included for this file-list entry. */
void receive_acl(int f, struct file_struct *file)
{
F_ACL(file) = recv_rsync_acl(f, &access_acl_list, SMB_ACL_TYPE_ACCESS, file->mode);
if (S_ISDIR(file->mode))
F_DIR_DEFACL(file) = recv_rsync_acl(f, &default_acl_list, SMB_ACL_TYPE_DEFAULT, 0);
}
static int cache_rsync_acl(rsync_acl *racl, SMB_ACL_TYPE_T type, item_list *racl_list)
{
int ndx;
if (!racl)
ndx = -1;
else if ((ndx = find_matching_rsync_acl(racl, type, racl_list)) == -1) {
acl_duo *new_duo;
ndx = racl_list->count;
new_duo = EXPAND_ITEM_LIST(racl_list, acl_duo, 1000);
new_duo->racl = *racl;
new_duo->sacl = NULL;
*racl = empty_rsync_acl;
}
return ndx;
}
/* Turn the ACL data in stat_x into cached ACL data, setting the index
* values in the file struct. */
void cache_tmp_acl(struct file_struct *file, stat_x *sxp)
{
if (prior_access_count == (size_t)-1)
prior_access_count = access_acl_list.count;
F_ACL(file) = cache_rsync_acl(sxp->acc_acl,
SMB_ACL_TYPE_ACCESS, &access_acl_list);
if (S_ISDIR(sxp->st.st_mode)) {
if (prior_default_count == (size_t)-1)
prior_default_count = default_acl_list.count;
F_DIR_DEFACL(file) = cache_rsync_acl(sxp->def_acl,
SMB_ACL_TYPE_DEFAULT, &default_acl_list);
}
}
static void uncache_duo_acls(item_list *duo_list, size_t start)
{
acl_duo *duo_item = duo_list->items;
acl_duo *duo_start = duo_item + start;
duo_item += duo_list->count;
duo_list->count = start;
while (duo_item-- > duo_start) {
rsync_acl_free(&duo_item->racl);
if (duo_item->sacl)
sys_acl_free_acl(duo_item->sacl);
}
}
void uncache_tmp_acls(void)
{
if (prior_access_count != (size_t)-1) {
uncache_duo_acls(&access_acl_list, prior_access_count);
prior_access_count = (size_t)-1;
}
if (prior_default_count != (size_t)-1) {
uncache_duo_acls(&default_acl_list, prior_default_count);
prior_default_count = (size_t)-1;
}
}
#if 0
static mode_t change_sacl_perms(SMB_ACL_T sacl, rsync_acl *racl, mode_t old_mode, mode_t mode)
{
SMB_ACL_ENTRY_T entry;
const char *errfun;
int rc;
if (S_ISDIR(mode)) {
/* If the sticky bit is going on, it's not safe to allow all
* the new ACL to go into effect before it gets set. */
#ifdef SMB_ACL_LOSES_SPECIAL_MODE_BITS
if (mode & S_ISVTX)
mode &= ~0077;
#else
if (mode & S_ISVTX && !(old_mode & S_ISVTX))
mode &= ~0077;
} else {
/* If setuid or setgid is going off, it's not safe to allow all
* the new ACL to go into effect before they get cleared. */
if ((old_mode & S_ISUID && !(mode & S_ISUID))
|| (old_mode & S_ISGID && !(mode & S_ISGID)))
mode &= ~0077;
#endif
}
errfun = "sys_acl_get_entry";
for (rc = sys_acl_get_entry(sacl, SMB_ACL_FIRST_ENTRY, &entry);
rc == 1;
rc = sys_acl_get_entry(sacl, SMB_ACL_NEXT_ENTRY, &entry)) {
SMB_ACL_TAG_T tag_type;
if ((rc = sys_acl_get_tag_type(entry, &tag_type)) != 0) {
errfun = "sys_acl_get_tag_type";
break;
}
switch (tag_type) {
case SMB_ACL_USER_OBJ:
COE2( store_access_in_entry,((mode >> 6) & 7, entry) );
break;
case SMB_ACL_GROUP_OBJ:
/* group is only empty when identical to group perms. */
if (racl->group_obj != NO_ENTRY)
break;
COE2( store_access_in_entry,((mode >> 3) & 7, entry) );
break;
case SMB_ACL_MASK:
#ifndef HAVE_SOLARIS_ACLS
#ifndef ACLS_NEED_MASK
/* mask is only empty when we don't need it. */
if (racl->mask_obj == NO_ENTRY)
break;
#endif
COE2( store_access_in_entry,((mode >> 3) & 7, entry) );
#endif
break;
case SMB_ACL_OTHER:
COE2( store_access_in_entry,(mode & 7, entry) );
break;
}
}
if (rc) {
error_exit:
if (errfun) {
rsyserr(FERROR_XFER, errno, "change_sacl_perms: %s()",
errfun);
}
return (mode_t)-1;
}
#ifdef SMB_ACL_LOSES_SPECIAL_MODE_BITS
/* Ensure that chmod() will be called to restore any lost setid bits. */
if (old_mode & (S_ISUID | S_ISGID | S_ISVTX)
&& BITS_EQUAL(old_mode, mode, CHMOD_BITS))
old_mode &= ~(S_ISUID | S_ISGID | S_ISVTX);
#endif
/* Return the mode of the file on disk, as we will set them. */
return (old_mode & ~ACCESSPERMS) | (mode & ACCESSPERMS);
}
#endif
static int set_rsync_acl(const char *fname, acl_duo *duo_item,
SMB_ACL_TYPE_T type, UNUSED(stat_x *sxp), UNUSED(mode_t mode))
{
if (type == SMB_ACL_TYPE_DEFAULT
&& duo_item->racl.user_obj == NO_ENTRY) {
int rc;
#ifdef SUPPORT_XATTRS
/* --fake-super support: delete default ACL from xattrs. */
rc = del_def_xattr_acl(fname);
#endif
if (rc < 0) {
rsyserr(FERROR_XFER, errno, "set_acl: sys_acl_delete_def_file(%s)",
fname);
return -1;
}
#ifdef SUPPORT_XATTRS
} else if ( duo_item->racl.names.count == 0 && duo_item->racl.user_obj == NO_ENTRY && duo_item->racl.group_obj == NO_ENTRY
&& duo_item->racl.mask_obj == NO_ENTRY && duo_item->racl.other_obj == NO_ENTRY ) {
/* remove emtpy acls */
return del_acc_xattr_acl(fname);
} else {
/* --fake-super support: store ACLs in an xattr. */
int cnt = duo_item->racl.names.count;
size_t len = 4*4 + cnt * (4+4);
char *buf = new_array(char, len);
int rc;
SIVAL(buf, 0, duo_item->racl.user_obj);
SIVAL(buf, 4, duo_item->racl.group_obj);
SIVAL(buf, 8, duo_item->racl.mask_obj);
SIVAL(buf, 12, duo_item->racl.other_obj);
if (cnt) {
char *bp = buf + 4*4;
id_access *ida = duo_item->racl.names.idas;
for ( ; cnt--; ida++, bp += 4+4) {
SIVAL(bp, 0, ida->id);
SIVAL(bp, 4, ida->access);
}
}
rc = set_xattr_acl(fname, type == SMB_ACL_TYPE_ACCESS, buf, len);
free(buf);
return rc;
}
#endif
return 0;
}
/* Given a fname, this sets extended access ACL entries, the default ACL (for a
* dir), and the regular mode bits on the file. Call this with fname set to
* NULL to just check if the ACL is different.
*
* If the ACL operation has a side-effect of changing the file's mode, the
* sxp->st.st_mode value will be changed to match.
*
* Returns 0 for an unchanged ACL, 1 for changed, -1 for failed. */
int set_acl(const char *fname, const struct file_struct *file, stat_x *sxp, mode_t new_mode)
{
int changed = 0;
int32 ndx;
BOOL eq;
if (!dry_run && (read_only || list_only)) {
errno = EROFS;
return -1;
}
ndx = F_ACL(file);
if (ndx >= 0 && (size_t)ndx < access_acl_list.count) {
acl_duo *duo_item = access_acl_list.items;
duo_item += ndx;
eq = sxp->acc_acl
&& rsync_acl_equal_enough(sxp->acc_acl, &duo_item->racl, new_mode);
if (!eq) {
changed = 1;
if (!dry_run && fname
&& set_rsync_acl(fname, duo_item, SMB_ACL_TYPE_ACCESS,
sxp, new_mode) < 0)
return -1;
}
}
if (!S_ISDIR(new_mode))
return changed;
ndx = F_DIR_DEFACL(file);
if (ndx >= 0 && (size_t)ndx < default_acl_list.count) {
acl_duo *duo_item = default_acl_list.items;
duo_item += ndx;
eq = sxp->def_acl && rsync_acl_equal(sxp->def_acl, &duo_item->racl);
if (!eq) {
changed = 1;
if (!dry_run && fname
&& set_rsync_acl(fname, duo_item, SMB_ACL_TYPE_DEFAULT,
sxp, new_mode) < 0)
return -1;
}
}
return changed;
}
/* Non-incremental recursion needs to convert all the received IDs.
* This is done in a single pass after receiving the whole file-list. */
static void match_racl_ids(const item_list *racl_list)
{
int list_cnt, name_cnt;
acl_duo *duo_item = racl_list->items;
for (list_cnt = racl_list->count; list_cnt--; duo_item++) {
ida_entries *idal = &duo_item->racl.names;
id_access *ida = idal->idas;
for (name_cnt = idal->count; name_cnt--; ida++) {
if (ida->access & NAME_IS_USER)
ida->id = match_uid(ida->id);
else
ida->id = match_gid(ida->id, NULL);
}
}
}
void match_acl_ids(void)
{
match_racl_ids(&access_acl_list);
match_racl_ids(&default_acl_list);
}
#endif /* SUPPORT_ACLS */
rsync-bpc-3.1.3.0/authenticate.c 0000664 0000000 0000000 00000023336 13737671777 0016436 0 ustar 00root root 0000000 0000000 /*
* Support rsync daemon authentication.
*
* Copyright (C) 1998-2000 Andrew Tridgell
* Copyright (C) 2002-2018 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 "itypes.h"
extern int read_only;
extern char *password_file;
/***************************************************************************
encode a buffer using base64 - simple and slow algorithm. null terminates
the result.
***************************************************************************/
void base64_encode(const char *buf, int len, char *out, int pad)
{
char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
int bit_offset, byte_offset, idx, i;
const uchar *d = (const uchar *)buf;
int bytes = (len*8 + 5)/6;
for (i = 0; i < bytes; i++) {
byte_offset = (i*6)/8;
bit_offset = (i*6)%8;
if (bit_offset < 3) {
idx = (d[byte_offset] >> (2-bit_offset)) & 0x3F;
} else {
idx = (d[byte_offset] << (bit_offset-2)) & 0x3F;
if (byte_offset+1 < len) {
idx |= (d[byte_offset+1] >> (8-(bit_offset-2)));
}
}
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(const char *addr, char *challenge)
{
char input[32];
char digest[MAX_DIGEST_LEN];
struct timeval tv;
int len;
memset(input, 0, sizeof input);
strlcpy(input, addr, 17);
sys_gettimeofday(&tv);
SIVAL(input, 16, tv.tv_sec);
SIVAL(input, 20, tv.tv_usec);
SIVAL(input, 24, getpid());
sum_init(-1, 0);
sum_update(input, sizeof input);
len = sum_end(digest);
base64_encode(digest, len, challenge, 0);
}
/* Generate an MD4 hash created from the combination of the password
* and the challenge string and return it base64-encoded. */
static void generate_hash(const char *in, const char *challenge, char *out)
{
char buf[MAX_DIGEST_LEN];
int len;
sum_init(-1, 0);
sum_update(in, strlen(in));
sum_update(challenge, strlen(challenge));
len = sum_end(buf);
base64_encode(buf, len, out, 0);
}
/* Return the secret for a user from the secret file, null terminated.
* Maximum length is len (not counting the null). */
static const char *check_secret(int module, const char *user, const char *group,
const char *challenge, const char *pass)
{
char line[1024];
char pass2[MAX_DIGEST_LEN*2];
const char *fname = lp_secrets_file(module);
STRUCT_STAT st;
int ok = 1;
int user_len = strlen(user);
int group_len = group ? strlen(group) : 0;
char *err;
FILE *fh;
if (!fname || !*fname || (fh = fopen(fname, "r")) == NULL)
return "no secrets file";
if (fstat(fileno(fh), &st) == -1) {
rsyserr(FLOG, errno, "fstat(%s)", fname);
ok = 0;
} else if (lp_strict_modes(module)) {
if ((st.st_mode & 06) != 0) {
rprintf(FLOG, "secrets file must not be other-accessible (see strict modes option)\n");
ok = 0;
} else if (MY_UID() == 0 && st.st_uid != 0) {
rprintf(FLOG, "secrets file must be owned by root when running as root (see strict modes)\n");
ok = 0;
}
}
if (!ok) {
fclose(fh);
return "ignoring secrets file";
}
if (*user == '#') {
/* Reject attempt to match a comment. */
fclose(fh);
return "invalid username";
}
/* Try to find a line that starts with the user (or @group) name and a ':'. */
err = "secret not found";
while ((user || group) && fgets(line, sizeof line, fh) != NULL) {
const char **ptr, *s = strtok(line, "\n\r");
int len;
if (!s)
continue;
if (*s == '@') {
ptr = &group;
len = group_len;
s++;
} else {
ptr = &user;
len = user_len;
}
if (!*ptr || strncmp(s, *ptr, len) != 0 || s[len] != ':')
continue;
generate_hash(s+len+1, challenge, pass2);
if (strcmp(pass, pass2) == 0) {
err = NULL;
break;
}
err = "password mismatch";
*ptr = NULL; /* Don't look for name again. */
}
fclose(fh);
memset(line, 0, sizeof line);
memset(pass2, 0, sizeof pass2);
return err;
}
static const char *getpassf(const char *filename)
{
STRUCT_STAT st;
char buffer[512], *p;
int n;
if (!filename)
return NULL;
if (strcmp(filename, "-") == 0) {
n = fgets(buffer, sizeof buffer, stdin) == NULL ? -1 : (int)strlen(buffer);
} else {
int fd;
if ((fd = open(filename,O_RDONLY)) < 0) {
rsyserr(FERROR, errno, "could not open password file %s", filename);
exit_cleanup(RERR_SYNTAX);
}
if (stat(filename, &st) == -1) {
rsyserr(FERROR, errno, "stat(%s)", filename);
exit_cleanup(RERR_SYNTAX);
}
if ((st.st_mode & 06) != 0) {
rprintf(FERROR, "ERROR: password file must not be other-accessible\n");
exit_cleanup(RERR_SYNTAX);
}
if (MY_UID() == 0 && st.st_uid != 0) {
rprintf(FERROR, "ERROR: password file must be owned by root when running as root\n");
exit_cleanup(RERR_SYNTAX);
}
n = read(fd, buffer, sizeof buffer - 1);
close(fd);
}
if (n > 0) {
buffer[n] = '\0';
if ((p = strtok(buffer, "\n\r")) != NULL)
return strdup(p);
}
rprintf(FERROR, "ERROR: failed to read a password from %s\n", filename);
exit_cleanup(RERR_SYNTAX);
}
/* Possibly negotiate authentication with the client. Use "leader" to
* start off the auth if necessary.
*
* Return NULL if authentication failed. Return "" if anonymous access.
* Otherwise return username.
*/
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[MAX_DIGEST_LEN*2];
char line[BIGPATHBUFLEN];
char **auth_uid_groups = NULL;
int auth_uid_groups_cnt = -1;
const char *err = NULL;
int group_match = -1;
char *tok, *pass;
char opt_ch = '\0';
/* if no auth list then allow anyone in! */
if (!users || !*users)
return "";
gen_challenge(addr, challenge);
io_printf(f_out, "%s%s\n", leader, challenge);
if (!read_line_old(f_in, line, sizeof line, 0)
|| (pass = strchr(line, ' ')) == NULL) {
rprintf(FLOG, "auth failed on module %s from %s (%s): "
"invalid challenge response\n",
lp_name(module), host, addr);
return NULL;
}
*pass++ = '\0';
if (!(users = strdup(users)))
out_of_memory("auth_server");
for (tok = strtok(users, " ,\t"); tok; tok = strtok(NULL, " ,\t")) {
char *opts;
/* See if the user appended :deny, :ro, or :rw. */
if ((opts = strchr(tok, ':')) != NULL) {
*opts++ = '\0';
opt_ch = isUpper(opts) ? toLower(opts) : *opts;
if (opt_ch == 'r') { /* handle ro and rw */
opt_ch = isUpper(opts+1) ? toLower(opts+1) : opts[1];
if (opt_ch == 'o')
opt_ch = 'r';
else if (opt_ch != 'w')
opt_ch = '\0';
} else if (opt_ch != 'd') /* if it's not deny, ignore it */
opt_ch = '\0';
} else
opt_ch = '\0';
if (*tok != '@') {
/* Match the username */
if (wildmatch(tok, line))
break;
} else {
#ifdef HAVE_GETGROUPLIST
int j;
/* See if authorizing user is a real user, and if so, see
* if it is in a group that matches tok+1 wildmat. */
if (auth_uid_groups_cnt < 0) {
item_list gid_list = EMPTY_ITEM_LIST;
uid_t auth_uid;
if (!user_to_uid(line, &auth_uid, False)
|| getallgroups(auth_uid, &gid_list) != NULL)
auth_uid_groups_cnt = 0;
else {
gid_t *gid_array = gid_list.items;
auth_uid_groups_cnt = gid_list.count;
if ((auth_uid_groups = new_array(char *, auth_uid_groups_cnt)) == NULL)
out_of_memory("auth_server");
for (j = 0; j < auth_uid_groups_cnt; j++)
auth_uid_groups[j] = gid_to_group(gid_array[j]);
}
}
for (j = 0; j < auth_uid_groups_cnt; j++) {
if (auth_uid_groups[j] && wildmatch(tok+1, auth_uid_groups[j])) {
group_match = j;
break;
}
}
if (group_match >= 0)
break;
#else
rprintf(FLOG, "your computer doesn't support getgrouplist(), so no @group authorization is possible.\n");
#endif
}
}
free(users);
if (!tok)
err = "no matching rule";
else if (opt_ch == 'd')
err = "denied by rule";
else {
char *group = group_match >= 0 ? auth_uid_groups[group_match] : NULL;
err = check_secret(module, line, group, challenge, pass);
}
memset(challenge, 0, sizeof challenge);
memset(pass, 0, strlen(pass));
if (auth_uid_groups) {
int j;
for (j = 0; j < auth_uid_groups_cnt; j++) {
if (auth_uid_groups[j])
free(auth_uid_groups[j]);
}
free(auth_uid_groups);
}
if (err) {
rprintf(FLOG, "auth failed on module %s from %s (%s) for %s: %s\n",
lp_name(module), host, addr, line, err);
return NULL;
}
if (opt_ch == 'r')
read_only = 1;
else if (opt_ch == 'w')
read_only = 0;
return strdup(line);
}
void auth_client(int fd, const char *user, const char *challenge)
{
const char *pass;
char pass2[MAX_DIGEST_LEN*2];
if (!user || !*user)
user = "nobody";
if (!(pass = getpassf(password_file))
&& !(pass = getenv("RSYNC_PASSWORD"))) {
/* XXX: cyeoh says that getpass is deprecated, because
* it may return a truncated password on some systems,
* and it is not in the LSB.
*
* Andrew Klein says that getpassphrase() is present
* on Solaris and reads up to 256 characters.
*
* OpenBSD has a readpassphrase() that might be more suitable.
*/
pass = getpass("Password: ");
}
if (!pass)
pass = "";
generate_hash(pass, challenge, pass2);
io_printf(fd, "%s %s\n", user, pass2);
}
rsync-bpc-3.1.3.0/backup.c 0000664 0000000 0000000 00000021765 13737671777 0015231 0 ustar 00root root 0000000 0000000 /*
* Backup handling code.
*
* Copyright (C) 1999 Andrew Tridgell
* Copyright (C) 2003-2018 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 "ifuncs.h"
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;
/* Returns -1 on error, 0 on missing dir, and 1 on present dir. */
static int validate_backup_dir(void)
{
STRUCT_STAT st;
if (do_lstat(backup_dir_buf, &st) < 0) {
if (errno == ENOENT)
return 0;
rsyserr(FERROR, errno, "backup lstat %s failed", backup_dir_buf);
return -1;
}
if (!S_ISDIR(st.st_mode)) {
int flags = get_del_for_flag(st.st_mode) | DEL_FOR_BACKUP | DEL_RECURSE;
if (delete_item(backup_dir_buf, st.st_mode, flags) == 0)
return 0;
return -1;
}
return 1;
}
/* Create a backup path from the given fname, putting the result into
* backup_dir_buf. Any new directories (compared to the prior backup
* path) are ensured to exist as directories, replacing anything else
* that may be in the way (e.g. a symlink). */
static BOOL copy_valid_path(const char *fname)
{
const char *f;
int val;
BOOL ret = True;
stat_x sx;
char *b, *rel = backup_dir_buf + backup_dir_len, *name = rel;
for (f = fname, b = rel; *f && *f == *b; f++, b++) {
if (*b == '/')
name = b + 1;
}
if (stringjoin(rel, backup_dir_remainder, fname, backup_suffix, NULL) >= backup_dir_remainder) {
rprintf(FERROR, "backup filename too long\n");
*name = '\0';
return False;
}
for ( ; ; name = b + 1) {
if ((b = strchr(name, '/')) == NULL)
return True;
*b = '\0';
val = validate_backup_dir();
if (val == 0)
break;
if (val < 0) {
*name = '\0';
return False;
}
*b = '/';
}
init_stat_x(&sx);
for ( ; b; name = b + 1, b = strchr(name, '/')) {
*b = '\0';
while (do_mkdir(backup_dir_buf, ACCESSPERMS) < 0) {
if (errno == EEXIST) {
val = validate_backup_dir();
if (val > 0)
break;
if (val == 0)
continue;
} else
rsyserr(FERROR, errno, "backup mkdir %s failed", backup_dir_buf);
*name = '\0';
ret = False;
goto cleanup;
}
/* Try to transfer the directory settings of the actual dir
* that the files are coming from. */
if (x_stat(rel, &sx.st, NULL) < 0)
rsyserr(FERROR, errno, "backup stat %s failed", full_fname(rel));
else {
struct file_struct *file;
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_tmp_acl(file, &sx);
free_acl(&sx);
}
#endif
#ifdef SUPPORT_XATTRS
if (preserve_xattrs) {
get_xattr(rel, &sx);
cache_tmp_xattr(file, &sx);
free_xattr(&sx);
}
#endif
set_file_attrs(backup_dir_buf, file, NULL, NULL, 0);
unmake_file(file);
}
*b = '/';
}
cleanup:
#ifdef SUPPORT_ACLS
uncache_tmp_acls();
#endif
#ifdef SUPPORT_XATTRS
uncache_tmp_xattrs();
#endif
return ret;
}
/* Make a complete pathname for backup file and verify any new path elements. */
char *get_backup_name(const char *fname)
{
if (backup_dir) {
static int initialized = 0;
if (!initialized) {
int ret;
if (backup_dir_len > 1)
backup_dir_buf[backup_dir_len-1] = '\0';
ret = make_path(backup_dir_buf, 0);
if (backup_dir_len > 1)
backup_dir_buf[backup_dir_len-1] = '/';
if (ret < 0)
return NULL;
initialized = 1;
}
/* copy fname into backup_dir_buf while validating the dirs. */
if (copy_valid_path(fname))
return backup_dir_buf;
/* copy_valid_path() has printed an error message. */
return NULL;
}
if (stringjoin(backup_dir_buf, MAXPATHLEN, fname, backup_suffix, NULL) < MAXPATHLEN)
return backup_dir_buf;
rprintf(FERROR, "backup filename too long\n");
return NULL;
}
/* Has same return codes as make_backup(). */
static inline int link_or_rename(const char *from, const char *to,
BOOL prefer_rename, STRUCT_STAT *stp)
{
#ifdef SUPPORT_HARD_LINKS
if (!prefer_rename) {
#ifndef CAN_HARDLINK_SYMLINK
if (S_ISLNK(stp->st_mode))
return 0; /* Use copy code. */
#endif
#ifndef CAN_HARDLINK_SPECIAL
if (IS_SPECIAL(stp->st_mode) || IS_DEVICE(stp->st_mode))
return 0; /* Use copy code. */
#endif
if (do_link(from, to) == 0) {
if (DEBUG_GTE(BACKUP, 1))
rprintf(FINFO, "make_backup: HLINK %s successful.\n", from);
return 2;
}
/* We prefer to rename a regular file rather than copy it. */
if (!S_ISREG(stp->st_mode) || errno == EEXIST || errno == EISDIR)
return 0;
}
#endif
if (do_rename(from, to) == 0) {
if (stp->st_nlink > 1 && !S_ISDIR(stp->st_mode)) {
/* If someone has hard-linked the file into the backup
* dir, rename() might return success but do nothing! */
robust_unlink(from); /* Just in case... */
}
if (DEBUG_GTE(BACKUP, 1))
rprintf(FINFO, "make_backup: RENAME %s successful.\n", from);
return 1;
}
return 0;
}
/* Hard-link, rename, or copy an item to the backup name. Returns 0 for
* failure, 1 if item was moved, 2 if item was duplicated or hard linked
* into backup area, or 3 if item doesn't exist or isn't a regular file. */
int make_backup(const char *fname, BOOL prefer_rename)
{
stat_x sx;
struct file_struct *file;
int save_preserve_xattrs;
char *buf;
int ret = 0;
init_stat_x(&sx);
/* Return success if no file to keep. */
if (x_lstat(fname, &sx.st, NULL) < 0)
return 3;
if (!(buf = get_backup_name(fname)))
return 0;
/* Try a hard-link or a rename first. Using rename is not atomic, but
* is more efficient than forcing a copy for larger files when no hard-
* linking is possible. */
if ((ret = link_or_rename(fname, buf, prefer_rename, &sx.st)) != 0)
goto success;
if (errno == EEXIST || errno == EISDIR) {
STRUCT_STAT bakst;
if (do_lstat(buf, &bakst) == 0) {
int flags = get_del_for_flag(bakst.st_mode) | DEL_FOR_BACKUP | DEL_RECURSE;
if (delete_item(buf, bakst.st_mode, flags) != 0)
return 0;
}
if ((ret = link_or_rename(fname, buf, prefer_rename, &sx.st)) != 0)
goto success;
}
/* Fall back to making a copy. */
if (!(file = make_file(fname, NULL, &sx.st, 0, NO_FILTERS)))
return 3; /* the file could have disappeared */
#ifdef SUPPORT_ACLS
if (preserve_acls && !S_ISLNK(file->mode)) {
get_acl(fname, &sx);
cache_tmp_acl(file, &sx);
free_acl(&sx);
}
#endif
#ifdef SUPPORT_XATTRS
if (preserve_xattrs) {
get_xattr(fname, &sx);
cache_tmp_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))) {
if (do_mknod(buf, file->mode, sx.st.st_rdev) < 0)
rsyserr(FERROR, errno, "mknod %s failed", full_fname(buf));
else if (DEBUG_GTE(BACKUP, 1))
rprintf(FINFO, "make_backup: DEVICE %s successful.\n", fname);
ret = 2;
}
#ifdef SUPPORT_LINKS
if (!ret && preserve_links && S_ISLNK(file->mode)) {
const char *sl = F_SYMLINK(file);
if (safe_symlinks && unsafe_symlink(sl, fname)) {
if (INFO_GTE(SYMSAFE, 1)) {
rprintf(FINFO, "not backing up unsafe symlink \"%s\" -> \"%s\"\n",
fname, sl);
}
ret = 2;
} else {
if (do_symlink(sl, buf) < 0)
rsyserr(FERROR, errno, "link %s -> \"%s\"", full_fname(buf), sl);
else if (DEBUG_GTE(BACKUP, 1))
rprintf(FINFO, "make_backup: SYMLINK %s successful.\n", fname);
ret = 2;
}
}
#endif
if (!ret && !S_ISREG(file->mode)) {
rprintf(FINFO, "make_bak: skipping non-regular file %s\n", fname);
unmake_file(file);
#ifdef SUPPORT_XATTRS
uncache_tmp_xattrs();
#endif
return 3;
}
/* Copy to backup tree if a file. */
if (!ret) {
if (copy_file(fname, buf, -1, file->mode) < 0) {
rsyserr(FERROR, errno, "keep_backup failed: %s -> \"%s\"",
full_fname(fname), buf);
unmake_file(file);
#ifdef SUPPORT_ACLS
uncache_tmp_acls();
#endif
#ifdef SUPPORT_XATTRS
uncache_tmp_xattrs();
#endif
return 0;
}
if (DEBUG_GTE(BACKUP, 1))
rprintf(FINFO, "make_backup: COPY %s successful.\n", fname);
ret = 2;
}
save_preserve_xattrs = preserve_xattrs;
preserve_xattrs = 0;
set_file_attrs(buf, file, NULL, fname, ATTRS_SET_NANO);
preserve_xattrs = save_preserve_xattrs;
unmake_file(file);
#ifdef SUPPORT_XATTRS
uncache_tmp_xattrs();
#endif
success:
if (INFO_GTE(BACKUP, 1))
rprintf(FINFO, "backed up %s to %s\n", fname, buf);
return ret;
}
rsync-bpc-3.1.3.0/backuppc/ 0000775 0000000 0000000 00000000000 13737671777 0015375 5 ustar 00root root 0000000 0000000 rsync-bpc-3.1.3.0/backuppc/backuppc.h 0000664 0000000 0000000 00000042751 13737671777 0017347 0 ustar 00root root 0000000 0000000 /*
* Definitions for BackupPC libraries.
*
* Copyright (C) 2013 Craig Barratt.
*
* 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.
*/
#ifndef _BACKUPPC_H_
#define _BACKUPPC_H_
#include
#include "zlib/zlib.h"
#define BPC_MAXPATHLEN (2 * MAXPATHLEN)
extern int BPC_HardLinkMax;
extern int BPC_PoolV3Enabled;
extern int BPC_TmpFileUnique;
extern int BPC_LogLevel;
/*
* String buffer functions
*/
typedef struct _bpc_strBuf {
char *s;
size_t size;
char buffer[2048];
struct _bpc_strBuf *next; /* for free list */
} bpc_strBuf;
bpc_strBuf *bpc_strBuf_new(void);
void bpc_strBuf_init(bpc_strBuf *buf);
void bpc_strBuf_free(bpc_strBuf *buf);
void bpc_strBuf_resize(bpc_strBuf *buf, size_t needed);
char *bpc_strBuf_strcpy(bpc_strBuf *buf, unsigned int offset, char *str);
char *bpc_strBuf_strcat(bpc_strBuf *buf, unsigned int offset, char *str);
int bpc_strBuf_vsnprintf(bpc_strBuf *buf, unsigned int offset, char *fmt, va_list args);
int bpc_strBuf_snprintf(bpc_strBuf *buf, unsigned int offset, char *fmt, ...);
extern bpc_strBuf BPC_PoolDir;
extern bpc_strBuf BPC_CPoolDir;
extern bpc_strBuf BPC_PoolDir3;
extern bpc_strBuf BPC_CPoolDir3;
extern bpc_strBuf BPC_TopDir;
/*
* Maximum length of a digest - 16 bytes for MD5, but 4 bytes of collision counting
*/
#define BPC_DIGEST_LEN_MAX 20
#define uint64 unsigned int64
typedef struct {
uchar digest[BPC_DIGEST_LEN_MAX];
int len;
} bpc_digest;
/*
* Simple hash table functions.
*
* Any structure stored in a hash table should start with a bpc_hashtable_key entry for the key.
*/
typedef struct {
void *key; /* a NULL key means this node is empty or deleted; also used for free list */
uint32 keyLen; /* with a NULL key, a zero value means empty; non-zero means deleted */
uint32 keyHash;
} bpc_hashtable_key;
typedef struct {
bpc_hashtable_key **nodes;
uint32 nodeSize;
uint32 size;
uint32 entries; /* total number of user entries */
uint32 entriesDel; /* number of entries flagged as deleted */
} bpc_hashtable;
void bpc_hashtable_create(bpc_hashtable *tbl, uint32 size, uint32 nodeSize);
void bpc_hashtable_destroy(bpc_hashtable *tbl);
void bpc_hashtable_erase(bpc_hashtable *tbl);
uint32 bpc_hashtable_hash(uchar *key, uint32 keyLen);
void *bpc_hashtable_find(bpc_hashtable *tbl, unsigned char *key, unsigned int keyLen, int allocate_if_missing);
void bpc_hashtable_growSize(bpc_hashtable *tbl, uint32 newSize);
void bpc_hashtable_nodeDelete(bpc_hashtable *tbl, void *node);
void bpc_hashtable_iterate(bpc_hashtable *tbl, void (*callback)(void*, void*), void *arg1);
void *bpc_hashtable_nextEntry(bpc_hashtable *tbl, uint *idx);
int bpc_hashtable_entryCount(bpc_hashtable *tbl);
/*
* Reference counting
*/
typedef struct {
bpc_hashtable ht;
int initDone;
} bpc_refCount_info;
void bpc_poolRefInit(bpc_refCount_info *info, int entryCnt);
void bpc_poolRefDestroy(bpc_refCount_info *info);
void bpc_poolRefSet(bpc_refCount_info *info, bpc_digest *digest, int32 count);
int bpc_poolRefDelete(bpc_refCount_info *info, bpc_digest *digest);
int bpc_poolRefGet(bpc_refCount_info *info, bpc_digest *digest, int32 *count);
int bpc_poolRefIncr(bpc_refCount_info *info, bpc_digest *digest, int32 delta);
int bpc_poolRefIterate(bpc_refCount_info *info, bpc_digest *digest, int32 *count, uint *idx);
void bpc_poolRefCountPrint(bpc_refCount_info *info);
int bpc_poolRefFileWrite(bpc_refCount_info *info, char *fileName);
int bpc_poolRefFileRead(bpc_refCount_info *info, char *fileName);
void bpc_poolRefRequestFsck(char *targetDir, int ext);
/*
* Delta counting
*/
typedef struct {
bpc_refCount_info refCnt[2];
bpc_strBuf *targetDir;
} bpc_deltaCount_info;
void bpc_poolRefDeltaFileInit(bpc_deltaCount_info *info, char *hostDir);
void bpc_poolRefDeltaFileDestroy(bpc_deltaCount_info *info);
uint32 bpc_poolRefDeltaFileFlush(bpc_deltaCount_info *info);
void bpc_poolRefDeltaUpdate(bpc_deltaCount_info *info, int compress, bpc_digest *digest, int32 count);
void bpc_poolRefDeltaPrint(bpc_deltaCount_info *info);
void bpc_poolRefDeltaFileInitOld(char *hostDir);
uint32 bpc_poolRefDeltaFileFlushOld(void);
void bpc_poolRefDeltaUpdateOld(int compress, bpc_digest *digest, int32 count);
void bpc_poolRefDeltaPrintOld(void);
/*
* Compressed file IO. A compressed file descriptor contains a buffer for compressed data.
*/
typedef struct {
z_stream strm;
char *buf;
size_t bufSize;
int fd;
int first;
int write;
int eof;
int error;
int compressLevel;
int writeTeeStderr;
/*
* readLine buffer
*/
char *lineBuf;
size_t lineBufSize;
size_t lineBufLen;
size_t lineBufIdx;
int lineBufEof;
} bpc_fileZIO_fd;
int bpc_fileZIO_open(bpc_fileZIO_fd *fd, char *fileName, int writeFile, int compressLevel);
int bpc_fileZIO_fdopen(bpc_fileZIO_fd *fd, FILE *stream, int writeFile, int compressLevel);
void bpc_fileZIO_writeTeeStderr(bpc_fileZIO_fd *fd, int tee);
ssize_t bpc_fileZIO_read(bpc_fileZIO_fd *fd, uchar *buf, size_t nRead);
ssize_t bpc_fileZIO_write(bpc_fileZIO_fd *fd, uchar *buf, size_t nWrite);
int bpc_fileZIO_readLine(bpc_fileZIO_fd *fd, char **str, size_t *strLen);
int bpc_fileZIO_close(bpc_fileZIO_fd *fd);
int bpc_fileZIO_rewind(bpc_fileZIO_fd *fd);
#define BPC_POOL_WRITE_BUF_SZ (8 * 1048576) /* 8 MB - must be at least 1MB so the V3 digest calculation can occur */
#define BPC_POOL_WRITE_CONCURRENT_MATCH (16) /* number of pool files we concurrently match */
typedef struct _bpc_candidate_file {
bpc_digest digest;
OFF_T fileSize;
int v3File;
bpc_strBuf *fileName;
struct _bpc_candidate_file *next;
} bpc_candidate_file;
typedef struct {
bpc_fileZIO_fd fd;
int used;
int v3File;
OFF_T fileSize;
bpc_digest digest;
bpc_strBuf *fileName;
} bpc_candidate_match;
typedef struct {
int compress;
int state;
int eof;
int retValue;
int retryCnt;
OFF_T fileSize;
OFF_T poolFileSize;
bpc_digest digest;
bpc_digest digest_v3;
md_context md5;
/*
* Set of active potential file matches. All files match up to matchPosn.
*/
OFF_T matchPosn;
bpc_candidate_match match[BPC_POOL_WRITE_CONCURRENT_MATCH];
bpc_candidate_file *candidateList;
/*
* When we first build the candidate match list, we remember where the first
* zero-length file is (if any), and the next open slot. If these change
* before we insert a new file, we know to try again (since someone probably
* won a race to get there first).
*/
int digestExtZeroLen, digestExtOpen;
/*
* Temporary output file if the in-memory buffer is too small
*/
int fdOpen;
bpc_fileZIO_fd fd;
bpc_strBuf *tmpFileName;
/*
* Error count
*/
int errorCnt;
/*
* Initial file buffer - used if the entire file fits, or otherwise keeps the first 1MB
* of the file so we can compute the V3 digest. If we have the entire file in memory
* then fileWritten == 0.
*
* This buffer is allocated to be size BPC_POOL_WRITE_BUF_SZ on open() and freed on close().
*/
uint32 bufferIdx;
uchar *buffer;
} bpc_poolWrite_info;
int bpc_poolWrite_open(bpc_poolWrite_info *info, int compress, bpc_digest *digest);
int bpc_poolWrite_write(bpc_poolWrite_info *info, uchar *data, size_t dataLen);
int bpc_poolWrite_createPoolDir(bpc_poolWrite_info *info, bpc_digest *digest);
void bpc_poolWrite_close(bpc_poolWrite_info *info, int *match, bpc_digest *digest, OFF_T *poolFileSize, int *errorCnt);
void bpc_poolWrite_cleanup(bpc_poolWrite_info *info);
void bpc_poolWrite_repeatPoolWrite(bpc_poolWrite_info *info, char *fileName);
int bpc_poolWrite_copyToPool(bpc_poolWrite_info *info, char *poolPath, char *fileName);
void bpc_poolWrite_addToPool(bpc_poolWrite_info *info, char *fileName, int v3PoolFile);
int bpc_poolWrite_unmarkPendingDelete(char *poolPath);
/*
* General library routines
*/
void bpc_lib_conf_init(char *topDir, int hardLinkMax, int poolV3Enabled, int logLevel);
void bpc_lib_setTmpFileUnique(int val);
int bpc_lib_setLogLevel(int logLevel);
void bpc_byte2hex(char *outStr, int byte);
uchar bpc_hexStr2byte(char c1, char c2);
void bpc_digest_buffer2MD5(bpc_digest *digest, uchar *buffer, size_t bufferLen);
void bpc_digest_append_ext(bpc_digest *digest, uint32 ext);
void bpc_digest_digest2str(bpc_digest *digest, char *hexStr);
void bpc_digest_str2digest(bpc_digest *digest, char *hexStr);
int bpc_digest_compare(bpc_digest *digest1, bpc_digest *digest2);
void bpc_digest_md52path(bpc_strBuf *path, int compress, bpc_digest *digest);
void bpc_digest_md52path_v3(bpc_strBuf *path, int compress, bpc_digest *digest);
void bpc_digest_buffer2MD5_v3(bpc_digest *digest, uchar *buffer, size_t bufferLen);
void bpc_fileNameEltMangle(bpc_strBuf *path, char *pathUM);
void bpc_fileNameMangle(bpc_strBuf *path, char *pathUM, unsigned int i);
void bpc_logMsgf(char *fmt, ...);
void bpc_logErrf(char *fmt, ...);
void bpc_logMsgGet(char **mesg, size_t *mesgLen);
void bpc_logMsgErrorCntGet(unsigned long *errorCnt);
void bpc_logMsgCBSet(void (*cb)(int errFlag, char *mesg, size_t mesgLen));
/*
* Compute file digest
*/
int bpc_fileDigest(char *fileName, int compress, bpc_digest *digest);
/*
* Directory operations
*/
int bpc_path_create(char *path);
int bpc_path_remove(bpc_deltaCount_info *deltaInfo, char *path, int compress);
int bpc_path_refCountAll(bpc_deltaCount_info *deltaInfo, char *path, int compress, int incr);
int bpc_path_refCountAllInodeMax(bpc_deltaCount_info *deltaInfo, char *path, int compress, int incr, unsigned int *inodeMax);
int bpc_lockRangeFd(int fd, OFF_T offset, OFF_T len, int block);
int bpc_unlockRangeFd(int fd, OFF_T offset, OFF_T len);
int bpc_lockRangeFile(char *lockFile, OFF_T offset, OFF_T len, int block);
void bpc_unlockRangeFile(int lockFd);
/*
* File attribs
*/
typedef struct {
bpc_hashtable_key key;
void *value;
uint32 valueLen;
} bpc_attrib_xattr;
typedef struct {
bpc_hashtable_key key;
char *name;
ushort type;
ushort compress;
/*
* isTemp is set if this is a temporary attribute entry (eg: mkstemp), that
* doesn't have referencing counting for the digest. Therefore, when a
* temporary file is created or deleted, there is no change to the
* reference counts.
*/
ushort isTemp;
uint32 mode;
uid_t uid;
gid_t gid;
uint32 nlinks;
time_t mtime;
OFF_T size;
ino_t inode;
int32 backupNum;
bpc_digest digest;
/*
* hash table of bpc_attrib_xattr entries, indexed by xattr key
*/
bpc_hashtable xattrHT;
} bpc_attrib_file;
/*
* A directory is a hash table of file attributes, indexed by file name
*/
typedef struct {
bpc_digest digest;
ushort compress;
ushort needRewrite;
/*
* hash table of bpc_attrib_file entries, indexed by file name
*/
bpc_hashtable filesHT;
} bpc_attrib_dir;
bpc_attrib_xattr *bpc_attrib_xattrGet(bpc_attrib_file *file, void *key, int keyLen, int allocate_if_missing);
void bpc_attrib_xattrDestroy(bpc_attrib_xattr *xattr);
int bpc_attrib_xattrDelete(bpc_attrib_file *file, void *key, int keyLen);
int bpc_attrib_xattrDeleteAll(bpc_attrib_file *file);
int bpc_attrib_xattrSetValue(bpc_attrib_file *file, void *key, int keyLen, void *value, uint32 valueLen);
int bpc_attrib_xattrCount(bpc_attrib_file *file);
size_t bpc_attrib_xattrList(bpc_attrib_file *file, char *list, size_t listLen, int ignoreRsyncACLs);
void bpc_attrib_fileInit(bpc_attrib_file *file, char *fileName, int xattrNumEntries);
void bpc_attrib_fileDestroy(bpc_attrib_file *file);
bpc_attrib_file *bpc_attrib_fileGet(bpc_attrib_dir *dir, char *fileName, int allocate_if_missing);
int bpc_attrib_fileIterate(bpc_attrib_dir *dir, bpc_attrib_file **file, uint *idx);
void bpc_attrib_fileCopyOpt(bpc_attrib_file *fileDest, bpc_attrib_file *fileSrc, int overwriteEmptyDigest);
void bpc_attrib_fileCopy(bpc_attrib_file *fileDest, bpc_attrib_file *fileSrc);
int bpc_attrib_fileCompare(bpc_attrib_file *file0, bpc_attrib_file *file1);
void bpc_attrib_fileDeleteName(bpc_attrib_dir *dir, char *fileName);
int bpc_attrib_fileCount(bpc_attrib_dir *dir);
char *bpc_attrib_fileType2Text(int type);
void bpc_attrib_dirInit(bpc_attrib_dir *dir, int compressLevel);
void bpc_attrib_dirDestroy(bpc_attrib_dir *dir);
int bpc_attrib_dirNeedRewrite(bpc_attrib_dir *dir);
ssize_t bpc_attrib_getEntries(bpc_attrib_dir *dir, char *entries, ssize_t entrySize);
void bpc_attrib_dirRefCount(bpc_deltaCount_info *deltaInfo, bpc_attrib_dir *dir, int incr);
void bpc_attrib_dirRefCountInodeMax(bpc_deltaCount_info *deltaInfo, bpc_attrib_dir *dir, int incr, unsigned int *inodeMax);
void bpc_attrib_attribFilePath(bpc_strBuf *path, char *dir, char *attribFileName);
bpc_digest *bpc_attrib_dirDigestGet(bpc_attrib_dir *dir);
uchar *bpc_attrib_buf2file(bpc_attrib_file *file, uchar *buf, uchar *bufEnd, int xattrNumEntries, int *xattrFixup);
uchar *bpc_attrib_buf2fileFull(bpc_attrib_file *file, uchar *buf, uchar *bufEnd);
uchar *bpc_attrib_file2buf(bpc_attrib_file *file, uchar *buf, uchar *bufEnd);
int bpc_attrib_digestRead(bpc_attrib_dir *dir, bpc_digest *digest, char *attribPath);
int bpc_attrib_dirRead(bpc_attrib_dir *dir, char *dirPath, char *attribFileName, int backupNum);
int bpc_attrib_dirWrite(bpc_deltaCount_info *deltaInfo, bpc_attrib_dir *dir, char *dirPath, char *attribFileName, bpc_digest *oldDigest);
void bpc_attrib_backwardCompat(int writeOldStyleAttribFile, int keepOldAttribFiles);
/*
* Attrib caching
*/
#define BPC_FTYPE_FILE (0)
#define BPC_FTYPE_HARDLINK (1)
#define BPC_FTYPE_SYMLINK (2)
#define BPC_FTYPE_CHARDEV (3)
#define BPC_FTYPE_BLOCKDEV (4)
#define BPC_FTYPE_DIR (5)
#define BPC_FTYPE_FIFO (6)
#define BPC_FTYPE_SOCKET (8)
#define BPC_FTYPE_UNKNOWN (9)
#define BPC_FTYPE_DELETED (10)
#define BPC_FTYPE_INVALID (11)
typedef struct {
int num;
int compress;
int version;
} bpc_backup_info;
typedef struct {
int backupNum;
int compress;
int readOnly;
uint cacheLruCnt;
/*
* optional merging of backups to create view for restore
*/
bpc_backup_info *bkupMergeList;
int bkupMergeCnt;
/*
* Hash table of cached file attributes.
* Key is the mangled attrib path (excluding backupTopDir[], and including attrib file name).
* Value is a bpc_attrib_dir structure.
* - Keys of the bpc_attrib_dir hash table are the file names in that directory.
*/
bpc_hashtable attrHT;
/*
* Hash table of cached inode attributes.
* Key is the inode attribute path (excluding backupTopDir[]).
* Value is a bpc_attrib_dir structure.
* - Keys of the bpc_attrib_dir hash table are the inode numbers converted to ascii hex, lsb first.
*/
bpc_hashtable inodeHT;
/*
* Delta reference count for any changes as we write/change files or attributes
*/
bpc_deltaCount_info *deltaInfo;
bpc_strBuf *shareName;
bpc_strBuf *shareNameUM;
bpc_strBuf *hostName;
bpc_strBuf *backupTopDir;
bpc_strBuf *currentDir;
} bpc_attribCache_info;
typedef struct {
bpc_hashtable_key key;
int dirty;
/*
* We flag directories whose parents either don't exist or aren't directories.
* We ignore attributes on bad directories.
* Initially this flag is zero, meaning we don't know if this directory is ok.
* After we check, > 0 means parent does exist and is a directory ; < 0 means dir is bad
*/
int dirOk;
uint lruCnt;
bpc_attrib_dir dir;
} bpc_attribCache_dir;
void bpc_attribCache_init(bpc_attribCache_info *ac, char *host, int backupNum, char *shareNameUM, int compress);
void bpc_attribCache_setDeltaInfo(bpc_attribCache_info *ac, bpc_deltaCount_info *deltaInfo);
void bpc_attribCache_setMergeList(bpc_attribCache_info *ac, bpc_backup_info *bkupList, int bkupCnt);
void bpc_attribCache_destroy(bpc_attribCache_info *ac);
int bpc_attribCache_readOnly(bpc_attribCache_info *ac, int readOnly);
void bpc_attribCache_setCurrentDirectory(bpc_attribCache_info *ac, char *dir);
bpc_attrib_file *bpc_attribCache_getFile(bpc_attribCache_info *ac, char *path, int allocate_if_missing, int dontReadInode);
int bpc_attribCache_setFile(bpc_attribCache_info *ac, char *path, bpc_attrib_file *file, int dontOverwriteInode);
int bpc_attribCache_deleteFile(bpc_attribCache_info *ac, char *path);
bpc_attrib_file *bpc_attribCache_getInode(bpc_attribCache_info *ac, ino_t inode, int allocate_if_missing);
int bpc_attribCache_setInode(bpc_attribCache_info *ac, ino_t inode, bpc_attrib_file *inodeSrc);
int bpc_attribCache_deleteInode(bpc_attribCache_info *ac, ino_t inode);
int bpc_attribCache_getDirEntryCnt(bpc_attribCache_info *ac, char *path);
ssize_t bpc_attribCache_getDirEntries(bpc_attribCache_info *ac, char *path, char *entries, ssize_t entrySize);
void bpc_attribCache_flush(bpc_attribCache_info *ac, int all, char *path);
void bpc_attribCache_getFullMangledPath(bpc_attribCache_info *ac, bpc_strBuf *path, char *dirName, int backupNum);
#endif
rsync-bpc-3.1.3.0/backuppc/bpc_attrib.c 0000664 0000000 0000000 00000151326 13737671777 0017662 0 ustar 00root root 0000000 0000000 /*
* Routines for read/writing/managing file attributes
*
* Copyright (C) 2013 Craig Barratt.
*
* 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 "backuppc.h"
/*
* Type of attribute file. This is saved as a magic number at the
* start of the file. This type is for V3 and earlier.
*/
#define BPC_ATTRIB_TYPE_UNIX (0x17555555)
/*
* super set of UNIX, including extended attribs and digest, for 4.x+
*/
#define BPC_ATTRIB_TYPE_XATTR (0x17565353)
/*
* starting in 4.x, attrib files in the pc backup tree are
* just digests that give the location of the real attrib file
* in the pool. attrib files written in the pc backup tree
* start with this magic number, followed by the digest.
*/
#define BPC_ATTRIB_TYPE_DIGEST (0x17585451)
static char *FileType2Text[] = {
"file",
"hardlink",
"symlink",
"chardev",
"blockdev",
"dir",
"fifo",
"?",
"socket",
"?",
"deleted",
};
/*
* Ensure by default we use old-style "attrib" files for <= 4.0.0alpha3 compatibility.
* Newer versions of BackupPC turn this off to use new attribute file naming.
*/
static int WriteOldStyleAttribFile = 1;
static int KeepOldAttribFiles = 1;
void bpc_attrib_backwardCompat(int writeOldStyleAttribFile, int keepOldAttribFiles)
{
if ( writeOldStyleAttribFile >= 0 ) WriteOldStyleAttribFile = writeOldStyleAttribFile;
if ( keepOldAttribFiles >= 0 ) KeepOldAttribFiles = keepOldAttribFiles;
if ( BPC_LogLevel >= 5 ) {
bpc_logMsgf("bpc_attrib_backwardCompat: WriteOldStyleAttribFile = %d, KeepOldAttribFiles = %d\n",
WriteOldStyleAttribFile, KeepOldAttribFiles);
}
}
#define CONV_BUF_TO_UINT32(buf) ((buf)[0] << 24 | (buf)[1] << 16 | (buf)[2] << 8 | (buf)[3])
#define CONV_UINT32_TO_BUF(buf, val) { *(buf)++ = ((val) >> 24) & 0xff; \
*(buf)++ = ((val) >> 16) & 0xff; \
*(buf)++ = ((val) >> 8) & 0xff; \
*(buf)++ = ((val) >> 0) & 0xff; }
/*
* Note on xattr keys: they are treated as opaque strings of bytes, and the convention
* is to include the '\0' byte termination in the keyLen (ie: it is strlen(key) + 1).
*/
bpc_attrib_xattr *bpc_attrib_xattrGet(bpc_attrib_file *file, void *key, int keyLen, int allocate_if_missing)
{
return (bpc_attrib_xattr*)bpc_hashtable_find(&file->xattrHT, key, keyLen, allocate_if_missing);
}
void bpc_attrib_xattrDestroy(bpc_attrib_xattr *xattr)
{
if ( xattr->key.key ) free(xattr->key.key);
if ( xattr->value ) free(xattr->value);
}
int bpc_attrib_xattrDelete(bpc_attrib_file *file, void *key, int keyLen)
{
bpc_attrib_xattr *xattr = bpc_hashtable_find(&file->xattrHT, key, keyLen, 0);
if ( !xattr ) return -1;
bpc_attrib_xattrDestroy(xattr);
bpc_hashtable_nodeDelete(&file->xattrHT, xattr);
return 0;
}
static void bpc_attrib_xattrDeleteNode(bpc_attrib_xattr *xattr, bpc_attrib_file *file)
{
bpc_attrib_xattrDestroy(xattr);
bpc_hashtable_nodeDelete(&file->xattrHT, xattr);
}
int bpc_attrib_xattrDeleteAll(bpc_attrib_file *file)
{
bpc_hashtable_iterate(&file->xattrHT, (void*)bpc_attrib_xattrDeleteNode, file);
return 0;
}
/*
* returns >0 if the new value is the same as the current value.
* returns 0 if the new value was set correctly
* returns <0 on error.
*/
int bpc_attrib_xattrSetValue(bpc_attrib_file *file, void *key, int keyLen, void *value, uint32 valueLen)
{
bpc_attrib_xattr *xattr;
if ( ((char*)key)[keyLen - 1] != 0x0 ) {
int ret;
bpc_strBuf *keyCopy = bpc_strBuf_new();
bpc_strBuf_resize(keyCopy, keyLen + 16);
memcpy(keyCopy->s, key, keyLen);
keyCopy->s[keyLen++] = 0x0;
if ( BPC_LogLevel >= 6 ) {
bpc_logMsgf("bpc_attrib_xattrSetValue: fixup: appended 0x0 to xattr name '%s' (keyLen now %u)\n", (char*)key, keyLen);
}
ret = bpc_attrib_xattrSetValue(file, keyCopy->s, keyLen, value, valueLen);
bpc_strBuf_free(keyCopy);
return ret;
}
xattr = bpc_attrib_xattrGet(file, key, keyLen, 1);
if ( !xattr->value ) {
/*
* new entry
*/
if ( !(xattr->key.key = malloc(keyLen)) ) {
bpc_logErrf("bpc_attrib_xattrSetValue: can't allocate %d bytes for key\n", keyLen);
return -1;
}
memcpy(xattr->key.key, key, keyLen);
xattr->key.keyLen = keyLen;
} else {
/*
* existing entry - no need to recopy key. If value array isn't big enough then create another.
*/
if ( valueLen > xattr->valueLen ) {
free(xattr->value);
xattr->value = NULL;
} else if ( valueLen == xattr->valueLen && !memcmp(xattr->value, value, valueLen) ) {
/*
* same value - no change
*/
return 1;
}
}
if ( !xattr->value && !(xattr->value = malloc(valueLen)) ) {
bpc_logErrf("bpc_attrib_xattrSetValue: can't allocate %d bytes for value\n", valueLen);
return -1;
}
memcpy(xattr->value, value, valueLen);
xattr->valueLen = valueLen;
return 0;
}
void bpc_attrib_xattrCopy(bpc_attrib_xattr *xattrSrc, bpc_attrib_file *fileDest)
{
bpc_attrib_xattr *xattr;
uchar *key = (uchar*)malloc(xattrSrc->key.keyLen > 0 ? xattrSrc->key.keyLen : 1);
uchar *value = (uchar*)malloc(xattrSrc->valueLen > 0 ? xattrSrc->valueLen : 1);
if ( !key || !value ) {
bpc_logErrf("bpc_attrib_xattrCopy: can't allocate %d,%d bytes\n", xattrSrc->key.keyLen + 1, xattrSrc->valueLen + 1);
return;
}
memcpy(key, xattrSrc->key.key, xattrSrc->key.keyLen);
memcpy(value, xattrSrc->value, xattrSrc->valueLen);
xattr = bpc_attrib_xattrGet(fileDest, key, xattrSrc->key.keyLen, 1);
if ( xattr->value ) {
/*
* Shouldn't be present, but if so clear it out and write the new key
*/
bpc_attrib_xattrDestroy(xattr);
xattr->key.key = key;
xattr->key.keyLen = xattrSrc->key.keyLen;
}
xattr->value = value;
xattr->valueLen = xattrSrc->valueLen;
}
int bpc_attrib_xattrCount(bpc_attrib_file *file)
{
return bpc_hashtable_entryCount(&file->xattrHT);
}
typedef struct {
char *list;
ssize_t idx;
ssize_t listLen;
int ignoreRsyncACLs;
} xattrList_info;
static void bpc_attrib_xattrListKey(bpc_attrib_xattr *xattr, xattrList_info *info)
{
if ( info->idx < 0 ) return;
if ( info->ignoreRsyncACLs ) {
static struct {
char *str;
unsigned int len;
} ignoreKeys[] = {
{ "user.rsync.%aacl", sizeof("user.rsync.%aacl"), }, /* note: sizeof() includes the \0 terminator */
{ "user.rsync.%dacl", sizeof("user.rsync.%dacl"), },
};
uint i;
for ( i = 0 ; i < sizeof(ignoreKeys) / sizeof(ignoreKeys[0]) ; i++ ) {
if ( xattr->key.keyLen == ignoreKeys[i].len
&& !memcmp(xattr->key.key, ignoreKeys[i].str, xattr->key.keyLen) ) {
return;
}
}
}
if ( info->list ) {
if ( info->idx + (signed)xattr->key.keyLen > info->listLen ) {
info->idx = -1;
return;
}
/*
* confirm that keyLen includes the \0 terminating byte
*/
memcpy(info->list + info->idx, xattr->key.key, xattr->key.keyLen);
if ( xattr->key.keyLen >= 1 && info->list[info->idx + xattr->key.keyLen - 1] != 0x0 ) {
info->list[info->idx + xattr->key.keyLen - 1] = 0x0;
bpc_logMsgf("bpc_attrib_xattrListKey: BOTCH: truncated xattr name '%s' to match keyLen %u\n", info->list + info->idx, xattr->key.keyLen);
}
if ( BPC_LogLevel >= 6 ) bpc_logMsgf("bpc_attrib_xattrListKey: adding %s\n", info->list + info->idx);
info->idx += xattr->key.keyLen;
} else {
info->idx += xattr->key.keyLen;
}
}
/*
* Concatenate all the xattr keys, (which the caller has ensured are \0 terminated),
* into a single string. Return the number of bytes in the output string.
* Returns -1 if listLen is too short to fit all the keys.
* If list is NULL, instead returns the number of bytes required to store all the keys.
*/
size_t bpc_attrib_xattrList(bpc_attrib_file *file, char *list, size_t listLen, int ignoreRsyncACLs)
{
xattrList_info info;
info.list = list;
info.idx = 0;
info.listLen = listLen;
info.ignoreRsyncACLs = ignoreRsyncACLs;
bpc_hashtable_iterate(&file->xattrHT, (void*)bpc_attrib_xattrListKey, &info);
return info.idx;
}
void bpc_attrib_fileDestroy(bpc_attrib_file *file)
{
if ( file->name) free(file->name);
bpc_hashtable_iterate(&file->xattrHT, (void*)bpc_attrib_xattrDestroy, NULL);
bpc_hashtable_destroy(&file->xattrHT);
}
/*
* Return the attributes for the given file.
* If allocate_if_missing == 0 and not present, then NULL is returned.
* If allocate_if_missing != 0 and not present, then an empty struct is returned with the key filled in,
* and file->name is NULL.
*/
bpc_attrib_file *bpc_attrib_fileGet(bpc_attrib_dir *dir, char *fileName, int allocate_if_missing)
{
return bpc_hashtable_find(&dir->filesHT, (uchar*)fileName, strlen(fileName), allocate_if_missing);
}
/*
* Initialize an empty file structure (ie: one returned by bpc_attrib_fileGet() that is empty)
*/
void bpc_attrib_fileInit(bpc_attrib_file *file, char *fileName, int xattrNumEntries)
{
int fileNameLen = strlen(fileName);
if ( file->name ) bpc_attrib_fileDestroy(file);
file->name = (char*)malloc(fileNameLen + 1);
if ( !file->name ) {
bpc_logErrf("bpc_attrib_fileInit: can't allocate %d bytes for file name\n", fileNameLen + 1);
return;
}
memcpy(file->name, fileName, fileNameLen + 1);
file->isTemp = 0;
file->key.key = file->name;
bpc_hashtable_create(&file->xattrHT, 16 + xattrNumEntries, sizeof(bpc_attrib_xattr));
}
/*
* Copy all the attributes from fileSrc to fileDest. fileDest should already have a
* valid allocated fileName and allocated xattr hash. The fileDest xattr hash is
* emptied before the copy, meaning it is over written.
*
* If overwriteEmptyDigest == 0, an empty digest in fileSrc will not overwrite fileDest.
*/
void bpc_attrib_fileCopyOpt(bpc_attrib_file *fileDest, bpc_attrib_file *fileSrc, int overwriteEmptyDigest)
{
if ( fileDest == fileSrc ) return;
fileDest->type = fileSrc->type;
fileDest->compress = fileSrc->compress;
fileDest->mode = fileSrc->mode;
fileDest->isTemp = fileSrc->isTemp;
fileDest->uid = fileSrc->uid;
fileDest->gid = fileSrc->gid;
fileDest->nlinks = fileSrc->nlinks;
fileDest->mtime = fileSrc->mtime;
fileDest->size = fileSrc->size;
fileDest->inode = fileSrc->inode;
fileDest->backupNum = fileSrc->backupNum;
if ( fileSrc->digest.len > 0 || overwriteEmptyDigest ) {
fileDest->digest = fileSrc->digest;
}
bpc_hashtable_iterate(&fileDest->xattrHT, (void*)bpc_attrib_xattrDestroy, NULL);
bpc_hashtable_erase(&fileDest->xattrHT);
bpc_hashtable_iterate(&fileSrc->xattrHT, (void*)bpc_attrib_xattrCopy, fileDest);
}
/*
* Copy all the attributes from fileSrc to fileDest. fileDest should already have a
* valid allocated fileName and allocated xattr hash. The fileDest xattr hash is
* emptied before the copy, meaning it is over written.
*/
void bpc_attrib_fileCopy(bpc_attrib_file *fileDest, bpc_attrib_file *fileSrc)
{
if ( fileDest == fileSrc ) return;
bpc_attrib_fileCopyOpt(fileDest, fileSrc, 1);
}
/*
* Check if two file attribute structures are the same. Returns 0 if they are the same.
*/
int bpc_attrib_fileCompare(bpc_attrib_file *file0, bpc_attrib_file *file1)
{
uint idx = 0;
if ( file0->type != file1->type
|| file0->compress != file1->compress
|| file0->mode != file1->mode
|| file0->uid != file1->uid
|| file0->gid != file1->gid
|| file0->nlinks != file1->nlinks
|| file0->mtime != file1->mtime
|| file0->size != file1->size
|| file0->inode != file1->inode
|| file0->digest.len != file1->digest.len
|| memcmp(file0->digest.digest, file1->digest.digest, file0->digest.len)
|| bpc_attrib_xattrCount(file0) != bpc_attrib_xattrCount(file1) ) {
if ( BPC_LogLevel >= 9 ) bpc_logMsgf("bpc_attrib_fileCompare: %s %s differ\n", file0->name, file1->name);
return 1;
}
while ( 1 ) {
bpc_attrib_xattr *xattr0 = bpc_hashtable_nextEntry(&file0->xattrHT, &idx), *xattr1;
if ( !xattr0 ) return 0;
if ( !(xattr1 = bpc_attrib_xattrGet(file1, xattr0->key.key, xattr0->key.keyLen, 0)) ) return 1;
if ( xattr0->valueLen != xattr1->valueLen || memcmp(xattr0->value, xattr1->value, xattr0->valueLen) ) return 1;
}
}
void bpc_attrib_fileDeleteName(bpc_attrib_dir *dir, char *fileName)
{
bpc_attrib_file *file = bpc_hashtable_find(&dir->filesHT, (uchar*)fileName, strlen(fileName), 0);
if ( !file ) return;
bpc_attrib_fileDestroy(file);
bpc_hashtable_nodeDelete(&dir->filesHT, file);
}
int bpc_attrib_fileIterate(bpc_attrib_dir *dir, bpc_attrib_file **file, uint *idx)
{
*file = bpc_hashtable_nextEntry(&dir->filesHT, idx);
if ( !*file ) return -1;
return 0;
}
int bpc_attrib_fileCount(bpc_attrib_dir *dir)
{
return bpc_hashtable_entryCount(&dir->filesHT);
}
char *bpc_attrib_fileType2Text(int type)
{
if ( type < 0 || type >= (int)(sizeof(FileType2Text) / sizeof(FileType2Text[0])) ) return "?";
return FileType2Text[type];
}
void bpc_attrib_dirInit(bpc_attrib_dir *dir, int compressLevel)
{
dir->digest.len = 0;
dir->compress = compressLevel;
dir->needRewrite = 0;
bpc_hashtable_create(&dir->filesHT, 512, sizeof(bpc_attrib_file));
}
void bpc_attrib_dirDestroy(bpc_attrib_dir *dir)
{
bpc_hashtable_iterate(&dir->filesHT, (void*)bpc_attrib_fileDestroy, NULL);
bpc_hashtable_destroy(&dir->filesHT);
}
int bpc_attrib_dirNeedRewrite(bpc_attrib_dir *dir)
{
return dir->needRewrite;
}
typedef struct {
bpc_deltaCount_info *deltaInfo;
int incr;
unsigned int *inodeMax;
} fileRefCnt_info;
static void bpc_attrib_fileRefCount(bpc_attrib_file *file, fileRefCnt_info *info)
{
if ( file->digest.len > 0 ) {
char hexStr[BPC_DIGEST_LEN_MAX * 2 + 1];
bpc_digest_digest2str(&file->digest, hexStr);
if ( BPC_LogLevel >= 7 ) bpc_logMsgf("bpc_attrib_fileRefCount: file %s digest %s delta %d\n", file->name, hexStr, info->incr);
bpc_poolRefDeltaUpdate(info->deltaInfo, file->compress, &file->digest, info->incr);
}
if ( info->inodeMax && file->inode > *info->inodeMax ) {
*info->inodeMax = file->inode;
}
}
/*
* call refDeltaUpdate with incr (typically +/-1) for every entry in the directory,
* as well as the dir itself.
*/
void bpc_attrib_dirRefCountInodeMax(bpc_deltaCount_info *deltaInfo, bpc_attrib_dir *dir, int incr, unsigned int *inodeMax)
{
fileRefCnt_info info;
info.deltaInfo = deltaInfo;
info.incr = incr;
info.inodeMax = inodeMax;
bpc_hashtable_iterate(&dir->filesHT, (void*)bpc_attrib_fileRefCount, &info);
if ( dir->digest.len > 0 ) {
char hexStr[BPC_DIGEST_LEN_MAX * 2 + 1];
bpc_digest_digest2str(&dir->digest, hexStr);
if ( BPC_LogLevel >= 7 ) bpc_logMsgf("bpc_attrib_dirRefCount: attrib digest %s delta = %d\n", hexStr, incr);
bpc_poolRefDeltaUpdate(deltaInfo, dir->compress, &dir->digest, incr);
} else {
if ( BPC_LogLevel >= 7 ) bpc_logMsgf("bpc_attrib_dirRefCount: no attrib digest -> no delta\n");
}
}
/*
* call refDeltaUpdate with incr (typically +/-1) for every entry in the directory,
* as well as the dir itself.
*/
void bpc_attrib_dirRefCount(bpc_deltaCount_info *deltaInfo, bpc_attrib_dir *dir, int incr)
{
bpc_attrib_dirRefCountInodeMax(deltaInfo, dir, incr, NULL);
}
typedef struct {
char *entries;
ssize_t entryIdx;
ssize_t entrySize;
} dirEntry_info;
static void bpc_attrib_getDirEntry(bpc_attrib_file *file, dirEntry_info *info)
{
ssize_t len = strlen(file->name) + 1;
if ( info->entryIdx < 0 ) return;
if ( info->entries ) {
if ( info->entryIdx + len > info->entrySize ) {
info->entryIdx = -1;
return;
}
memcpy(info->entries + info->entryIdx, file->name, len);
}
info->entryIdx += len;
}
ssize_t bpc_attrib_getEntries(bpc_attrib_dir *dir, char *entries, ssize_t entrySize)
{
dirEntry_info info;
info.entries = entries;
info.entryIdx = 0;
info.entrySize = entrySize;
bpc_hashtable_iterate(&dir->filesHT, (void*)bpc_attrib_getDirEntry, &info);
return info.entryIdx;
}
void bpc_attrib_attribFilePath(bpc_strBuf *path, char *dir, char *attribFileName)
{
if ( !dir ) {
bpc_strBuf_snprintf(path, 0, "%s", attribFileName);
} else {
bpc_strBuf_snprintf(path, 0, "%s/%s", dir, attribFileName ? attribFileName : "attrib");
}
}
bpc_digest *bpc_attrib_dirDigestGet(bpc_attrib_dir *dir)
{
return &dir->digest;
}
static int read_more_data(bpc_fileZIO_fd *fd, uchar *buf, size_t bufSize, size_t *nRead, uchar **bufPP, char *attribPath)
{
int thisRead;
/*
* move the remaining part of the buffer down, and read more data
*/
*nRead = (buf + *nRead) - *bufPP;
memmove(buf, *bufPP, *nRead);
*bufPP = buf;
thisRead = bpc_fileZIO_read(fd, buf + *nRead, bufSize - *nRead);
if ( thisRead < 0 ) {
bpc_logErrf("bpc_attrib_dirRead: can't read more bytes from %s\n", attribPath);
return -1;
}
*nRead += thisRead;
return 0;
}
/*
* Read variable-length unsigned integer in 7 bit chunks, LSB first.
*/
static int64 getVarInt(uchar **bufPP, uchar *bufEnd)
{
int64 result = 0;
uchar *bufP = *bufPP;
int i = 0;
while ( bufP < bufEnd ) {
uchar c = *bufP++;
result |= ((int64)(c & 0x7f)) << i;
if ( !(c & 0x80) ) {
*bufPP = bufP;
return result;
}
i += 7;
}
/*
* we ran out of data... make sure bufP is greater than bufEnd, since
* returning it to be equal (ie: bufP) will be incorrectly interpreted as
* meaning the integer correctly ended right at the end of the buffer.
*/
*bufPP = bufEnd + 1;
return result;
}
/*
* V3 variable length integer read, MSB first, which is compatible with perl pack("w")
*/
static int64 getVarInt_v3(uchar **bufPP, uchar *bufEnd)
{
int64 result = 0;
uchar *bufP = *bufPP;
while ( bufP < bufEnd ) {
uchar c = *bufP++;
result = (result << 7) | (c & 0x7f);
if ( !(c & 0x80) ) {
*bufPP = bufP;
return result;
}
}
/*
* we ran out of data... make sure bufP is greater than bufEnd, since
* returning it to be equal (ie: bufP) will be incorrectly interpreted as
* meaning the integer correctly ended right at the end of the buffer.
*/
*bufPP = bufEnd + 1;
return result;
}
/*
* Write variable-length unsigned integer in 7 bit chunks, LSB first
*/
static void setVarInt(uchar **bufPP, uchar *bufEnd, int64 value)
{
uchar *bufP = *bufPP;
int maxBytes = (sizeof(value) * 8 + 6) / 7;
do {
uchar c = value & 0x7f;
value >>= 7;
maxBytes--;
if ( value && maxBytes > 0 ) c |= 0x80;
if ( bufP < bufEnd ) {
*bufP++ = c;
} else {
bufP++;
}
} while ( value && maxBytes > 0 );
*bufPP = bufP;
}
/*
* Unpack the data in buf[] into the file structure, after the file name and xattr entry
* count have been extracted. Returns next unused buffer location.
*
* If there isn't enough data to extract a complete file structure, the return value
* will be greater than bufEnd. You should gather more data and re-call the function.
*/
uchar *bpc_attrib_buf2file(bpc_attrib_file *file, uchar *buf, uchar *bufEnd, int xattrNumEntries, int *xattrFixup)
{
uchar *bufP = buf;
int i;
file->type = getVarInt(&bufP, bufEnd);
file->mtime = getVarInt(&bufP, bufEnd);
file->mode = getVarInt(&bufP, bufEnd);
file->uid = getVarInt(&bufP, bufEnd);
file->gid = getVarInt(&bufP, bufEnd);
file->size = getVarInt(&bufP, bufEnd);
file->inode = getVarInt(&bufP, bufEnd);
file->compress = getVarInt(&bufP, bufEnd);
file->nlinks = getVarInt(&bufP, bufEnd);
file->digest.len = getVarInt(&bufP, bufEnd);
file->isTemp = 0;
if ( file->digest.len > 0 && bufP + file->digest.len <= bufEnd ) {
memcpy(file->digest.digest, bufP, file->digest.len);
}
bufP += file->digest.len;
for ( i = 0 ; i < xattrNumEntries ; i++ ) {
uint keyLen = getVarInt(&bufP, bufEnd);
uint valueLen = getVarInt(&bufP, bufEnd);
if ( bufP + keyLen + valueLen <= bufEnd ) {
if ( xattrFixup && bufP[keyLen - 1] != 0x0 ) {
*xattrFixup = 1;
}
bpc_attrib_xattrSetValue(file, bufP, keyLen, bufP + keyLen, valueLen);
}
bufP += keyLen + valueLen;
}
return bufP;
}
/*
* Extract an entire packed file structure, starting with the fileName length varint.
* Returns next unused buffer location. It is assumed the file structure is already
* initialized and has a valid fileName allocated, so we don't allocate it here.
*
* If there isn't enough data to extract a complete file structure, the return value
* will be greater than bufEnd. You should gather more data and re-call the function.
* On certain errors, returns NULL;
*/
uchar *bpc_attrib_buf2fileFull(bpc_attrib_file *file, uchar *bufP, uchar *bufEnd)
{
uint fileNameLen, xattrNumEntries;
fileNameLen = getVarInt(&bufP, bufEnd);
if ( fileNameLen > BPC_MAXPATHLEN - 1 ) {
bpc_logErrf("bpc_attrib_buf2fileFull: got unreasonable file name length %d\n", fileNameLen);
return NULL;
}
bufP += fileNameLen;
bpc_attrib_xattrDeleteAll(file);
xattrNumEntries = getVarInt(&bufP, bufEnd);
if ( BPC_LogLevel >= 6 ) bpc_logMsgf("bpc_attrib_buf2fileFull: xattrNumEntries = %d\n", xattrNumEntries);
bufP = bpc_attrib_buf2file(file, bufP, bufEnd, xattrNumEntries, NULL);
return bufP;
}
/*
* Read the attribute file at dirPath/attribFilePath and populate dir
*/
int bpc_attrib_dirRead(bpc_attrib_dir *dir, char *dirPath, char *attribFilePath, int backupNum)
{
bpc_strBuf *attribPath = bpc_strBuf_new();
bpc_fileZIO_fd fd;
size_t nRead;
uint32 magic = 0;
uchar buf[8 * 65536], *bufP;
STRUCT_STAT st;
char *p, *attribFileName;
bpc_attrib_attribFilePath(attribPath, dirPath, attribFilePath);
dir->digest.len = 0;
/*
* attribFileName points to the last portion of attribFilePath, or the whole
* string if it doesn't contain '/'
*/
if ( (attribFileName = strrchr(attribFilePath, '/')) ) {
attribFileName++;
} else {
attribFileName = attribFilePath;
}
if ( BPC_LogLevel >= 6 ) bpc_logMsgf("bpc_attrib_dirRead(%s); dirPath = %s, attribFilePath = %s, attribFileName = %s\n",
attribPath->s, dirPath, attribFilePath, attribFileName);
if ( (p = strchr(attribFileName, '_')) && !stat(attribPath->s, &st) && S_ISREG(st.st_mode) ) {
/*
* Explicit path name to new-style attrib file, and it exists; extract digest
*/
if ( !strcmp(p + 1, "0") ) {
bpc_strBuf_free(attribPath);
return 0;
}
bpc_digest_str2digest(&dir->digest, p + 1);
if ( BPC_LogLevel >= 6 ) {
char str[256];
bpc_digest_digest2str(&dir->digest, str);
bpc_logMsgf("bpc_attrib_dirRead: called with attrib file %s: digest = %s, len = %d\n",
attribPath->s, str, dir->digest.len);
}
/*
* Write new type attrib files (since we found a new-style one)
*/
WriteOldStyleAttribFile = 0;
magic = BPC_ATTRIB_TYPE_XATTR;
} else if ( stat(attribPath->s, &st) || !S_ISREG(st.st_mode) || strchr(attribFileName, '_') ) {
DIR *dirOs;
struct dirent *dp;
int attribFileNameLen = strlen(attribFileName);
bpc_strBuf *attribDirPath = bpc_strBuf_new();
/*
* Starting in 0.50, the attrib files are zero length with the digest encoded in
* the file name, so there is no file just called "attrib". Look in the directory
* to find it.
*/
bpc_strBuf_strcpy(attribDirPath, 0, attribPath->s);
if ( (p = strrchr(attribDirPath->s, '/')) ) {
*p = '\0';
} else {
bpc_strBuf_strcpy(attribDirPath, 0, ".");
}
if ( !(dirOs = opendir(attribDirPath->s)) ) {
/*
* This is a benign error - just return as though there is an empty attrib file
*/
if ( BPC_LogLevel >= 8 ) bpc_logMsgf("bpc_attrib_dirRead: can't opendir %s (note: this is ok)\n", attribDirPath->s);
bpc_strBuf_free(attribPath);
bpc_strBuf_free(attribDirPath);
return 0;
}
bpc_strBuf_free(attribDirPath);
while ( (dp = readdir(dirOs)) ) {
if ( strncmp(dp->d_name, attribFileName, attribFileNameLen) ) continue;
p = dp->d_name + attribFileNameLen;
if ( p[0] != '_' ) continue;
p++;
if ( !strcmp(p, "0") ) {
/*
* An empty attrib file is legit; just return with no entries
*/
if ( BPC_LogLevel >= 6 ) {
bpc_logMsgf("bpc_attrib_dirRead: Got empty attrib file %s\n", dp->d_name);
}
closedir(dirOs);
bpc_strBuf_free(attribPath);
return 0;
}
bpc_digest_str2digest(&dir->digest, p);
if ( BPC_LogLevel >= 6 ) {
char str[256];
bpc_digest_digest2str(&dir->digest, str);
bpc_logMsgf("bpc_attrib_dirRead: Got attrib file %s: digest = %s, len = %d\n",
dp->d_name, str, dir->digest.len);
}
/*
* Write new type attrib files (since we found a new-style one)
*/
WriteOldStyleAttribFile = 0;
break;
}
closedir(dirOs);
if ( dir->digest.len == 0 ) {
bpc_strBuf_free(attribPath);
return 0;
}
magic = BPC_ATTRIB_TYPE_XATTR;
} else {
if ( bpc_fileZIO_open(&fd, attribPath->s, 0, dir->compress) ) {
bpc_logErrf("bpc_attrib_dirRead: can't open %s\n", attribPath->s);
bpc_strBuf_free(attribPath);
return -1;
}
nRead = bpc_fileZIO_read(&fd, buf, sizeof(buf));
if ( nRead == 0 ) {
/*
* an empty file is legit - this means an empty directory (ie: zero attrib entries).
* indicate this with an empty digest and empty hash of entries.
*/
bpc_fileZIO_close(&fd);
if ( !strcmp(attribFileName, "attrib") ) {
bpc_strBuf *attribPathTemp = bpc_strBuf_new();
bpc_strBuf_strcpy(attribPathTemp, 0, attribPath->s);
bpc_strBuf_strcat(attribPathTemp, 0, "_0");
if ( rename(attribPath->s, attribPathTemp->s) ) {
bpc_logErrf("bpc_attrib_dirRead: rename of empty attrib file from %s to %s failed\n", attribPath->s, attribPathTemp->s);
bpc_strBuf_free(attribPath);
bpc_strBuf_free(attribPathTemp);
return -1;
} else if ( BPC_LogLevel >= 6 ) {
bpc_logMsgf("bpc_attrib_dirRead: renamed empty attrib file %s -> %s\n", attribPath->s, attribPathTemp->s);
}
bpc_strBuf_free(attribPathTemp);
}
bpc_strBuf_free(attribPath);
return 0;
}
if ( nRead < 4 ) {
bpc_logErrf("bpc_attrib_dirRead: can't read at least 4 bytes from %s\n", attribPath->s);
bpc_fileZIO_close(&fd);
bpc_strBuf_free(attribPath);
return -1;
}
magic = CONV_BUF_TO_UINT32(buf);
}
if ( magic == BPC_ATTRIB_TYPE_DIGEST ) {
bpc_strBuf *attribPathNew = bpc_strBuf_new();
int fdNum;
size_t digestLen = nRead - 4, attribPathLen = strlen(attribPath->s);
if ( nRead < 20 ) {
bpc_logErrf("bpc_attrib_dirRead: can't read at least 20 bytes from %s\n", attribPath->s);
bpc_strBuf_free(attribPath);
bpc_strBuf_free(attribPathNew);
return -1;
}
bpc_fileZIO_close(&fd);
if ( digestLen > sizeof(dir->digest.digest) ) digestLen = sizeof(dir->digest.digest);
memcpy(dir->digest.digest, buf + 4, digestLen);
dir->digest.len = digestLen;
if ( !KeepOldAttribFiles ) {
/*
* replace the attrib file with a new-style attrib file where the digest is encoded
* in a zero length file name
*/
bpc_strBuf_strcpy(attribPathNew, 0, attribPath->s);
bpc_strBuf_resize(attribPathNew, attribPathLen + 1 + 2 * dir->digest.len + 1 + 16);
attribPathNew->s[attribPathLen++] = '_';
bpc_digest_digest2str(&dir->digest, attribPathNew->s + attribPathLen);
if ( (fdNum = open(attribPathNew->s, O_WRONLY | O_CREAT | O_TRUNC, 0660)) < 0 ) {
bpc_logErrf("bpc_attrib_dirRead: can't open/create empty attrib file %s\n", attribPathNew->s);
bpc_strBuf_free(attribPath);
bpc_strBuf_free(attribPathNew);
return -1;
}
close(fdNum);
unlink(attribPath->s);
if ( BPC_LogLevel >= 4 ) bpc_logMsgf("bpc_attrib_dirRead: replaced %s with %s\n",
attribPath->s, attribPathNew->s);
}
bpc_strBuf_free(attribPathNew);
}
if ( dir->digest.len > 0 ) {
/*
* Handle V4+ case - open the pool file directly
* For V3, digest.len == 0 since we opened the attrib file above (it is stored hardlinked in the backup
* directory; there is no digest)
*/
bpc_digest_md52path(attribPath, dir->compress, &dir->digest);
if ( bpc_fileZIO_open(&fd, attribPath->s, 0, dir->compress) ) {
bpc_logErrf("bpc_attrib_dirRead: can't open %s\n", attribPath->s);
bpc_strBuf_free(attribPath);
return -1;
}
nRead = bpc_fileZIO_read(&fd, buf, sizeof(buf));
if ( nRead < 4 ) {
bpc_logErrf("bpc_attrib_dirRead: can't read at least 4 bytes from %s\n", attribPath->s);
bpc_fileZIO_close(&fd);
bpc_strBuf_free(attribPath);
return -1;
}
magic = CONV_BUF_TO_UINT32(buf);
}
bufP = buf + 4;
if ( magic == BPC_ATTRIB_TYPE_XATTR ) {
int retry = 0;
while ( bufP < buf + nRead ) {
uint fileNameLen, xattrNumEntries;
char *fileName;
bpc_attrib_file *file;
uchar *bufPsave = bufP;
int xattrFixup = 0;
if ( nRead == sizeof(buf) && bufP > buf + nRead - 2 * BPC_MAXPATHLEN
&& read_more_data(&fd, buf, sizeof(buf), &nRead, &bufP, attribPath->s) ) {
bpc_fileZIO_close(&fd);
bpc_strBuf_free(attribPath);
return -1;
}
fileNameLen = getVarInt(&bufP, buf + nRead);
if ( fileNameLen > BPC_MAXPATHLEN - 1 ) {
bpc_logErrf("bpc_attrib_dirRead: got unreasonable file name length %d\n", fileNameLen);
bpc_fileZIO_close(&fd);
bpc_strBuf_free(attribPath);
return -1;
}
/*
* Save the fileName, but it's not NULL terminated yet.
* After we consume the next varint, we can safely NULL-terminate
* the fileName, which allows us to look up or create the file entry.
*/
fileName = (char*)bufP;
bufP += fileNameLen;
xattrNumEntries = getVarInt(&bufP, buf + nRead);
fileName[fileNameLen] = '\0';
file = bpc_attrib_fileGet(dir, fileName, 1);
bpc_attrib_fileInit(file, fileName, xattrNumEntries);
file->backupNum = backupNum;
bufP = bpc_attrib_buf2file(file, bufP, buf + nRead, xattrNumEntries, &xattrFixup);
dir->needRewrite |= xattrFixup;
if ( bufP > buf + nRead ) {
/*
* Need to get more data and try again. We have allocated file->name,
* and perhaps partially filled the xattr structure, which will be ok
* on the retry since the same structure will be used.
*/
if ( retry ) {
bpc_logErrf("bpc_attrib_dirRead: BOTCH: couldn't complete file conversion on retry (%ld,%ld,%ld)\n",
bufP - buf, bufPsave - buf, nRead);
bpc_fileZIO_close(&fd);
bpc_strBuf_free(attribPath);
return -1;
}
if ( BPC_LogLevel >= 7 ) bpc_logMsgf("bpc_attrib_dirRead: retrying file conversion\n");
bufP = bufPsave;
if ( read_more_data(&fd, buf, sizeof(buf), &nRead, &bufP, attribPath->s) ) {
bpc_fileZIO_close(&fd);
bpc_strBuf_free(attribPath);
return -1;
}
retry = 1;
} else {
retry = 0;
}
if ( !retry && BPC_LogLevel >= 8 ) bpc_logMsgf("bpc_attrib_dirRead(%s): Got file %s: type = %d, mode = 0%o, uid/gid = %d/%d, size = %d\n",
attribPath->s, file->name, file->type, file->mode, file->uid, file->gid, file->size);
}
} else if ( magic == BPC_ATTRIB_TYPE_UNIX ) {
while ( bufP < buf + nRead ) {
uint fileNameLen;
char *fileName;
bpc_attrib_file *file;
int64 sizeDiv4GB;
uint type;
if ( nRead == sizeof(buf) && bufP > buf + nRead - 2 * BPC_MAXPATHLEN
&& read_more_data(&fd, buf, sizeof(buf), &nRead, &bufP, attribPath->s) ) {
bpc_fileZIO_close(&fd);
bpc_strBuf_free(attribPath);
return -1;
}
fileNameLen = getVarInt_v3(&bufP, buf + nRead);
if ( fileNameLen > 2 * BPC_MAXPATHLEN - 16 ) {
bpc_logErrf("bpc_attrib_dirRead: got unreasonable file name length %d\n", fileNameLen);
bpc_fileZIO_close(&fd);
bpc_strBuf_free(attribPath);
return -1;
}
/*
* Save the fileName, but it's not NULL terminated yet.
* After we get the next data, we can safely NULL-terminate the fileName.
*/
fileName = (char*)bufP;
bufP += fileNameLen;
type = getVarInt_v3(&bufP, buf + nRead);
fileName[fileNameLen] = '\0';
file = bpc_attrib_fileGet(dir, fileName, 1);
bpc_attrib_fileInit(file, fileName, 0);
file->type = type;
file->mode = getVarInt_v3(&bufP, buf + nRead);
file->uid = getVarInt_v3(&bufP, buf + nRead);
file->gid = getVarInt_v3(&bufP, buf + nRead);
sizeDiv4GB = getVarInt_v3(&bufP, buf + nRead);
file->size = (sizeDiv4GB << 32) + getVarInt_v3(&bufP, buf + nRead);
file->mtime = CONV_BUF_TO_UINT32(bufP); bufP += 4;
file->compress = dir->compress;
file->backupNum = backupNum;
if ( BPC_LogLevel >= 8 ) bpc_logMsgf("bpc_attrib_dirRead(%s): Got v3 file %s: type = %d, mode = 0%o, uid/gid = %d/%d, size = %d\n",
attribPath->s, file->name, file->type, file->mode, file->uid, file->gid, file->size);
}
} else {
bpc_logErrf("Unexpected magic number 0x%x read from %s\n", magic, attribPath->s);
bpc_strBuf_free(attribPath);
return -1;
}
/* TODO: make sure we are at EOF? */
bpc_fileZIO_close(&fd);
bpc_strBuf_free(attribPath);
return 0;
}
typedef struct {
uchar *bufP;
uchar *bufEnd;
uint numEntries;
} buf_info;
typedef struct {
bpc_poolWrite_info fd;
uchar buf[4 * 65536];
uchar *bufP;
} write_info;
static void write_file_flush(write_info *info)
{
if ( info->bufP > info->buf ) {
if ( BPC_LogLevel >= 7 ) bpc_logMsgf("write_file_flush: writing %lu bytes to pool\n", (unsigned long)(info->bufP - info->buf));
bpc_poolWrite_write(&info->fd, info->buf, info->bufP - info->buf);
}
info->bufP = info->buf;
}
static void bpc_attrib_xattrWrite(bpc_attrib_xattr *xattr, buf_info *info)
{
setVarInt(&info->bufP, info->bufEnd, xattr->key.keyLen);
setVarInt(&info->bufP, info->bufEnd, xattr->valueLen);
if ( xattr->key.keyLen >= 1 && info->bufP + xattr->key.keyLen <= info->bufEnd ) {
memcpy(info->bufP, xattr->key.key, xattr->key.keyLen);
if ( info->bufP[xattr->key.keyLen - 1] != 0x0 ) {
info->bufP[xattr->key.keyLen - 1] = 0x0;
bpc_logMsgf("bpc_attrib_xattrWrite: BOTCH: truncated xattr name '%s' to match keyLen %u\n", info->bufP, xattr->key.keyLen);
}
}
info->bufP += xattr->key.keyLen;
if ( info->bufP + xattr->valueLen <= info->bufEnd ) {
memcpy(info->bufP, xattr->value, xattr->valueLen);
}
info->bufP += xattr->valueLen;
info->numEntries++;
}
/*
* Write a file structure to the memory buffer. Returns the next unused buffer
* pointer. If the buffer is exhausted, no data is written past the buffer end,
* Therefore, if the return value is greater than bufEnd, then the conversion
* failed to fit. The routine can be called again with at least (bufP - buf)
* bytes allocated.
*/
uchar *bpc_attrib_file2buf(bpc_attrib_file *file, uchar *buf, uchar *bufEnd)
{
uchar *bufP = buf;
size_t fileNameLen = strlen(file->name);
uint xattrEntryCnt = bpc_hashtable_entryCount(&file->xattrHT);
buf_info info;
setVarInt(&bufP, bufEnd, fileNameLen);
if ( bufP + fileNameLen < bufEnd ) {
memcpy(bufP, file->name, fileNameLen);
}
bufP += fileNameLen;
setVarInt(&bufP, bufEnd, xattrEntryCnt);
setVarInt(&bufP, bufEnd, file->type);
setVarInt(&bufP, bufEnd, file->mtime);
setVarInt(&bufP, bufEnd, file->mode);
setVarInt(&bufP, bufEnd, file->uid);
setVarInt(&bufP, bufEnd, file->gid);
setVarInt(&bufP, bufEnd, file->size);
setVarInt(&bufP, bufEnd, file->inode);
setVarInt(&bufP, bufEnd, file->compress);
setVarInt(&bufP, bufEnd, file->nlinks);
setVarInt(&bufP, bufEnd, file->digest.len);
if ( bufP + file->digest.len <= bufEnd ) {
memcpy(bufP, file->digest.digest, file->digest.len);
}
bufP += file->digest.len;
info.bufEnd = bufEnd;
info.bufP = bufP;
info.numEntries = 0;
bpc_hashtable_iterate(&file->xattrHT, (void*)bpc_attrib_xattrWrite, &info);
if ( info.numEntries != xattrEntryCnt ) {
bpc_logErrf("bpc_attrib_file2buf: BOTCH: wrote %u xattr entries vs %u; attrib file corrupted\n", info.numEntries, xattrEntryCnt);
}
return info.bufP;
}
static void bpc_attrib_fileWrite(bpc_attrib_file *file, write_info *info)
{
uchar *bufP;
if ( file->isTemp ) {
if ( BPC_LogLevel >= 6 ) bpc_logMsgf("Skipping temp file %s: type = %d, mode = 0%o, uid/gid = %lu/%lu, size = %lu, inode = %lu, nlinks = %d, digest = 0x%02x%02x%02x..., bufUsed = %lu\n",
file->name, file->type, file->mode,
(unsigned long)file->uid, (unsigned long)file->gid,
(unsigned long)file->size, (unsigned long)file->inode, file->nlinks,
file->digest.digest[0], file->digest.digest[1], file->digest.digest[2],
(unsigned long)(info->bufP - info->buf));
return;
}
bufP = bpc_attrib_file2buf(file, info->bufP, info->buf + sizeof(info->buf));
if ( BPC_LogLevel >= 6 ) bpc_logMsgf("Wrote file %s: type = %d, mode = 0%o, uid/gid = %lu/%lu, size = %lu, inode = %lu, nlinks = %d, digest = 0x%02x%02x%02x..., bufUsed = %lu\n",
file->name, file->type, file->mode,
(unsigned long)file->uid, (unsigned long)file->gid,
(unsigned long)file->size, (unsigned long)file->inode, file->nlinks,
file->digest.digest[0], file->digest.digest[1], file->digest.digest[2],
(unsigned long)(info->bufP - info->buf));
if ( bufP <= info->buf + sizeof(info->buf) ) {
/*
* it fit into the buffer
*/
info->bufP = bufP;
return;
}
/*
* we overflowed the buffer - flush and try again
*/
write_file_flush(info);
bufP = bpc_attrib_file2buf(file, info->bufP, info->buf + sizeof(info->buf));
if ( bufP <= info->buf + sizeof(info->buf) ) {
info->bufP = bufP;
return;
}
bpc_logErrf("bpc_attrib_fileWrite: BOTCH: can't fit file into buffer (%ld, %ld)\n", bufP - info->buf, sizeof(info->buf));
}
/*
* Pre 0.50 attribute writing. Writes a small file that contains the file hash of the attrib file
*/
static int bpc_attrib_dirWriteOld(bpc_deltaCount_info *deltaInfo, bpc_attrib_dir *dir,
char *dirPath, char *attribFileName, bpc_digest *oldDigest)
{
bpc_strBuf *attribPath = bpc_strBuf_new(), *attribPathTemp = bpc_strBuf_new();
bpc_fileZIO_fd fd;
bpc_digest digest;
int status;
OFF_T poolFileSize;
int errorCnt;
static write_info info;
char *p;
bpc_attrib_attribFilePath(attribPath, dirPath, attribFileName);
if ( BPC_LogLevel >= 6 ) bpc_logMsgf("bpc_attrib_dirWriteOld(%s)\n", attribPath->s);
bpc_strBuf_snprintf(attribPathTemp, 0, "%s.%d", attribPath->s, getpid());
if ( (p = strrchr(attribPathTemp->s, '/')) ) {
*p = '\0';
if ( bpc_path_create(attribPathTemp->s) ) {
bpc_strBuf_free(attribPath);
bpc_strBuf_free(attribPathTemp);
return -1;
}
*p = '/';
}
if ( bpc_hashtable_entryCount(&dir->filesHT) == 0 ) {
int fdNum;
/*
* Empty directory - we just generate an empty attrib file, which we don't pool
*/
if ( (fdNum = open(attribPathTemp->s, O_WRONLY | O_CREAT | O_TRUNC, 0660)) < 0 ) {
bpc_logErrf("bpc_attrib_dirWrite: can't open/create raw %s for writing\n", attribPathTemp->s);
bpc_strBuf_free(attribPath);
bpc_strBuf_free(attribPathTemp);
return -1;
}
close(fdNum);
if ( rename(attribPathTemp->s, attribPath->s) ) {
bpc_logErrf("bpc_attrib_dirWrite: rename from %s to %s failed\n", attribPathTemp->s, attribPath->s);
bpc_strBuf_free(attribPath);
bpc_strBuf_free(attribPathTemp);
return -1;
}
if ( oldDigest ) bpc_poolRefDeltaUpdate(deltaInfo, dir->compress, oldDigest, -1);
dir->digest.len = 0;
bpc_strBuf_free(attribPath);
bpc_strBuf_free(attribPathTemp);
return 0;
}
info.bufP = info.buf;
CONV_UINT32_TO_BUF(info.bufP, BPC_ATTRIB_TYPE_XATTR);
bpc_poolWrite_open(&info.fd, dir->compress, NULL);
bpc_hashtable_iterate(&dir->filesHT, (void*)bpc_attrib_fileWrite, &info);
write_file_flush(&info);
bpc_poolWrite_close(&info.fd, &status, &digest, &poolFileSize, &errorCnt);
if ( errorCnt ) {
bpc_strBuf_free(attribPath);
bpc_strBuf_free(attribPathTemp);
return -1;
}
/*
* Now write the small atttib file, which just contains a magic number and the digest
*/
if ( bpc_fileZIO_open(&fd, attribPathTemp->s, 1, dir->compress) ) {
bpc_logErrf("bpc_attrib_dirWrite: can't open/create %s for writing\n", attribPathTemp->s);
bpc_strBuf_free(attribPath);
bpc_strBuf_free(attribPathTemp);
return -1;
}
info.bufP = info.buf;
CONV_UINT32_TO_BUF(info.bufP, BPC_ATTRIB_TYPE_DIGEST);
if ( digest.len > 0 ) {
memcpy(info.bufP, digest.digest, digest.len);
info.bufP += digest.len;
}
if ( bpc_fileZIO_write(&fd, info.buf, info.bufP - info.buf) < 0 ) {
bpc_logErrf("bpc_attrib_dirWrite: can't write to %s\n", attribPathTemp->s);
bpc_fileZIO_close(&fd);
bpc_strBuf_free(attribPath);
bpc_strBuf_free(attribPathTemp);
return -1;
}
bpc_fileZIO_close(&fd);
if ( rename(attribPathTemp->s, attribPath->s) ) {
bpc_logErrf("bpc_attrib_dirWrite: rename from %s to %s failed\n", attribPathTemp->s, attribPath->s);
bpc_strBuf_free(attribPath);
bpc_strBuf_free(attribPathTemp);
return -1;
}
if ( BPC_LogLevel >= 8 ) bpc_logMsgf("bpc_attrib_dirWrite: new attrib digest = 0x%02x%02x%02x..., oldDigest = 0x%02x%02x...\n",
digest.digest[0], digest.digest[1], digest.digest[2],
oldDigest ? oldDigest->digest[0] : 0x0, oldDigest ? oldDigest->digest[1] : 0x0);
if ( oldDigest ) bpc_poolRefDeltaUpdate(deltaInfo, dir->compress, oldDigest, -1);
bpc_poolRefDeltaUpdate(deltaInfo, dir->compress, &digest, 1);
/*
* update with the new digest
*/
memcpy(&dir->digest, &digest, sizeof(digest));
bpc_strBuf_free(attribPath);
bpc_strBuf_free(attribPathTemp);
return 0;
}
int bpc_attrib_dirWrite(bpc_deltaCount_info *deltaInfo, bpc_attrib_dir *dir, char *dirPath, char *attribFileName, bpc_digest *oldDigest)
{
bpc_strBuf *attribPath, *attribPathTemp;
char *baseAttribFileName;
bpc_digest digest;
int status;
OFF_T poolFileSize;
int errorCnt;
static write_info info;
char *p;
int fdNum;
size_t attribPathLen, baseAttribFileNameLen;
int digestChanged;
if ( WriteOldStyleAttribFile ) return bpc_attrib_dirWriteOld(deltaInfo, dir, dirPath, attribFileName, oldDigest);
attribPath = bpc_strBuf_new();
attribPathTemp = bpc_strBuf_new();
/*
* baseAttribFileName points to the last portion of attribFileName, or the whole
* string if it doesn't contain '/'
*/
if ( (baseAttribFileName = strrchr(attribFileName, '/')) ) {
baseAttribFileName++;
} else {
baseAttribFileName = attribFileName;
}
baseAttribFileNameLen = strlen(baseAttribFileName);
bpc_attrib_attribFilePath(attribPath, dirPath, attribFileName);
if ( BPC_LogLevel >= 6 ) bpc_logMsgf("bpc_attrib_dirWrite(%s): dirPath = %s, attribFileName = %s, baseAttribFileName = %s\n",
attribPath->s, dirPath, attribFileName, baseAttribFileName);
bpc_strBuf_snprintf(attribPathTemp, 0, "%s.%d", attribPath->s, getpid());
if ( (p = strrchr(attribPathTemp->s, '/')) ) {
*p = '\0';
if ( bpc_path_create(attribPathTemp->s) ) {
bpc_strBuf_free(attribPath);
bpc_strBuf_free(attribPathTemp);
return -1;
}
*p = '/';
}
attribPathLen = strlen(attribPath->s);
if ( bpc_hashtable_entryCount(&dir->filesHT) > 0 ) {
/*
* Write the attribute file to the pool
*/
info.bufP = info.buf;
CONV_UINT32_TO_BUF(info.bufP, BPC_ATTRIB_TYPE_XATTR);
bpc_poolWrite_open(&info.fd, dir->compress, NULL);
bpc_hashtable_iterate(&dir->filesHT, (void*)bpc_attrib_fileWrite, &info);
write_file_flush(&info);
bpc_poolWrite_close(&info.fd, &status, &digest, &poolFileSize, &errorCnt);
if ( errorCnt ) {
bpc_strBuf_free(attribPath);
bpc_strBuf_free(attribPathTemp);
return -1;
}
/*
* Starting in 0.50, the attrib file is always empty (so it takes no extra blocks)
* and we simply include the digest in the file name by appending the hex digits.
*
* An empty attrib file is simply "attrib_0", and a legacy attrib file (pre <0.50)
* is "attrib".
*/
bpc_strBuf_resize(attribPath, attribPathLen + 1 + 2 * digest.len + 1 + 16);
attribPath->s[attribPathLen++] = '_';
bpc_digest_digest2str(&digest, attribPath->s + attribPathLen);
/*
* Now create an empty attrib file with the file name digest
*/
if ( (fdNum = open(attribPathTemp->s, O_WRONLY | O_CREAT | O_TRUNC, 0660)) < 0 ) {
bpc_logErrf("bpc_attrib_dirWrite: can't open/create raw %s for writing\n", attribPathTemp->s);
bpc_strBuf_free(attribPath);
bpc_strBuf_free(attribPathTemp);
return -1;
}
close(fdNum);
if ( rename(attribPathTemp->s, attribPath->s) ) {
bpc_logErrf("bpc_attrib_dirWrite: rename from %s to %s failed\n", attribPathTemp->s, attribPath->s);
bpc_strBuf_free(attribPath);
bpc_strBuf_free(attribPathTemp);
return -1;
}
if ( BPC_LogLevel >= 5 ) bpc_logMsgf("bpc_attrib_dirWrite: created new attrib file %s\n", attribPath->s);
} else {
bpc_strBuf_resize(attribPathTemp, attribPathLen + 16);
memset(&digest, 0, sizeof(digest));
attribPath->s[attribPathLen++] = '_';
strcpy(attribPath->s + attribPathLen, "0");
if ( BPC_LogLevel >= 5 ) bpc_logMsgf("bpc_attrib_dirWrite: skipping creating new empty attrib file %s\n", attribPath->s);
unlink(attribPath->s);
}
if ( BPC_LogLevel >= 8 ) bpc_logMsgf("bpc_attrib_dirWrite: new attrib digest = 0x%02x%02x%02x..., oldDigest = 0x%02x%02x...\n",
digest.digest[0], digest.digest[1], digest.digest[2],
oldDigest ? oldDigest->digest[0] : 0x0, oldDigest ? oldDigest->digest[1] : 0x0);
digestChanged = !oldDigest || bpc_digest_compare(&digest, oldDigest);
if ( digestChanged && digest.len > 0 ) {
bpc_poolRefDeltaUpdate(deltaInfo, dir->compress, &digest, 1);
}
if ( oldDigest ) {
if ( !digestChanged ) {
if ( BPC_LogLevel >= 4 ) bpc_logMsgf("bpc_attrib_dirWrite: old attrib has same digest; no changes to ref counts\n");
bpc_strBuf_free(attribPath);
bpc_strBuf_free(attribPathTemp);
return 0;
}
bpc_strBuf_strcpy(attribPathTemp, 0, attribPath->s);
if ( oldDigest->len > 0 ) {
bpc_poolRefDeltaUpdate(deltaInfo, dir->compress, oldDigest, -1);
bpc_strBuf_resize(attribPathTemp, attribPathLen + 1 + 2 * oldDigest->len + 1 + 16);
bpc_digest_digest2str(oldDigest, attribPathTemp->s + attribPathLen);
} else {
bpc_strBuf_resize(attribPathTemp, attribPathLen + 16);
strcpy(attribPathTemp->s + attribPathLen, "0");
}
if ( !unlink(attribPathTemp->s) ) {
if ( BPC_LogLevel >= 5 ) bpc_logMsgf("bpc_attrib_dirWrite: removed old attrib file %s\n", attribPathTemp->s);
} else {
DIR *dirOs;
struct dirent *dp;
bpc_strBuf *deletePath;
/*
* Scan the directory and remove any other attribute files that have the
* same root.
*/
if ( !(p = strrchr(attribPath->s, '/')) ) {
bpc_logErrf("bpc_attrib_dirWrite: can't find a '/' in %s\n", attribPath->s);
bpc_strBuf_free(attribPath);
bpc_strBuf_free(attribPathTemp);
return -1;
}
*p++ = '\0';
if ( !(dirOs = opendir(attribPath->s)) ) {
bpc_logErrf("bpc_attrib_dirWrite: can't opendir %s\n", attribPath->s);
bpc_strBuf_free(attribPath);
bpc_strBuf_free(attribPathTemp);
return -1;
}
deletePath = bpc_strBuf_new();
while ( (dp = readdir(dirOs)) ) {
if ( strncmp(dp->d_name, baseAttribFileName, baseAttribFileNameLen) || !strcmp(dp->d_name, p) ) continue;
bpc_strBuf_snprintf(deletePath, 0, "%s/%s", attribPath->s, dp->d_name);
unlink(deletePath->s);
if ( BPC_LogLevel >= 5 ) bpc_logMsgf("bpc_attrib_dirWrite: removed other old attrib file %s\n", deletePath->s);
}
bpc_strBuf_free(deletePath);
closedir(dirOs);
}
}
/*
* update with the new digest
*/
memcpy(&dir->digest, &digest, sizeof(digest));
bpc_strBuf_free(attribPath);
bpc_strBuf_free(attribPathTemp);
return 0;
}
rsync-bpc-3.1.3.0/backuppc/bpc_attribCache.c 0000664 0000000 0000000 00000100610 13737671777 0020574 0 ustar 00root root 0000000 0000000 /*
* Routines for caching multiple directories.
*
* Copyright (C) 2013 Craig Barratt.
*
* 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 "backuppc.h"
#define BPC_ATTRIBCACHE_DIR_COUNT_MAX (380)
#define BPC_ATTRIBCACHE_DIR_HT_SIZE (512)
void bpc_attribCache_init(bpc_attribCache_info *ac, char *hostName, int backupNum, char *shareNameUM, int compress)
{
ac->backupNum = backupNum;
ac->compress = compress;
ac->cacheLruCnt = 0;
ac->bkupMergeList = NULL;
ac->bkupMergeCnt = 0;
ac->deltaInfo = NULL;
ac->shareName = bpc_strBuf_new();
ac->shareNameUM = bpc_strBuf_new();
ac->hostName = bpc_strBuf_new();
ac->backupTopDir = bpc_strBuf_new();
ac->currentDir = bpc_strBuf_new();
bpc_strBuf_strcpy(ac->hostName, 0, hostName);
bpc_strBuf_strcpy(ac->shareNameUM, 0, shareNameUM);
bpc_fileNameEltMangle(ac->shareName, ac->shareNameUM->s);
bpc_strBuf_snprintf(ac->backupTopDir, 0, "%s/pc/%s/%d", BPC_TopDir.s, ac->hostName->s, ac->backupNum);
bpc_strBuf_strcpy(ac->currentDir, 0, "");
bpc_path_create(ac->backupTopDir->s);
bpc_hashtable_create(&ac->attrHT, BPC_ATTRIBCACHE_DIR_HT_SIZE, sizeof(bpc_attribCache_dir));
bpc_hashtable_create(&ac->inodeHT, BPC_ATTRIBCACHE_DIR_HT_SIZE, sizeof(bpc_attribCache_dir));
}
void bpc_attribCache_setDeltaInfo(bpc_attribCache_info *ac, bpc_deltaCount_info *deltaInfo)
{
ac->deltaInfo = deltaInfo;
}
/*
* Caller is responsible for calling malloc for bkupList.
*/
void bpc_attribCache_setMergeList(bpc_attribCache_info *ac, bpc_backup_info *bkupList, int bkupCnt)
{
ac->bkupMergeList = bkupList;
ac->bkupMergeCnt = bkupCnt;
}
static void bpc_attribCache_destroyEntry(bpc_attribCache_dir *attr)
{
bpc_attrib_dirDestroy(&attr->dir);
}
void bpc_attribCache_destroy(bpc_attribCache_info *ac)
{
bpc_hashtable_iterate(&ac->attrHT, (void*)bpc_attribCache_destroyEntry, NULL);
bpc_hashtable_destroy(&ac->attrHT);
bpc_hashtable_iterate(&ac->inodeHT, (void*)bpc_attribCache_destroyEntry, NULL);
bpc_hashtable_destroy(&ac->inodeHT);
if ( ac->bkupMergeList ) free(ac->bkupMergeList);
bpc_strBuf_free(ac->shareName);
bpc_strBuf_free(ac->shareNameUM);
bpc_strBuf_free(ac->hostName);
bpc_strBuf_free(ac->backupTopDir);
bpc_strBuf_free(ac->currentDir);
ac->bkupMergeList = NULL;
ac->bkupMergeCnt = 0;
}
int bpc_attribCache_readOnly(bpc_attribCache_info *ac, int readOnly)
{
if ( readOnly >= 0 ) ac->readOnly = readOnly;
return ac->readOnly;
}
void bpc_attribCache_setCurrentDirectory(bpc_attribCache_info *ac, char *dir)
{
char *p;
bpc_strBuf_strcpy(ac->currentDir, 0, dir);
p = ac->currentDir->s + strlen(ac->currentDir->s) - 1;
while ( p >= ac->currentDir->s && p[0] == '/' ) *p-- = '\0';
}
/*
* Given a backup path, split it into the directory, file name, and path to the directory (starting
* with the share name, ie: relative to ac->backupTopDir->s).
*
* splitPath will strip initial "./" and trailing "/." or "/" before splitting the path, but isn't
* capable of handling paths with "/." in the middle, or ".." anywhere.
*/
static void splitPath(bpc_attribCache_info *ac, bpc_strBuf *dir, bpc_strBuf *fileName, bpc_strBuf *attribPath, char *path)
{
bpc_strBuf *fullPath = bpc_strBuf_new();
size_t pathLen;
/*
* remove initial "./"
*/
while ( path[0] == '.' && path[1] == '/' ) {
path += 2;
while ( path[0] == '/' ) path++;
}
/*
* if this is a relative path, prepend ac->currentDir->s (provided ac->currentDir->s is set)
*/
if ( path[0] != '/' && ac->currentDir->s[0] ) {
bpc_strBuf_snprintf(fullPath, 0, "%s/%s", ac->currentDir->s, path);
path = fullPath->s;
}
/*
* strip trailing "/." or "/"
*/
pathLen = strlen(path);
while ( (pathLen > 1 && path[pathLen - 2] == '/' && path[pathLen - 1] == '.')
|| (pathLen > 0 && path[pathLen - 1] == '/') ) {
if ( path != fullPath->s ) {
bpc_strBuf_strcpy(fullPath, 0, path);
path = fullPath->s;
}
if ( path[pathLen - 1] == '/' ) {
pathLen -= 1;
} else {
pathLen -= 2;
}
path[pathLen] = '\0';
if ( BPC_LogLevel >= 9 ) bpc_logMsgf("splitPath: trimming path = '%s'\n", path);
}
if ( !path[0] || (!path[1] && (path[0] == '.' || path[0] == '/')) ) {
bpc_strBuf_strcpy(fileName, 0, ac->shareNameUM->s);
bpc_strBuf_strcpy(dir, 0, "/");
bpc_strBuf_strcpy(attribPath, 0, "/attrib");
} else {
char *p;
int i;
bpc_strBuf_strcpy(dir, 0, ac->shareName->s);
i = strlen(dir->s);
if ( (p = strrchr(path, '/')) ) {
if ( *path != '/' ) {
bpc_strBuf_strcat(dir, i++, "/");
}
bpc_strBuf_strcpy(fileName, 0, p+1);
*p = '\0';
bpc_fileNameMangle(dir, path, i);
*p = '/';
} else {
bpc_strBuf_strcpy(fileName, 0, path);
}
bpc_strBuf_snprintf(attribPath, 0, "%s/attrib", dir->s);
}
if ( BPC_LogLevel >= 9 ) bpc_logMsgf("splitPath: returning dir = '%s', fileName = '%s', attrib = '%s' from path = '%s'\n",
dir->s, fileName->s, attribPath->s, path);
bpc_strBuf_free(fullPath);
}
static void inodePath(UNUSED(bpc_attribCache_info *ac), char *indexStr, bpc_strBuf *attribPath, bpc_strBuf *attribFile, ino_t inode)
{
bpc_strBuf_snprintf(attribPath, 0, "inode/%02x", (unsigned int)(inode >> 17) & 0x7f);
bpc_strBuf_snprintf(attribFile, 0, "attrib%02x", (unsigned int)(inode >> 10) & 0x7f);
do {
bpc_byte2hex(indexStr, inode & 0xff);
indexStr += 2;
inode >>= 8;
} while ( inode );
*indexStr = '\0';
}
static void bpc_attribCache_removeDeletedEntries(bpc_attrib_file *file, void *arg)
{
bpc_attribCache_dir *attr = (bpc_attribCache_dir*)arg;
if ( file->type != BPC_FTYPE_DELETED ) return;
attr->dirty = 1;
bpc_attrib_fileDestroy(file);
bpc_hashtable_nodeDelete(&attr->dir.filesHT, file);
}
static bpc_attribCache_dir *bpc_attribCache_loadPath(bpc_attribCache_info *ac, bpc_strBuf *fileName, char *path)
{
bpc_strBuf *dirStr = bpc_strBuf_new(), *attribPath = bpc_strBuf_new();
bpc_attribCache_dir *attr;
int attribPathLen, status;
splitPath(ac, dirStr, fileName, attribPath, path);
attribPathLen = strlen(attribPath->s);
if ( BPC_LogLevel >= 9 ) bpc_logMsgf("bpc_attribCache_loadPath: path = %s -> dir = %s, fileName = %s, attribPath = %s\n", path, dirStr->s, fileName, attribPath->s);
bpc_strBuf_free(dirStr);
attr = bpc_hashtable_find(&ac->attrHT, (uchar*)attribPath->s, attribPathLen, 1);
if ( !attr || attr->key.key != attribPath->s ) {
/*
* cache hit - return the existing attributes
*/
if ( attr ) attr->lruCnt = ac->cacheLruCnt++;
bpc_strBuf_free(attribPath);
return attr;
}
if ( !(attr->key.key = malloc(attribPathLen + 1)) ) {
bpc_logErrf("bpc_attribCache_loadPath: can't allocate %d bytes\n", attribPathLen + 1);
bpc_strBuf_free(attribPath);
return NULL;
}
strcpy(attr->key.key, attribPath->s);
bpc_attrib_dirInit(&attr->dir, ac->compress);
attr->dirty = 0;
attr->dirOk = 0;
attr->lruCnt = ac->cacheLruCnt++;
if ( ac->bkupMergeCnt > 0 ) {
int i;
bpc_strBuf *topDir = bpc_strBuf_new(), *fullAttribPath = bpc_strBuf_new();
/*
* Merge multiple attrib files to create the "view" for this backup.
* There are two cases: merging forward for v3, or merging in reverse
* for v4+. bkupMergeList is already in the order we need.
*/
for ( i = 0 ; i < ac->bkupMergeCnt ; i++ ) {
bpc_attrib_dir dir;
ssize_t entrySize;
char *entries, *entry;
bpc_strBuf_snprintf(topDir, 0, "%s/pc/%s/%d", BPC_TopDir.s, ac->hostName->s, ac->bkupMergeList[i].num);
bpc_strBuf_snprintf(fullAttribPath, 0, "%s/%s", topDir->s, attribPath->s);
bpc_attrib_dirInit(&dir, ac->bkupMergeList[i].compress);
if ( (status = bpc_attrib_dirRead(&dir, topDir->s, attribPath->s, ac->bkupMergeList[i].num)) ) {
if ( ac->bkupMergeList[i].version < 4 ) {
char *p;
int attribDirExists = 1;
STRUCT_STAT st;
if ( (p = strrchr(fullAttribPath->s, '/')) ) {
*p = '\0';
attribDirExists = !stat(fullAttribPath->s, &st) && S_ISDIR(st.st_mode);
*p = '/';
}
if ( i == ac->bkupMergeCnt - 1 && !attribDirExists ) {
/*
* For V3, if the last backup doesn't have a directory, then the merged view is empty
*/
bpc_attrib_dirDestroy(&dir);
bpc_attrib_dirDestroy(&attr->dir);
bpc_attrib_dirInit(&attr->dir, ac->compress);
break;
}
if ( !attribDirExists ) {
/*
* nothing to update here - keep going
*/
bpc_attrib_dirDestroy(&dir);
continue;
}
}
bpc_logErrf("bpc_attribCache_loadPath: bpc_attrib_dirRead(%s/%s) returned %d\n", topDir->s, attribPath->s, status);
}
if ( bpc_attrib_dirNeedRewrite(&dir) ) {
attr->dirty = 1;
}
entrySize = bpc_attrib_getEntries(&dir, NULL, 0);
if ( (entries = malloc(entrySize + 1)) && bpc_attrib_getEntries(&dir, entries, entrySize) == entrySize ) {
for ( entry = entries ; entry < entries + entrySize ; entry += strlen(entry) + 1 ) {
bpc_attrib_file *file = bpc_attrib_fileGet(&dir, entry, 0);
if ( !file ) continue;
if ( file->type == BPC_FTYPE_DELETED ) {
bpc_attrib_fileDeleteName(&attr->dir, entry);
} else {
bpc_attrib_file *fileDest;
if ( !(fileDest = bpc_attrib_fileGet(&attr->dir, entry, 1)) ) {
bpc_strBuf_free(attribPath);
bpc_strBuf_free(topDir);
bpc_strBuf_free(fullAttribPath);
return NULL;
}
if ( fileDest->key.key == entry ) {
/*
* new entry - initialize
*/
bpc_attrib_fileInit(fileDest, entry, 0);
}
bpc_attrib_fileCopy(fileDest, file);
fileDest->backupNum = ac->bkupMergeList[i].num;
}
}
} else {
bpc_logErrf("bpc_attribCache_loadPath(%s/%s): can't malloc %lu bytes for entries\n",
topDir->s, attribPath->s, (unsigned long)entrySize);
if ( entries ) free(entries);
bpc_attrib_dirDestroy(&dir);
bpc_strBuf_free(attribPath);
bpc_strBuf_free(topDir);
bpc_strBuf_free(fullAttribPath);
return NULL;
}
free(entries);
bpc_attrib_dirDestroy(&dir);
}
bpc_strBuf_free(topDir);
bpc_strBuf_free(fullAttribPath);
} else {
/*
* non-merge case - read the single attrib file
*/
if ( (status = bpc_attrib_dirRead(&attr->dir, ac->backupTopDir->s, attribPath->s, ac->backupNum)) ) {
bpc_logErrf("bpc_attribCache_loadPath: bpc_attrib_dirRead(%s, %s) returned %d\n", ac->backupTopDir->s, attribPath->s, status);
}
if ( bpc_attrib_dirNeedRewrite(&attr->dir) ) {
attr->dirty = 1;
}
/*
* remove any extraneous BPC_FTYPE_DELETED file types
*/
bpc_hashtable_iterate(&attr->dir.filesHT, (void*)bpc_attribCache_removeDeletedEntries, attr);
}
if ( attr->dirty ) {
if ( BPC_LogLevel >= 8 ) bpc_logMsgf("bpc_attribCache_loadPath: will rewrite path = %s -> dir = %s, fileName = %s, attribPath = %s\n", path, dirStr->s, fileName, attribPath->s);
}
if ( bpc_hashtable_entryCount(&ac->attrHT) > BPC_ATTRIBCACHE_DIR_COUNT_MAX ) {
bpc_attribCache_flush(ac, 0, NULL);
}
bpc_strBuf_free(attribPath);
return attr;
}
static bpc_attribCache_dir *bpc_attribCache_loadInode(bpc_attribCache_info *ac, char *indexStr, ino_t inode)
{
bpc_strBuf *attribPath = bpc_strBuf_new(), *attribDir = bpc_strBuf_new(), *attribFile = bpc_strBuf_new();
bpc_strBuf *inodeDir, *fullAttribPath;
bpc_attribCache_dir *attr;
int attribPathLen, status;
inodePath(ac, indexStr, attribDir, attribFile, inode);
attribPathLen = bpc_strBuf_snprintf(attribPath, 0, "%s/%s", attribDir->s, attribFile->s);
attr = bpc_hashtable_find(&ac->inodeHT, (uchar*)attribPath->s, attribPathLen, 1);
if ( !attr || attr->key.key != attribPath->s ) {
if ( attr ) attr->lruCnt = ac->cacheLruCnt++;
bpc_strBuf_free(attribPath);
bpc_strBuf_free(attribDir);
bpc_strBuf_free(attribFile);
return attr;
}
/*
* new entry - read the attrib file
*/
if ( !(attr->key.key = malloc(attribPathLen + 1)) ) {
bpc_logErrf("bpc_attribCache_loadInode: can't allocate %d bytes\n", attribPathLen + 1);
bpc_strBuf_free(attribPath);
bpc_strBuf_free(attribDir);
bpc_strBuf_free(attribFile);
return NULL;
}
strcpy(attr->key.key, attribPath->s);
bpc_attrib_dirInit(&attr->dir, ac->compress);
attr->dirty = 0;
attr->dirOk = 1;
attr->lruCnt = ac->cacheLruCnt++;
inodeDir = bpc_strBuf_new();
fullAttribPath = bpc_strBuf_new();
if ( ac->bkupMergeCnt > 0 ) {
int i;
/*
* Merge multiple attrib files to create the "view" for this backup.
* There is only one case here, v4, since v3 didn't have inodes.
*/
for ( i = 0 ; i < ac->bkupMergeCnt ; i++ ) {
bpc_attrib_dir dir;
ssize_t entrySize;
char *entries, *entry;
bpc_strBuf_snprintf(inodeDir, 0, "%s/pc/%s/%d/%s", BPC_TopDir.s, ac->hostName->s, ac->bkupMergeList[i].num, attribDir->s);
bpc_strBuf_snprintf(fullAttribPath, 0, "%s/%s", inodeDir->s, attribFile->s);
bpc_attrib_dirInit(&dir, ac->bkupMergeList[i].compress);
if ( (status = bpc_attrib_dirRead(&dir, inodeDir->s, attribFile->s, ac->bkupMergeList[i].num)) ) {
STRUCT_STAT st;
int attribDirExists = !stat(inodeDir->s, &st) && S_ISDIR(st.st_mode);
if ( ac->bkupMergeList[i].version < 4 || !attribDirExists ) {
/*
* nothing to update here - keep going
*/
bpc_attrib_dirDestroy(&dir);
continue;
}
bpc_logErrf("bpc_attribCache_loadInode: bpc_attrib_dirRead(%s/%s) returned %d\n", inodeDir->s, attribFile->s, status);
}
if ( bpc_attrib_dirNeedRewrite(&dir) ) {
attr->dirty = 1;
}
entrySize = bpc_attrib_getEntries(&dir, NULL, 0);
if ( (entries = malloc(entrySize + 1)) && bpc_attrib_getEntries(&dir, entries, entrySize) == entrySize ) {
for ( entry = entries ; entry < entries + entrySize ; entry += strlen(entry) + 1 ) {
bpc_attrib_file *file = bpc_attrib_fileGet(&dir, entry, 0);
if ( !file ) continue;
if ( file->type == BPC_FTYPE_DELETED ) {
bpc_attrib_fileDeleteName(&attr->dir, entry);
} else {
bpc_attrib_file *fileDest;
if ( !(fileDest = bpc_attrib_fileGet(&attr->dir, entry, 1)) ) {
bpc_strBuf_free(attribPath);
bpc_strBuf_free(attribDir);
bpc_strBuf_free(attribFile);
bpc_strBuf_free(inodeDir);
bpc_strBuf_free(fullAttribPath);
return NULL;
}
if ( fileDest->key.key == entry ) {
/*
* new entry - initialize
*/
bpc_attrib_fileInit(fileDest, entry, 0);
}
bpc_attrib_fileCopy(fileDest, file);
}
}
} else {
bpc_logErrf("bpc_attribCache_loadInode(%s): can't malloc %lu bytes for entries\n",
fullAttribPath->s, (unsigned long)entrySize);
if ( entries ) free(entries);
bpc_attrib_dirDestroy(&dir);
bpc_strBuf_free(attribPath);
bpc_strBuf_free(attribDir);
bpc_strBuf_free(attribFile);
bpc_strBuf_free(inodeDir);
bpc_strBuf_free(fullAttribPath);
return NULL;
}
free(entries);
bpc_attrib_dirDestroy(&dir);
}
} else {
/*
* non-merge case - read the single attrib file
*/
bpc_strBuf_snprintf(inodeDir, 0, "%s/%s", ac->backupTopDir->s, attribDir->s);
if ( (status = bpc_attrib_dirRead(&attr->dir, inodeDir->s, attribFile->s, ac->backupNum)) ) {
bpc_logErrf("bpc_attribCache_loadInode: bpc_attrib_dirRead(%s/%s) returned %d\n", inodeDir->s, attribFile->s, status);
}
if ( bpc_attrib_dirNeedRewrite(&attr->dir) ) {
attr->dirty = 1;
}
}
if ( attr->dirty ) {
if ( BPC_LogLevel >= 8 ) bpc_logMsgf("bpc_attribCache_loadInode: will rewrite path = %s -> dir = %s, fileName = %s\n", attribPath, attribDir, attribFile);
}
if ( bpc_hashtable_entryCount(&ac->inodeHT) > BPC_ATTRIBCACHE_DIR_COUNT_MAX ) {
bpc_attribCache_flush(ac, 0, NULL);
}
bpc_strBuf_free(attribPath);
bpc_strBuf_free(attribDir);
bpc_strBuf_free(attribFile);
bpc_strBuf_free(inodeDir);
bpc_strBuf_free(fullAttribPath);
return attr;
}
bpc_attrib_file *bpc_attribCache_getFile(bpc_attribCache_info *ac, char *path, int allocate_if_missing, int dontReadInode)
{
bpc_strBuf *fileName = bpc_strBuf_new();
bpc_attribCache_dir *attr;
bpc_attrib_file *file;
if ( !(attr = bpc_attribCache_loadPath(ac, fileName, path)) ) {
bpc_strBuf_free(fileName);
return NULL;
}
attr->lruCnt = ac->cacheLruCnt++;
if ( !(file = bpc_attrib_fileGet(&attr->dir, fileName->s, allocate_if_missing)) ) {
bpc_strBuf_free(fileName);
return NULL;
}
if ( allocate_if_missing && file->key.key == fileName->s ) {
/*
* new entry - initialize
*/
bpc_attrib_fileInit(file, fileName->s, 0);
file->compress = ac->compress;
}
bpc_strBuf_free(fileName);
if ( dontReadInode || file->nlinks == 0 ) return file;
return bpc_attribCache_getInode(ac, file->inode, allocate_if_missing);
}
int bpc_attribCache_setFile(bpc_attribCache_info *ac, char *path, bpc_attrib_file *file, int dontOverwriteInode)
{
bpc_strBuf *fileName = bpc_strBuf_new();
char indexStr[256];
bpc_attribCache_dir *attr, *attrInode;
bpc_attrib_file *fileDest;
if ( !(attr = bpc_attribCache_loadPath(ac, fileName, path)) ) {
bpc_strBuf_free(fileName);
return -1;
}
attr->lruCnt = ac->cacheLruCnt++;
file->compress = ac->compress;
if ( !(fileDest = bpc_attrib_fileGet(&attr->dir, fileName->s, 1)) ) {
bpc_strBuf_free(fileName);
return -1;
}
if ( fileDest->key.key == fileName->s ) {
/*
* new entry - initialize
*/
bpc_attrib_fileInit(fileDest, fileName->s, 0);
}
bpc_attrib_fileCopy(fileDest, file);
attr->dirty = 1;
bpc_strBuf_free(fileName);
if ( file->nlinks > 0 ) {
bpc_attrib_file *inodeDest = bpc_attribCache_getInode(ac, file->inode, 0);
if ( !dontOverwriteInode || !inodeDest ) {
inodeDest = bpc_attribCache_getInode(ac, file->inode, 1);
bpc_attrib_fileCopyOpt(inodeDest, file, 0);
attrInode = bpc_attribCache_loadInode(ac, indexStr, file->inode);
attrInode->dirty = 1;
/*
* remove the digest from the file attributes since the reference counting is reflected
* by the inode (can't do this up above since fileDest might be the same as file).
*/
fileDest->digest.len = 0;
return 1;
} else {
/*
* remove the digest from the file attributes since the reference counting is reflected
* by the inode (can't do this up above since fileDest might be the same as file).
*/
fileDest->digest.len = 0;
return 0;
}
}
return 1;
}
int bpc_attribCache_deleteFile(bpc_attribCache_info *ac, char *path)
{
bpc_strBuf *fileName = bpc_strBuf_new();
bpc_attribCache_dir *attr;
if ( !(attr = bpc_attribCache_loadPath(ac, fileName, path)) ) {
bpc_strBuf_free(fileName);
return -1;
}
attr->lruCnt = ac->cacheLruCnt++;
bpc_attrib_fileDeleteName(&attr->dir, fileName->s);
attr->dirty = 1;
bpc_strBuf_free(fileName);
return 0;
}
bpc_attrib_file *bpc_attribCache_getInode(bpc_attribCache_info *ac, ino_t inode, int allocate_if_missing)
{
char indexStr[256];
bpc_attribCache_dir *attr;
bpc_attrib_file *file;
if ( !(attr = bpc_attribCache_loadInode(ac, indexStr, inode)) ) return NULL;
attr->lruCnt = ac->cacheLruCnt++;
if ( !(file = bpc_attrib_fileGet(&attr->dir, indexStr, allocate_if_missing)) ) return NULL;
if ( allocate_if_missing && file->key.key == indexStr ) {
/*
* new entry - initialize
*/
bpc_attrib_fileInit(file, indexStr, 0);
file->compress = ac->compress;
}
return file;
}
int bpc_attribCache_setInode(bpc_attribCache_info *ac, ino_t inode, bpc_attrib_file *inodeSrc)
{
char indexStr[256];
bpc_attribCache_dir *attr;
bpc_attrib_file *inodeDest;
if ( !(attr = bpc_attribCache_loadInode(ac, indexStr, inode)) ) return -1;
attr->lruCnt = ac->cacheLruCnt++;
if ( !(inodeDest = bpc_attrib_fileGet(&attr->dir, indexStr, 1)) ) return -1;
if ( inodeDest->key.key == indexStr ) {
/*
* new entry - initialize
*/
bpc_attrib_fileInit(inodeDest, indexStr, 0);
}
bpc_attrib_fileCopy(inodeDest, inodeSrc);
attr->dirty = 1;
return 0;
}
int bpc_attribCache_deleteInode(bpc_attribCache_info *ac, ino_t inode)
{
char indexStr[256];
bpc_attribCache_dir *attr;
if ( !(attr = bpc_attribCache_loadInode(ac, indexStr, inode)) ) return -1;
attr->lruCnt = ac->cacheLruCnt++;
bpc_attrib_fileDeleteName(&attr->dir, indexStr);
attr->dirty = 1;
return 0;
}
int bpc_attribCache_getDirEntryCnt(bpc_attribCache_info *ac, char *path)
{
bpc_attribCache_dir *attr;
bpc_strBuf *fileName = bpc_strBuf_new(), *pathAppend = bpc_strBuf_new();
/*
* Append a fake file name so we actually open the directory's contents, not the directory entry one level up
*/
bpc_strBuf_snprintf(pathAppend, 0, "%s/x", path);
attr = bpc_attribCache_loadPath(ac, fileName, pathAppend->s);
bpc_strBuf_free(fileName);
bpc_strBuf_free(pathAppend);
if ( !attr ) return -1;
return bpc_hashtable_entryCount(&attr->dir.filesHT);
}
typedef struct {
char *entries;
ssize_t entryIdx;
ssize_t entrySize;
} dirEntry_info;
static void bpc_attribCache_getDirEntry(bpc_attrib_file *file, dirEntry_info *info)
{
ssize_t len = strlen(file->name) + 1;
if ( info->entryIdx < 0 ) return;
if ( info->entries ) {
if ( info->entryIdx + len + (ssize_t)sizeof(ino_t) > info->entrySize ) {
info->entryIdx = -1;
return;
}
memcpy(info->entries + info->entryIdx, file->name, len);
info->entryIdx += len;
memcpy(info->entries + info->entryIdx, &file->inode, sizeof(ino_t));
info->entryIdx += sizeof(ino_t);
} else {
info->entryIdx += len + sizeof(ino_t);
}
}
ssize_t bpc_attribCache_getDirEntries(bpc_attribCache_info *ac, char *path, char *entries, ssize_t entrySize)
{
bpc_attribCache_dir *attr;
bpc_strBuf *fileName = bpc_strBuf_new(), *fullPath = bpc_strBuf_new();
dirEntry_info info;
ino_t inode = 0;
/*
* Append a fake file name so we actually open the directory's contents, not the directory entry one level up
*/
if ( path[0] == '.' && path[1] == '\0' ) {
if ( ac->currentDir->s[0] ) {
bpc_strBuf_snprintf(fullPath, 0, "%s/x", ac->currentDir->s);
} else {
bpc_strBuf_strcpy(fullPath, 0, "/x");
}
attr = bpc_attribCache_loadPath(ac, fileName, fullPath->s);
} else {
bpc_strBuf_snprintf(fullPath, 0, "%s/x", path);
attr = bpc_attribCache_loadPath(ac, fileName, fullPath->s);
}
bpc_strBuf_free(fileName);
bpc_strBuf_free(fullPath);
if ( !attr ) return -1;
attr->lruCnt = ac->cacheLruCnt++;
info.entries = entries;
info.entryIdx = 0;
info.entrySize = entrySize;
if ( entries && entrySize >= (ssize_t)(5 + 2 * sizeof(ino_t)) ) {
strcpy(info.entries + info.entryIdx, ".");
info.entryIdx += 2;
/* dummy inode number */
memcpy(info.entries + info.entryIdx, &inode, sizeof(inode));
info.entryIdx += sizeof(inode);
strcpy(info.entries + info.entryIdx, "..");
info.entryIdx += 3;
/* dummy inode number */
memcpy(info.entries + info.entryIdx, &inode, sizeof(inode));
info.entryIdx += sizeof(inode);
} else {
info.entryIdx += 5 + 2 * sizeof(ino_t);
}
bpc_hashtable_iterate(&attr->dir.filesHT, (void*)bpc_attribCache_getDirEntry, &info);
return info.entryIdx;
}
typedef struct {
char *path;
int pathLen;
int all;
bpc_attribCache_info *ac;
int entryCnt;
int entryIdx;
bpc_attribCache_dir **entries;
bpc_hashtable *ht;
int errorCnt;
} flush_info;
static void bpc_attribCache_dirWrite(bpc_attribCache_dir *attr, flush_info *info)
{
int status;
if ( !info->ac->readOnly && !info->all && info->path ) {
if ( BPC_LogLevel >= 9 ) bpc_logMsgf("bpc_attribCache_dirWrite: comparing %s vs key %s\n", info->path, attr->key.key);
if ( strncmp(info->path, attr->key.key, info->pathLen)
|| (((char*)attr->key.key)[info->pathLen] != '/' && ((char*)attr->key.key)[info->pathLen] != '\0') ) {
if ( BPC_LogLevel >= 9 ) bpc_logMsgf("bpc_attribCache_dirWrite: skipping %s (doesn't match %s)\n", (char*)attr->key.key, info->path);
return;
}
}
if ( !info->ac->readOnly && attr->dirty ) {
bpc_digest *oldDigest = bpc_attrib_dirDigestGet(&attr->dir);
if ( BPC_LogLevel >= 6 ) bpc_logMsgf("bpc_attribCache_dirWrite: writing %s/%s with %d entries (oldDigest = 0x%02x%02x...)\n",
info->ac->backupTopDir->s, (char*)attr->key.key, bpc_hashtable_entryCount(&attr->dir.filesHT),
oldDigest ? oldDigest->digest[0] : 0, oldDigest ? oldDigest->digest[1] : 0);
if ( (status = bpc_attrib_dirWrite(info->ac->deltaInfo, &attr->dir, info->ac->backupTopDir->s, attr->key.key, oldDigest)) ) {
bpc_logErrf("bpc_attribCache_dirWrite: failed to write attributes for dir %s\n", (char*)attr->key.key);
info->errorCnt++;
}
}
/*
* Now deallocate memory
*/
bpc_attrib_dirDestroy(&attr->dir);
if ( attr->key.key ) free(attr->key.key);
bpc_hashtable_nodeDelete(info->ht, attr);
}
static void bpc_attribCache_flush_lruListFill(bpc_attribCache_dir *attr, flush_info *info)
{
if ( info->entryIdx >= info->entryCnt ) return;
info->entries[info->entryIdx++] = attr;
}
static int bpc_attribCache_flush_lruCompare(bpc_attribCache_dir **d1, bpc_attribCache_dir **d2)
{
return (*d1)->lruCnt - (*d2)->lruCnt;
}
/*
* Build a list of all entries in the hash table, sorted by LRU count from lowest to highest
*/
static void bpc_attribCache_flush_lruList(flush_info *info)
{
int i;
/*
* allocate list of all entries
*/
info->entryCnt = bpc_hashtable_entryCount(info->ht);
info->entryIdx = 0;
info->entries = NULL;
if ( info->entryCnt == 0 ) return;
if ( !(info->entries = malloc(info->entryCnt * sizeof(*info->entries))) ) {
bpc_logErrf("bpc_attribCache_flush_lruList: can't allocated %lu bytes\n", (unsigned long)info->entryCnt * sizeof(*info->entries));
return;
}
bpc_hashtable_iterate(info->ht, (void*)bpc_attribCache_flush_lruListFill, info);
/*
* sort by lruCnt, from lowest to highest
*/
qsort(info->entries, info->entryCnt, sizeof(*info->entries), (void*)bpc_attribCache_flush_lruCompare);
/*
* Now flush the oldest half of the entries
*/
for ( i = 0 ; i < info->entryCnt / 2 ; i++ ) {
bpc_attribCache_dirWrite(info->entries[i], info);
}
if ( info->entries ) free(info->entries);
}
/*
* Flush some or all of the cache. If all, then flush everything. If path is not NULL
* then just those entries that start with that path are flushed.
*/
void bpc_attribCache_flush(bpc_attribCache_info *ac, int all, char *path)
{
flush_info info;
bpc_strBuf *attribPath = bpc_strBuf_new();
info.all = all;
info.ac = ac;
if ( path ) {
bpc_strBuf *pathDeep = bpc_strBuf_new(), *fileName = bpc_strBuf_new(), *dir = bpc_strBuf_new();
bpc_strBuf_snprintf(pathDeep, 0, "%s/foo", path);
splitPath(ac, dir, fileName, attribPath, pathDeep->s);
info.path = attribPath->s;
info.pathLen = strlen(info.path);
bpc_strBuf_free(pathDeep);
bpc_strBuf_free(fileName);
bpc_strBuf_free(dir);
} else {
info.path = NULL;
info.pathLen = 0;
}
info.entryCnt = 0;
info.entryIdx = 0;
info.entries = NULL;
info.errorCnt = 0;
if ( !all && !path ) {
/*
* flush the oldest half of the entries based on the lruCnt
*/
info.ht = &ac->attrHT;
bpc_attribCache_flush_lruList(&info);
info.ht = &ac->inodeHT;
bpc_attribCache_flush_lruList(&info);
} else {
info.ht = &ac->attrHT;
bpc_hashtable_iterate(&ac->attrHT, (void*)bpc_attribCache_dirWrite, &info);
info.ht = &ac->inodeHT;
bpc_hashtable_iterate(&ac->inodeHT, (void*)bpc_attribCache_dirWrite, &info);
}
if ( info.errorCnt ) {
/*
* Any errors likely mean the deltas are probably out of sync with the
* file system, so request an fsck.
*/
bpc_poolRefRequestFsck(ac->backupTopDir->s, 1);
}
bpc_strBuf_free(attribPath);
}
/*
* Returns the full mangled path, given a file path.
*/
void bpc_attribCache_getFullMangledPath(bpc_attribCache_info *ac, bpc_strBuf *path, char *dirName, int backupNum)
{
char *p;
int len;
do {
p = dirName;
while ( dirName[0] == '.' && dirName[1] == '/' ) dirName += 2;
while ( dirName[0] == '/' ) dirName++;
} while ( p != dirName );
if ( backupNum < 0 || ac->bkupMergeCnt <= 0 ) {
backupNum = ac->backupNum;
}
len = bpc_strBuf_snprintf(path, 0, "%s/pc/%s/%d/%s", BPC_TopDir.s, ac->hostName->s, backupNum, ac->shareName->s);
if ( (dirName[0] == '/' && dirName[1] == '\0') || dirName[0] == '\0' ) {
return;
}
bpc_strBuf_strcat(path, len++, "/");
bpc_fileNameMangle(path, dirName, len);
}
rsync-bpc-3.1.3.0/backuppc/bpc_dirOps.c 0000664 0000000 0000000 00000022675 13737671777 0017641 0 ustar 00root root 0000000 0000000 /*
* Directory and file system operations
*
* Copyright (C) 2013 Craig Barratt.
*
* 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 "backuppc.h"
/*
* Create all the directories in the given path. Path must be non-const. Trailing '/' characters are removed.
*/
int bpc_path_create(char *path)
{
char *p = path;
STRUCT_STAT st;
int levels = 0;
if ( BPC_LogLevel >= 6 ) bpc_logMsgf("bpc_path_create(%s)\n", path);
/*
* check if it exists already
*/
if ( !stat(path, &st) && S_ISDIR(st.st_mode) ) return 0;
/*
* We walk up until we find the deepest level directory that exists.
* First remove trailing slashes.
*/
p = path + strlen(path);
while ( p > path && p[-1] == '/' ) p--;
if ( *p == '/' ) *p = '\0';
while ( p > path ) {
while ( p > path && p[-1] != '/' ) p--;
while ( p > path && p[-1] == '/' ) p--;
if ( *p == '/' ) {
*p = '\0';
levels++;
if ( !stat(path, &st) && S_ISDIR(st.st_mode) ) break;
}
}
if ( BPC_LogLevel >= 9 ) bpc_logMsgf("bpc_path_create: found that %s exists (%d levels up)\n", path, levels);
/*
* We have removed levels '/' characters from path. Replace each one and create the directory.
*/
while ( levels-- > 0 ) {
p = path + strlen(path);
*p = '/';
if ( mkdir(path, ACCESSPERMS) < 0 && errno != EEXIST) {
bpc_logErrf("bpc_path_create: can't create %s (errno %d)\n", path, errno);
return -1;
}
if ( BPC_LogLevel >= 9 ) bpc_logMsgf("bpc_path_create: created %s\n", path);
}
return 0;
}
/*
* Remove all the files below path (if a directory) and path itself. Deduct reference counts
* for every attrib file removed.
*
* Note that inodes are *not* updated, even in cases where nlinks > 0.
*/
int bpc_path_remove(bpc_deltaCount_info *deltaInfo, char *path, int compress)
{
bpc_strBuf *filePath, *dirList;
size_t dirListLen = 0;
STRUCT_STAT st;
DIR *dir;
struct dirent *dp;
int errorCnt = 0;
if ( BPC_LogLevel >= 6 ) bpc_logMsgf("bpc_path_remove(%s)\n", path);
if ( !(dir = opendir(path)) ) {
unlink(path);
return errorCnt;
}
filePath = bpc_strBuf_new();
dirList = bpc_strBuf_new();
while ( (dp = readdir(dir)) ) {
if ( !strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..") ) continue;
bpc_strBuf_snprintf(filePath, 0, "%s/%s", path, dp->d_name);
if ( BPC_LogLevel >= 8 ) bpc_logMsgf("bpc_path_remove: removing %s\n", filePath->s);
if ( stat(filePath->s, &st) ) {
/*
* hmmm. stat failed - just try to remove it
*/
unlink(filePath->s);
continue;
}
if ( S_ISDIR(st.st_mode) ) {
/*
* To avoid recursing with dir still open (consuming an open fd), remember all the dirs
* and recurse after we close dir. We concatenate the '\0' terminated strings,
* keeping the '\0' (can't use bpc_strBuf_strcat()).
*/
bpc_strBuf_strcpy(dirList, dirListLen, dp->d_name);
dirListLen += strlen(dp->d_name) + 1;
} else {
/*
* if this is an attrib file, we need to read it and deduct the reference counts.
*/
if ( !strncmp(dp->d_name, "attrib", 6) ) {
bpc_attrib_dir dir;
bpc_attrib_dirInit(&dir, compress);
if ( bpc_attrib_dirRead(&dir, NULL, filePath->s, 0) ) {
bpc_logErrf("bpc_path_remove: can't read attrib file %s\n", filePath->s);
errorCnt++;
}
if ( BPC_LogLevel >= 9 ) bpc_logMsgf("bpc_path_remove: adjusting ref counts from attrib file %s\n", filePath->s);
if ( !unlink(filePath->s) ) {
/*
* Only reduce the ref counts if we succeeded in removing the attrib file
*/
bpc_attrib_dirRefCount(deltaInfo, &dir, -1);
}
bpc_attrib_dirDestroy(&dir);
} else {
if ( unlink(filePath->s) ) errorCnt++;
}
}
}
closedir(dir);
/*
* Now visit the subdirs we have saved above.
*/
if ( dirListLen > 0 ) {
char *dirListP;
for ( dirListP = dirList->s ; dirListP < dirList->s + dirListLen ; dirListP += strlen(dirListP) + 1 ) {
bpc_strBuf_snprintf(filePath, 0, "%s/%s", path, dirListP);
errorCnt += bpc_path_remove(deltaInfo, filePath->s, compress);
}
}
if ( rmdir(path) ) errorCnt++;
bpc_strBuf_free(filePath);
bpc_strBuf_free(dirList);
return errorCnt;
}
/*
* Reference count all the files below the directory path, based on the attrib
* files in and below path.
*/
int bpc_path_refCountAllInodeMax(bpc_deltaCount_info *deltaInfo, char *path, int compress, int incr, unsigned int *inodeMax)
{
bpc_strBuf *filePath, *dirList;
size_t dirListLen = 0;
STRUCT_STAT st;
DIR *dir;
struct dirent *dp;
int errorCnt = 0;
if ( BPC_LogLevel >= 6 ) bpc_logMsgf("bpc_path_refCountAll(%s)\n", path);
if ( !(dir = opendir(path)) ) {
return errorCnt;
}
filePath = bpc_strBuf_new();
dirList = bpc_strBuf_new();
while ( (dp = readdir(dir)) ) {
if ( !strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..") ) continue;
bpc_strBuf_snprintf(filePath, 0, "%s/%s", path, dp->d_name);
if ( BPC_LogLevel >= 8 ) bpc_logMsgf("bpc_path_refCountAll: got %s\n", filePath->s);
if ( stat(filePath->s, &st) ) continue;
if ( S_ISDIR(st.st_mode) ) {
/*
* To avoid recursing with dir still open (consuming an open fd), remember all the dirs
* and recurse after we close dir. We concatenate the '\0' terminated strings,
* keeping the '\0' (can't use bpc_strBuf_strcat()).
*/
bpc_strBuf_strcpy(dirList, dirListLen, dp->d_name);
dirListLen += strlen(dp->d_name) + 1;
} else {
/*
* if this is an attrib file, we need to read it and deduct the reference counts.
*/
if ( !strncmp(dp->d_name, "attrib", 6) ) {
bpc_attrib_dir dir;
bpc_attrib_dirInit(&dir, compress);
if ( bpc_attrib_dirRead(&dir, path, dp->d_name, 0) ) {
bpc_logErrf("bpc_path_refCountAll: can't read attrib file %s\n", filePath->s);
errorCnt++;
} else {
if ( BPC_LogLevel >= 9 ) bpc_logMsgf("bpc_path_refCountAll: adjusting ref counts from attrib file %s\n", filePath->s);
bpc_attrib_dirRefCountInodeMax(deltaInfo, &dir, incr, inodeMax);
}
bpc_attrib_dirDestroy(&dir);
}
}
}
closedir(dir);
/*
* Now visit the subdirs we have saved above.
*/
if ( dirListLen > 0 ) {
char *dirListP;
for ( dirListP = dirList->s ; dirListP < dirList->s + dirListLen ; dirListP += strlen(dirListP) + 1 ) {
bpc_strBuf_snprintf(filePath, 0, "%s/%s", path, dirListP);
errorCnt += bpc_path_refCountAllInodeMax(deltaInfo, filePath->s, compress, incr, inodeMax);
}
}
bpc_strBuf_free(filePath);
bpc_strBuf_free(dirList);
return errorCnt;
}
/*
* Reference count all the files below the directory path, based on the attrib
* files in and below path.
*/
int bpc_path_refCountAll(bpc_deltaCount_info *deltaInfo, char *path, int compress, int incr)
{
return bpc_path_refCountAllInodeMax(deltaInfo, path, compress, incr, NULL);
}
/*
* Add an exclusive lock to the byte range in the given file.
* Blocks until the lock becomes available.
*/
int bpc_lockRangeFd(int fd, OFF_T offset, OFF_T len, int block)
{
struct flock lock;
lock.l_type = F_WRLCK;
lock.l_whence = SEEK_SET;
lock.l_start = offset;
lock.l_len = len;
lock.l_pid = 0;
return fcntl(fd, block ? F_SETLKW : F_SETLK, &lock);
}
int bpc_unlockRangeFd(int fd, OFF_T offset, OFF_T len)
{
struct flock lock;
lock.l_type = F_UNLCK;
lock.l_whence = SEEK_SET;
lock.l_start = offset;
lock.l_len = len;
lock.l_pid = 0;
return fcntl(fd, F_SETLK, &lock);
}
int bpc_lockRangeFile(char *lockFile, OFF_T offset, OFF_T len, int block)
{
int fd;
if ( (fd = open(lockFile, O_CREAT | O_RDWR, 0660)) < 0 ) {
bpc_logErrf("bpc_lockRangeFile: can't open/create lock file %s\n", lockFile);
return fd;
}
if ( bpc_lockRangeFd(fd, offset, len, block) ) {
close(fd);
if ( block ) {
bpc_logErrf("bpc_lockRangeFile: lock(%s) failed (errno = %d)\n", lockFile, errno);
}
return -1;
}
return fd;
}
void bpc_unlockRangeFile(int lockFd)
{
if ( lockFd >= 0 ) close(lockFd);
}
rsync-bpc-3.1.3.0/backuppc/bpc_fileDigest.c 0000664 0000000 0000000 00000002720 13737671777 0020445 0 ustar 00root root 0000000 0000000 /*
* Library routines
*
* Copyright (C) 2020 Craig Barratt.
*
* 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 "backuppc.h"
/*
* Compute the md5 digest of a file. Returns 0 on success
*/
int bpc_fileDigest(char *fileName, int compress, bpc_digest *digest)
{
md_context md5;
bpc_fileZIO_fd fd;
ssize_t nRead;
uchar buffer[1 << 20];
digest->len = 0;
md5_begin(&md5);
if ( bpc_fileZIO_open(&fd, fileName, 0, compress) ) {
bpc_logErrf("bpc_fileDigest: can't open %s for reading\n", fileName);
return -1;
}
while ( (nRead = bpc_fileZIO_read(&fd, buffer, sizeof(buffer))) > 0 ) {
md5_update(&md5, buffer, nRead);
}
bpc_fileZIO_close(&fd);
if ( nRead < 0 ) {
bpc_logErrf("bpc_fileDigest: failed to read %s\n", fileName);
return -1;
}
md5_result(&md5, digest->digest);
digest->len = MD5_DIGEST_LEN;
return 0;
}
rsync-bpc-3.1.3.0/backuppc/bpc_fileZIO.c 0000664 0000000 0000000 00000040104 13737671777 0017665 0 ustar 00root root 0000000 0000000 /*
* Routines for reading and writing compressed files using zlib
*
* Copyright (C) 2013 Craig Barratt.
*
* 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 "backuppc.h"
/*
* A freelist of unused data buffers.
* We use the first sizeof(void*) bytes of the buffer as a single-linked
* list, with a NULL at the end.
*/
static void *DataBufferFreeList = (void*)NULL;
/*
* Open a regular or compressed file for reading or writing/create
*/
int bpc_fileZIO_open(bpc_fileZIO_fd *fd, char *fileName, int writeFile, int compressLevel)
{
fd->strm.next_out = NULL;
fd->strm.zalloc = NULL;
fd->strm.zfree = NULL;
fd->strm.opaque = NULL;
fd->compressLevel = compressLevel;
fd->first = 1;
fd->write = writeFile;
fd->eof = 0;
fd->error = 0;
fd->writeTeeStderr = 0;
fd->lineBuf = NULL;
fd->lineBufSize = 0;
fd->lineBufLen = 0;
fd->lineBufIdx = 0;
fd->lineBufEof = 0;
fd->bufSize = 1 << 20; /* 1MB */
if ( writeFile ) {
fd->fd = open(fileName, O_WRONLY | O_CREAT | O_TRUNC, 0660);
if ( fd->fd < 0 ) {
/*
* try removing first
*/
unlink(fileName);
fd->fd = open(fileName, O_WRONLY | O_CREAT | O_TRUNC, 0660);
}
if ( fd->fd < 0 ) return -1;
if ( fd->compressLevel ) {
if (deflateInit2(&fd->strm, compressLevel, Z_DEFLATED, MAX_WBITS, 8,
Z_DEFAULT_STRATEGY) != Z_OK) {
bpc_logErrf("bpc_fileZIO_open: compression init failed\n");
return -1;
}
fd->strm.next_out = (Bytef*)fd->buf;
fd->strm.avail_out = fd->bufSize;
}
} else {
fd->fd = open(fileName, O_RDONLY);
if ( fd->fd < 0 ) return -1;
if ( fd->compressLevel ) {
if ( inflateInit(&fd->strm) != Z_OK ) {
bpc_logErrf("bpc_fileZIO_open: compression init failed\n");
return -1;
}
fd->strm.avail_in = 0;
}
}
if ( DataBufferFreeList ) {
fd->buf = DataBufferFreeList;
DataBufferFreeList = *(void**)DataBufferFreeList;
} else {
fd->buf = malloc(fd->bufSize);
}
if ( !fd->buf ) {
bpc_logErrf("bpc_fileZIO_open: fatal error: can't allocate %u bytes\n", (unsigned)fd->bufSize);
return -1;
}
if ( BPC_LogLevel >= 8 ) bpc_logMsgf("bpc_fileZIO_open(%s, %d, %d) -> %d\n", fileName, writeFile, compressLevel, fd->fd);
return 0;
}
/*
* Open an existing FILE stream for reading/writing.
* Note: we used unbuffered integer fds here, and we simply grab the underlying integer fd. That will
* mess up the FILE stream buffering if anything has been read/written from/to the FILE.
*
* This function is only used to support the legacy BackupPC::FileZIO feature that allows you to
* pass STDIN in as an argument to open().
*/
int bpc_fileZIO_fdopen(bpc_fileZIO_fd *fd, FILE *stream, int writeFile, int compressLevel)
{
fd->strm.next_out = NULL;
fd->strm.zalloc = NULL;
fd->strm.zfree = NULL;
fd->strm.opaque = NULL;
fd->compressLevel = compressLevel;
fd->first = 1;
fd->write = writeFile;
fd->eof = 0;
fd->error = 0;
fd->writeTeeStderr = 0;
fd->lineBuf = NULL;
fd->lineBufSize = 0;
fd->lineBufLen = 0;
fd->lineBufIdx = 0;
fd->lineBufEof = 0;
fd->fd = fileno(stream);
if ( fd->fd < 0 ) return -1;
fd->bufSize = 1 << 20; /* 1MB */
if ( !(fd->buf = malloc(fd->bufSize)) ) {
bpc_logErrf("bpc_fileZIO_fdopen: can't allocate %u bytes\n", (unsigned)fd->bufSize);
return -1;
}
if ( fd->compressLevel ) {
if ( writeFile ) {
if (deflateInit2(&fd->strm, compressLevel, Z_DEFLATED, MAX_WBITS, 8,
Z_DEFAULT_STRATEGY) != Z_OK) {
bpc_logErrf("bpc_fileZIO_open: compression init failed\n");
return -1;
}
fd->strm.next_out = (Bytef*)fd->buf;
fd->strm.avail_out = fd->bufSize;
} else {
if ( inflateInit(&fd->strm) != Z_OK ) {
bpc_logErrf("bpc_fileZIO_open: compression init failed\n");
return -1;
}
fd->strm.avail_in = 0;
}
}
if ( BPC_LogLevel >= 8 ) bpc_logMsgf("bpc_fileZIO_fdopen(%d, %d) -> %d\n", writeFile, compressLevel, fd->fd);
return 0;
}
void bpc_fileZIO_writeTeeStderr(bpc_fileZIO_fd *fd, int tee)
{
fd->writeTeeStderr = tee;
}
/*
* Read from a compressed or regular file.
*/
ssize_t bpc_fileZIO_read(bpc_fileZIO_fd *fd, uchar *buf, size_t nRead)
{
size_t totalRead = 0;
if ( fd->write || fd->fd < 0 ) return -1;
if ( fd->compressLevel == 0 ) {
ssize_t thisRead;
while ( nRead > 0 ) {
do {
thisRead = read(fd->fd, buf, nRead);
} while ( thisRead < 0 && errno == EINTR );
if ( thisRead < 0 ) return thisRead;
if ( thisRead == 0 ) return totalRead;
buf += thisRead;
nRead -= thisRead;
totalRead += thisRead;
}
return totalRead;
}
if ( fd->error ) return fd->error;
while ( nRead > 0 ) {
/*
* Start by trying to read more of the compressed input file
*/
int maxRead, thisRead = -1;
if ( fd->strm.avail_in == 0 ) {
fd->strm.next_in = (Bytef*)fd->buf;
}
maxRead = fd->bufSize - ((fd->strm.next_in - (Bytef*)fd->buf) + fd->strm.avail_in);
if ( !fd->eof && maxRead > 0 ) {
do {
thisRead = read(fd->fd, fd->strm.next_in + fd->strm.avail_in, maxRead);
} while ( thisRead < 0 && errno == EINTR );
if ( thisRead < 0 ) {
fd->error = thisRead;
return fd->error;
}
fd->strm.avail_in += thisRead;
if ( thisRead == 0 ) {
fd->eof = 1;
}
}
while ( nRead > 0 ) {
int status, numOut;
fd->strm.next_out = (Bytef*)buf;
fd->strm.avail_out = nRead;
if ( fd->first && fd->strm.avail_in > 0 ) {
/*
* we are at the very start of a new zlib block (or it could be cached checksums)
*/
fd->first = 0;
if ( fd->strm.next_in[0] == 0xd6 || fd->strm.next_in[0] == 0xd7 ) {
/*
* Flag 0xd6 or 0xd7 means this is a compressed file with
* appended md4 block checksums for rsync. Change
* the first byte back to 0x78 and proceed.
*/
fd->strm.next_in[0] = 0x78;
} else if ( fd->strm.next_in[0] == 0xb3 ) {
/*
* Flag 0xb3 means this is the start of the rsync
* block checksums, so consider this as EOF for
* the compressed file. Also seek the file so
* it is positioned at the 0xb3.
*/
fd->eof = 1;
/* TODO: check return status */
lseek(fd->fd, -fd->strm.avail_in, SEEK_CUR);
fd->strm.avail_in = 0;
}
}
status = inflate(&fd->strm, fd->eof ? Z_SYNC_FLUSH : Z_NO_FLUSH);
numOut = fd->strm.next_out - (Bytef*)buf;
nRead -= numOut;
buf += numOut;
totalRead += numOut;
if ( BPC_LogLevel >= 10 ) bpc_logMsgf("inflate returns %d; thisRead = %d, avail_in = %d, numOut = %d\n", status, thisRead, fd->strm.avail_in, numOut);
if ( fd->eof && fd->strm.avail_in == 0 && numOut == 0 ) return totalRead;
if ( status == Z_OK && fd->strm.avail_in == 0 ) break;
if ( status == Z_BUF_ERROR && fd->strm.avail_in == 0 && numOut == 0 ) break;
if ( status == Z_STREAM_END ) {
inflateReset(&fd->strm);
fd->first = 1;
}
if ( status < 0 ) {
/*
* return error immediately if there are no bytes to return
*/
if ( totalRead <= 0 ) return status;
/*
* save error return for next call and return remaining buffer
*/
fd->error = status;
return totalRead;
}
}
}
return totalRead;
}
/*
* Write to a compressed or regular file.
* Write flush and eof is indicated with nWrite == 0.
*/
ssize_t bpc_fileZIO_write(bpc_fileZIO_fd *fd, uchar *buf, size_t nWrite)
{
if ( !fd->write || fd->fd < 0 ) return -1;
if ( fd->eof ) return 0;
if ( fd->writeTeeStderr && nWrite > 0 ) (void)fwrite((char*)buf, nWrite, 1, stderr);
if ( fd->compressLevel == 0 ) {
int thisWrite, totalWrite = 0;
while ( nWrite > 0 ) {
do {
thisWrite = write(fd->fd, buf, nWrite);
} while ( thisWrite < 0 && errno == EINTR );
if ( thisWrite < 0 ) return thisWrite;
buf += thisWrite;
nWrite -= thisWrite;
totalWrite += thisWrite;
}
return totalWrite;
}
if ( fd->error ) return fd->error;
if ( nWrite == 0 || (fd->strm.total_in > (1 << 23) && fd->strm.total_out < (1 << 18)) ) {
/*
* final or intermediate flush (if the compression ratio is too high, since the
* perl Compress::Zlib implementation allocates the output buffer for inflate
* and it could grow to be very large).
*/
if ( BPC_LogLevel >= 10 ) bpc_logMsgf("Flushing (nWrite = %d)\n", nWrite);
while ( 1 ) {
int status, numOut, thisWrite;
char *writePtr = fd->buf;
fd->strm.next_in = NULL;
fd->strm.avail_in = 0;
fd->strm.next_out = (Bytef*)fd->buf;
fd->strm.avail_out = fd->bufSize;
status = deflate(&fd->strm, Z_FINISH);
numOut = fd->strm.next_out - (Bytef*)fd->buf;
while ( numOut > 0 ) {
do {
thisWrite = write(fd->fd, writePtr, numOut);
} while ( thisWrite < 0 && errno == EINTR );
if ( thisWrite < 0 ) return thisWrite;
numOut -= thisWrite;
writePtr += thisWrite;
}
if ( status != Z_OK ) break;
}
deflateReset(&fd->strm);
}
if ( nWrite == 0 ) {
fd->eof = 1;
return nWrite;
}
fd->strm.next_in = (Bytef*)buf;
fd->strm.avail_in = nWrite;
while ( fd->strm.avail_in > 0 ) {
int numOut, thisWrite;
char *writePtr = fd->buf;
fd->strm.next_out = (Bytef*)fd->buf;
fd->strm.avail_out = fd->bufSize;
deflate(&fd->strm, Z_NO_FLUSH);
numOut = fd->strm.next_out - (Bytef*)fd->buf;
while ( numOut > 0 ) {
do {
thisWrite = write(fd->fd, writePtr, numOut);
} while ( thisWrite < 0 && errno == EINTR );
if ( thisWrite < 0 ) return thisWrite;
numOut -= thisWrite;
writePtr += thisWrite;
}
}
return nWrite;
}
int bpc_fileZIO_close(bpc_fileZIO_fd *fd)
{
if ( fd->fd < 0 ) return -1;
if ( fd->compressLevel ) {
if ( fd->write ) {
/*
* Flush the output file
*/
bpc_fileZIO_write(fd, NULL, 0);
deflateEnd(&fd->strm);
} else {
inflateEnd(&fd->strm);
}
}
if ( BPC_LogLevel >= 8 ) bpc_logMsgf("bpc_fileZIO_close(%d)\n", fd->fd);
close(fd->fd);
if ( fd->lineBuf ) free(fd->lineBuf);
fd->lineBuf = NULL;
if ( fd->buf ) {
*(void**)fd->buf = DataBufferFreeList;
DataBufferFreeList = fd->buf;
fd->buf = NULL;
}
fd->fd = -1;
return 0;
}
int bpc_fileZIO_rewind(bpc_fileZIO_fd *fd)
{
if ( fd->write ) return -1;
if ( fd->compressLevel ) {
inflateReset(&fd->strm);
fd->first = 1;
fd->eof = 0;
fd->error = 0;
fd->strm.avail_in = 0;
}
return lseek(fd->fd, 0, SEEK_SET) == 0 ? 0 : -1;
}
/*
* Returns \n terminated lines, one at a time, from the opened read stream.
* The returned string is not '\0' terminated. At EOF sets *str = NULL;
*/
int bpc_fileZIO_readLine(bpc_fileZIO_fd *fd, char **str, size_t *strLen)
{
if ( !fd->lineBuf ) {
/*
* allocate initial read buffer
*/
fd->lineBufSize = 65536;
if ( !(fd->lineBuf = malloc(fd->lineBufSize)) ) {
bpc_logErrf("bpc_fileZIO_readLine: can't allocate %u bytes\n", (unsigned)fd->lineBufSize);
return -1;
}
fd->lineBufLen = 0;
fd->lineBufIdx = 0;
fd->lineBufEof = 0;
}
while ( 1 ) {
char *p;
if ( fd->lineBufIdx < fd->lineBufLen ) {
if ( (p = memchr(fd->lineBuf + fd->lineBufIdx, '\n', fd->lineBufLen - fd->lineBufIdx)) ) {
/*
* found next complete line
*/
p++;
*str = fd->lineBuf + fd->lineBufIdx;
*strLen = p - (fd->lineBuf + fd->lineBufIdx);
fd->lineBufIdx += p - (fd->lineBuf + fd->lineBufIdx);
return 0;
} else if ( fd->lineBufEof ) {
/*
* return last string - not \n terminated
*/
*str = fd->lineBuf + fd->lineBufIdx;
*strLen = fd->lineBufLen - fd->lineBufIdx;
fd->lineBufIdx += fd->lineBufLen - fd->lineBufIdx;
return 0;
} else if ( fd->lineBufLen >= fd->lineBufSize ) {
/*
* No complete lines left, and buffer is full. Either move the unused buffer down to make
* more room for reading, or make the buffer bigger.
*/
if ( fd->lineBufIdx > 0 ) {
memmove(fd->lineBuf, fd->lineBuf + fd->lineBufIdx, fd->lineBufLen - fd->lineBufIdx);
fd->lineBufLen -= fd->lineBufIdx;
fd->lineBufIdx = 0;
} else {
fd->lineBufSize *= 2;
if ( !(fd->lineBuf = realloc(fd->lineBuf, fd->lineBufSize)) ) {
bpc_logErrf("bpc_fileZIO_readLine: can't reallocate %u bytes\n", (unsigned)fd->lineBufSize);
return -1;
}
}
}
}
if ( fd->lineBufIdx >= fd->lineBufLen && fd->lineBufEof ) {
/*
* at EOF
*/
*str = NULL;
*strLen = 0;
return 0;
}
if ( fd->lineBufIdx >= fd->lineBufLen ) {
fd->lineBufLen = 0;
fd->lineBufIdx = 0;
}
if ( fd->lineBufLen < fd->lineBufSize && !fd->lineBufEof ) {
int nread = bpc_fileZIO_read(fd, (uchar*)fd->lineBuf + fd->lineBufLen, fd->lineBufSize - fd->lineBufLen);
if ( nread < 0 ) {
bpc_logErrf("bpc_fileZIO_readLine: reading %u returned %d\n", (unsigned)(fd->lineBufSize - fd->lineBufLen), nread);
return nread;
}
if ( nread == 0 ) fd->lineBufEof = 1;
fd->lineBufLen += nread;
}
}
}
rsync-bpc-3.1.3.0/backuppc/bpc_hashtable.c 0000664 0000000 0000000 00000034221 13737671777 0020322 0 ustar 00root root 0000000 0000000 /*
* Routines to provide a memory-efficient hashtable.
*
* Copyright (C) 2007-2009 Wayne Davison
*
* Modified for BackupPC to use arbitrary-length binary keys, and supporting
* a rudimentary delete feature by Craig Barratt. In 6/2016 rewrote to
* make the storage an array of pointers to entries, instead of inplace.
* That way entries fetched from the hashtable are still value after a
* resize. Still no chaining.
*
* 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 "backuppc.h"
/*
* Simple freelist of hash table entries. We maintain a single linked list of
* unused entries of each size, indexed by the FREELIST_SIZE2IDX() macro.
*
* FreeList[0] isn't used,
* FreeList[1] is a free list of blocks of size 8,
* FreeList[2] is a free list of blocks of size 16, ...
*
* eg, if you ask for a block of size 9, a block of size 16 will be returned.
*/
static bpc_hashtable_key **FreeList;
static uint32 FreeListSz;
/*
* to map size to the FreeList index we round up to the nearest multiple of 8
*/
#define FREELIST_SIZE2IDX(size) (((size) + 7) / 8)
#define FREELIST_IDX2SIZE(idx) ((idx) * 8)
/*
* how many new blocks to allocate when the free list is empty
*/
#define FREELIST_ALLOC_CNT (512)
/*
* allocate a single block of a given size by grabbing one off the FreeList
*/
static bpc_hashtable_key *bpc_hashtable_entryAlloc(uint32 size)
{
uint32 freeListIdx = FREELIST_SIZE2IDX(size);
bpc_hashtable_key *key;
size = FREELIST_IDX2SIZE(freeListIdx);
if ( freeListIdx >= FreeListSz ) {
/*
* need a bigger array of freelists
*/
if ( !(FreeList = (bpc_hashtable_key**)realloc(FreeList, 2 * freeListIdx * sizeof(bpc_hashtable_key*))) ) {
bpc_logErrf("bpc_hashtable_entryAlloc: out of memory\n");
return NULL;
}
memset(FreeList + FreeListSz, 0, (2 * freeListIdx - FreeListSz) * sizeof(bpc_hashtable_key*));
FreeListSz = 2 * freeListIdx;
}
if ( !FreeList[freeListIdx] ) {
char *newBuf;
uint32 i;
/*
* need to populate the freelist with more blocks
*/
if ( !(newBuf = (char*)malloc(size * FREELIST_ALLOC_CNT)) ) {
bpc_logErrf("bpc_hashtable_entryAlloc: out of memory\n");
return NULL;
}
FreeList[freeListIdx] = (bpc_hashtable_key*)newBuf;
/*
* chain all the buffers together in a linked list
*/
key = (bpc_hashtable_key*)newBuf;
for ( i = 0 ; i < FREELIST_ALLOC_CNT - 1 ; i++ ) {
key->key = (void*)key + size;
key = key->key;
}
key->key = NULL;
}
key = FreeList[freeListIdx];
FreeList[freeListIdx] = key->key;
memset(key, 0, size);
return key;
}
/*
* free a block of a given size by putting it back on the FreeList
*/
static void bpc_hashtable_entryFree(bpc_hashtable_key *key, uint32 size)
{
uint32 freeListIdx = FREELIST_SIZE2IDX(size);
key->key = FreeList[freeListIdx];
FreeList[freeListIdx] = key;
}
#define HASH_LOAD_LIMIT(size) ((size)*3/4)
/*
* This implements a very simple linear hash table (no chaining etc).
*
* It has rudimentary support for delete, by flagging the deleted node. It doesn't
* shift other nodes on delete, but can re-use a deleted node on insert.
*/
/*
* Create a hash table of the initial given size, with entries of size nodeSize
*/
void bpc_hashtable_create(bpc_hashtable *tbl, uint32 size, uint32 nodeSize)
{
/* Pick a power of 2 that can hold the requested size. */
if ( (size & (size-1)) || size < 16 ) {
uint32 req = size;
size = 16;
while ( size < req ) {
size *= 2;
}
}
if ( !(tbl->nodes = calloc(size, sizeof(tbl->nodes[0]))) ) {
bpc_logErrf("bpc_hashtable_create: out of memory\n");
return;
}
tbl->size = size;
tbl->entries = 0;
tbl->entriesDel = 0;
tbl->nodeSize = nodeSize;
return;
}
void bpc_hashtable_destroy(bpc_hashtable *tbl)
{
uint32 i;
for ( i = 0 ; i < tbl->size ; i++ ) {
if ( tbl->nodes[i] ) {
bpc_hashtable_entryFree(tbl->nodes[i], tbl->nodeSize);
}
}
free(tbl->nodes);
}
void bpc_hashtable_erase(bpc_hashtable *tbl)
{
uint32 i;
for ( i = 0 ; i < tbl->size ; i++ ) {
if ( tbl->nodes[i] ) {
bpc_hashtable_entryFree(tbl->nodes[i], tbl->nodeSize);
}
}
memset(tbl->nodes, 0, tbl->size * sizeof(tbl->nodes[0]));
tbl->entries = 0;
tbl->entriesDel = 0;
}
/*
* Compute a hash for a given key. Note that it is *not* modulo the table size - the returned
* hash is independent of the table size, so we don't have to recompute this hash if we
* resize the table. However, the current implementation does recompute the hash when
* we resize the hash table :(. Oh well.
*/
uint32 bpc_hashtable_hash(uchar *key, uint32 keyLen)
{
/* Based on Jenkins One-at-a-time hash. */
uint32 ndx;
for ( ndx = 0 ; keyLen > 0 ; keyLen-- ) {
ndx += *key++;
ndx += (ndx << 10);
ndx ^= (ndx >> 6);
}
ndx += (ndx << 3);
ndx ^= (ndx >> 11);
ndx += (ndx << 15);
return ndx;
}
#if 0
static void bpc_hashttable_check(bpc_hashtable *tbl, char *str)
{
bpc_hashtable_key **node = tbl->nodes;
uint i, entries = 0, entriesDel = 0;
for ( i = 0 ; i < tbl->size ; i++, node++ ) {
bpc_hashtable_key *keyInfo = *node;
if ( !keyInfo ) {
continue;
}
if ( !keyInfo->key && keyInfo->keyLen == 1 ) {
entriesDel++;
} else {
entries++;
}
}
if ( entries != tbl->entries ) {
bpc_logErrf("bpc_hashttable_check: botch at %s on HT (%u,%u): got %u entries vs %u expected\n",
str, tbl->size, tbl->nodeSize, entries, tbl->entries);
tbl->entries = entries;
}
if ( entriesDel != tbl->entriesDel ) {
bpc_logErrf("bpc_hashttable_check: botch at %s on HT (%u,%u): got %u entriesDel vs %u expected\n",
str, tbl->size, tbl->nodeSize, entriesDel, tbl->entriesDel);
tbl->entriesDel = entriesDel;
}
}
#endif
/*
* Ensure the hash table is of size at least newSize
*/
void bpc_hashtable_growSize(bpc_hashtable *tbl, uint32 newSize)
{
bpc_hashtable_key **old_nodes = tbl->nodes;
bpc_hashtable_key **old_node = tbl->nodes;
uint32 oldSize = tbl->size;
uint i, j, ndx;
/* Pick a power of 2 that can hold the requested newSize. */
if ( (newSize & (newSize-1)) || newSize < 16 ) {
uint32 req = newSize;
newSize = 16;
while ( newSize < req ) {
newSize *= 2;
}
}
if ( tbl->size >= newSize ) return;
if ( !(tbl->nodes = (bpc_hashtable_key**)calloc(newSize, sizeof(tbl->nodes[0]))) ) {
bpc_logErrf("bpc_hashtable_create: out of memory\n");
return;
}
tbl->entries = 0;
tbl->entriesDel = 0;
tbl->size = newSize;
for ( i = 0 ; i < oldSize ; i++, old_node++ ) {
bpc_hashtable_key *keyInfo = *old_node;
/* empty slot */
if ( !keyInfo ) continue;
/* deleted slot: free it and don't reinsert */
if ( !keyInfo->key && keyInfo->keyLen == 1 ) {
bpc_hashtable_entryFree(keyInfo, tbl->nodeSize);
continue;
}
ndx = keyInfo->keyHash & (tbl->size - 1);
for ( j = 0 ; j < tbl->size ; j++, ndx++ ) {
if ( ndx >= tbl->size ) ndx = 0;
if ( tbl->nodes[ndx] ) continue;
tbl->nodes[ndx] = keyInfo;
tbl->entries++;
break;
}
if ( j >= tbl->size ) {
bpc_logErrf("bpc_hashtable_growSize: botch on filling new hashtable (%d,%d)\n", newSize, tbl->entries);
return;
}
}
free(old_nodes);
}
/*
* This returns the node for the indicated key, either newly created or
* already existing. Returns NULL if not allocating and not found.
*/
void *bpc_hashtable_find(bpc_hashtable *tbl, unsigned char *key, unsigned int keyLen, int allocate_if_missing)
{
bpc_hashtable_key *keyInfo, *keyDeleted = NULL;
uint32 i, ndx, keyHash;
if ( allocate_if_missing && tbl->entries + tbl->entriesDel > HASH_LOAD_LIMIT(tbl->size) ) {
bpc_hashtable_growSize(tbl, tbl->size * 2);
}
/* bpc_hashttable_check(tbl, "find"); */
/*
* If it already exists, return the node. If we're not
* allocating, return NULL if the key is not found.
*/
ndx = keyHash = bpc_hashtable_hash(key, keyLen);
ndx &= tbl->size - 1;
for ( i = 0 ; i < tbl->size ; i++ ) {
keyInfo = tbl->nodes[ndx];
if ( !keyInfo ) {
/*
* Not found since we hit an empty node (ie: not a deleted one)
* If requested, place the new at a prior deleted node, or here
*/
if ( allocate_if_missing ) {
tbl->entries++;
if ( keyDeleted ) {
/*
* we found a prior deleted entry, so use it instead
*/
keyInfo = keyDeleted;
tbl->entriesDel--;
} else {
tbl->nodes[ndx] = keyInfo = bpc_hashtable_entryAlloc(tbl->nodeSize);
}
keyInfo->key = key;
keyInfo->keyLen = keyLen;
keyInfo->keyHash = keyHash;
/* TODO - check this? */
if ( !key ) {
bpc_logErrf("bpc_hashtable_find: botch adding NULL key to hT (%d,%d)\n", tbl->size, tbl->nodeSize);
}
return (void*)keyInfo;
}
return (void*)NULL;
} else {
if ( !keyInfo->key && keyInfo->keyLen == 1 ) {
if ( !keyDeleted ) {
/*
* this is the first deleted slot, which we remember so we can insert a new entry
* here if we don't find the desired entry, and allocate_if_missing != 0
*/
keyDeleted = keyInfo;
}
} else if ( keyInfo->keyHash == keyHash && keyInfo->keyLen == keyLen && !memcmp(key, keyInfo->key, keyLen) ) {
return (void*)keyInfo;
}
}
ndx++;
if ( ndx >= tbl->size ) ndx = 0;
}
return (void*)NULL;
}
/*
* Remove a node from the hash table. Node must be a valid node returned by bpc_hashtable_find!
* Node gets cleared.
*/
void bpc_hashtable_nodeDelete(bpc_hashtable *tbl, void *node)
{
bpc_hashtable_key *keyInfo = (bpc_hashtable_key*)node;
memset(node, 0, tbl->nodeSize);
/*
* special delete flag (key is NULL, keyLen is 1), so that the linear hash table continues
* finding entries past this point.
* TODO optimization: if the next entry is empty, then we can make this empty too.
*/
keyInfo->keyLen = 1;
tbl->entries--;
tbl->entriesDel++;
/* bpc_hashttable_check(tbl, "delete"); */
}
/*
* Iterate over all the entries in the hash table, calling a callback for each valid entry
*
* Note: this function won't work if the callback adds new entries to the hash table while
* iterating over the entries. You can update or delete entries, but adding an entry might
* cause the * hash table size to be bumped, which breaks the indexing. So don't add new
* entries while iterating over the table.
*/
void bpc_hashtable_iterate(bpc_hashtable *tbl, void (*callback)(void*, void*), void *arg1)
{
uint i, entries = 0, entriesDel = 0;
/* bpc_hashttable_check(tbl, "iterate"); */
for ( i = 0 ; i < tbl->size ; i++ ) {
bpc_hashtable_key *keyInfo = tbl->nodes[i];
if ( !keyInfo ) continue;
if ( !keyInfo->key ) {
if ( keyInfo->keyLen == 1 ) entriesDel++;
continue;
}
(*callback)((void*)keyInfo, arg1);
if ( !keyInfo->key ) {
if ( keyInfo->keyLen == 1 ) entriesDel++;
continue;
} else {
entries++;
}
}
if ( entries != tbl->entries ) {
bpc_logErrf("bpc_hashtable_iterate: botch on HT (%u,%u): got %u entries vs %u expected\n",
tbl->size, tbl->nodeSize, entries, tbl->entries);
tbl->entries = entries;
}
if ( entriesDel != tbl->entriesDel ) {
bpc_logErrf("bpc_hashtable_iterate: botch on HT (%u,%u): got %u entriesDel vs %u expected\n",
tbl->size, tbl->nodeSize, entriesDel, tbl->entriesDel);
tbl->entriesDel = entriesDel;
}
}
/*
* An alternative way to iterate over all the hash table entries. Initially index should
* be zero, and is updated on each call. A pointer to each entry is returned. After
* the last entry, NULL is returned, and idx is set back to zero.
*
* Note: this function won't work if you add new entries to the hash table while iterating
* over the entries. You can update or delete entries, but adding an entry might cause the
* hash table size to be bumped, which breaks the indexing. So don't add new entries while
* iterating over the table.
*/
void *bpc_hashtable_nextEntry(bpc_hashtable *tbl, uint *idx)
{
uint i = *idx;
/* bpc_hashttable_check(tbl, "next entry"); */
for ( ; i < (uint)tbl->size ; i++ ) {
bpc_hashtable_key *keyInfo = tbl->nodes[i];
if ( !keyInfo || !keyInfo->key ) continue;
*idx = i + 1;
return (void*)keyInfo;
}
*idx = 0;
return NULL;
}
/*
* Return the number of entries in the hash table
*/
int bpc_hashtable_entryCount(bpc_hashtable *tbl)
{
/* bpc_hashttable_check(tbl, "entryCount"); */
return tbl->entries;
}
rsync-bpc-3.1.3.0/backuppc/bpc_lib.c 0000664 0000000 0000000 00000032325 13737671777 0017140 0 ustar 00root root 0000000 0000000 /*
* Library routines
*
* Copyright (C) 2013 Craig Barratt.
*
* 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 "backuppc.h"
bpc_strBuf BPC_TopDir;
bpc_strBuf BPC_PoolDir;
bpc_strBuf BPC_CPoolDir;
bpc_strBuf BPC_PoolDir3;
bpc_strBuf BPC_CPoolDir3;
int BPC_HardLinkMax = 32000;
int BPC_PoolV3Enabled = 0;
int BPC_TmpFileUnique = -1;
int BPC_LogLevel = 0;
static char *hexDigits = "0123456789abcdef";
void bpc_lib_conf_init(char *topDir, int hardLinkMax, int poolV3Enabled, int logLevel)
{
if ( logLevel >= 8 ) bpc_logMsgf("bpc_lib_conf_init: topDir = %s, logLevel = %d\n", topDir, logLevel);
bpc_strBuf_snprintf(&BPC_TopDir, 0, "%s", topDir);
bpc_strBuf_snprintf(&BPC_CPoolDir, 0, "%s/%s", BPC_TopDir.s, "cpool");
bpc_strBuf_snprintf(&BPC_CPoolDir3, 0, "%s/%s", BPC_TopDir.s, "cpool");
bpc_strBuf_snprintf(&BPC_PoolDir, 0, "%s/%s", BPC_TopDir.s, "pool");
bpc_strBuf_snprintf(&BPC_PoolDir3, 0, "%s/%s", BPC_TopDir.s, "pool");
BPC_HardLinkMax = hardLinkMax;
BPC_PoolV3Enabled = poolV3Enabled;
BPC_LogLevel = logLevel;
}
void bpc_lib_setTmpFileUnique(int val)
{
BPC_TmpFileUnique = val;
}
int bpc_lib_setLogLevel(int logLevel)
{
if ( logLevel >= 0 ) {
BPC_LogLevel = logLevel;
}
return BPC_LogLevel;
}
/*
* Converts a byte to two ascii hex digits at outStr[0] and outStr[1].
* Nothing is written at outStr[2]; ie: no NULL termination
*/
void bpc_byte2hex(char *outStr, int byte)
{
outStr[0] = hexDigits[(byte >> 4) & 0xf];
outStr[1] = hexDigits[(byte >> 0) & 0xf];
}
static uchar bpc_hexChar2nibble(char c)
{
if ( '0' <= c && c <= '9' ) return c - '0';
if ( 'A' <= c && c <= 'F' ) return 0xa + (c - 'A');
if ( 'a' <= c && c <= 'f' ) return 0xa + (c - 'a');
return 0;
}
uchar bpc_hexStr2byte(char c1, char c2)
{
return (bpc_hexChar2nibble(c1) << 4) | bpc_hexChar2nibble(c2);
}
void bpc_digest_buffer2MD5(bpc_digest *digest, uchar *buffer, size_t bufferLen)
{
md_context md5;
md5_begin(&md5);
md5_update(&md5, buffer, bufferLen);
md5_result(&md5, digest->digest);
digest->len = MD5_DIGEST_LEN;
}
void bpc_digest_append_ext(bpc_digest *digest, uint32 ext)
{
int i;
digest->len = 16;
if ( ext == 0 ) return;
for ( i = 24 ; i >= 0 ; i -= 8 ) {
if ( ext >= (1U << i) ) {
digest->digest[digest->len++] = (ext >> i) & 0xff;
}
}
}
/*
* returns 0 if the two digests are equal, non-zero if they are not
*/
int bpc_digest_compare(bpc_digest *digest1, bpc_digest *digest2)
{
if ( digest1->len != digest2->len ) return digest1->len - digest2->len;
return memcmp(digest1->digest, digest2->digest, digest1->len);
}
void bpc_digest_digest2str(bpc_digest *digest, char *hexStr)
{
int i;
char *out = hexStr;
for ( i = 0 ; i < digest->len ; i++ ) {
bpc_byte2hex(out, digest->digest[i]);
out += 2;
}
*out = '\0';
}
void bpc_digest_str2digest(bpc_digest *digest, char *hexStr)
{
for ( digest->len = 0 ; hexStr[0] && hexStr[1] && digest->len < BPC_DIGEST_LEN_MAX ; hexStr += 2 ) {
digest->digest[digest->len++] = bpc_hexStr2byte(hexStr[0], hexStr[1]);
}
}
void bpc_digest_md52path(bpc_strBuf *path, int compress, bpc_digest *digest)
{
char *out;
size_t len;
/*
* MD5 digest of an empty file (ie, md5sum /dev/null)
*/
static uchar emptyFileMD5[] = {
0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e
};
#if 0
/*
* Test code to create collisions in pool files.
* If you turn on this test, you should also force the zeroLenMD5
* digest comparison in bpc_poolWrite_write() to true.
*/
bpc_digest fixedDigest = *digest;
digest = &fixedDigest;
memcpy(digest->digest, emptyFileMD5, sizeof(emptyFileMD5));
#endif
if ( digest->len == sizeof(emptyFileMD5) && !memcmp(digest->digest, emptyFileMD5, sizeof(emptyFileMD5)) ) {
bpc_strBuf_strcpy(path, 0, "/dev/null");
return;
}
bpc_strBuf_strcpy(path, 0, compress ? BPC_CPoolDir.s : BPC_PoolDir.s);
len = strlen(path->s);
bpc_strBuf_resize(path, len + 3 + 3 + 1 + 2 * digest->len + 1 + 16);
out = path->s + len;
*out++ = '/';
bpc_byte2hex(out, digest->digest[0] & 0xfe); out += 2;
*out++ = '/';
bpc_byte2hex(out, digest->digest[1] & 0xfe); out += 2;
*out++ = '/';
bpc_digest_digest2str(digest, out);
}
void bpc_digest_md52path_v3(bpc_strBuf *path, int compress, bpc_digest *digest)
{
int i;
char hexStr[BPC_DIGEST_LEN_MAX * 2 + 1];
uint32 ext = 0;
char n0 = hexDigits[(digest->digest[0] >> 4) & 0xf];
char n1 = hexDigits[(digest->digest[0] >> 0) & 0xf];
char n2 = hexDigits[(digest->digest[1] >> 4) & 0xf];
bpc_digest_digest2str(digest, hexStr);
for ( i = 16 ; i < digest->len ; i++ ) {
ext |= digest->digest[i - 16] << (8 * (i - 16));
}
if ( ext > 0 ) {
bpc_strBuf_snprintf(path, 0, "%s/%c/%c/%c/%s_%d", compress ? BPC_CPoolDir3.s : BPC_PoolDir3.s, n0, n1, n2, hexStr, ext);
} else {
bpc_strBuf_snprintf(path, 0, "%s/%c/%c/%c/%s", compress ? BPC_CPoolDir3.s : BPC_PoolDir3.s, n0, n1, n2, hexStr);
}
}
void bpc_digest_buffer2MD5_v3(bpc_digest *digest, uchar *buffer, size_t bufferLen)
{
char lenStr[256];
md_context md5;
md5_begin(&md5);
sprintf(lenStr, "%llu", (long long unsigned int)bufferLen);
md5_update(&md5, (uchar*)lenStr, strlen(lenStr));
if ( bufferLen > 262144 ) {
/*
* add the first and last 131072 bytes of the buffer,
* up to 1MB.
*/
int seekPosn = (bufferLen > 1048576 ? 1048576 : bufferLen) - 131072;
md5_update(&md5, buffer, 131072);
md5_update(&md5, buffer + seekPosn, 131072);
} else {
/*
* add the whole buffer
*/
md5_update(&md5, buffer, bufferLen);
}
md5_result(&md5, digest->digest);
digest->len = MD5_DIGEST_LEN;
}
static void bpc_fileNameEltMangle2(bpc_strBuf *path, char *pathUM, int stopAtSlash, unsigned int i)
{
if ( i >= path->size - 16 ) {
bpc_strBuf_resize(path, i + 32);
}
if ( !*pathUM || (stopAtSlash && *pathUM == '/') ) {
path->s[i] = '\0';
return;
}
path->s[i++] = 'f';
for ( ; *pathUM ; ) {
if ( i >= path->size - 16 ) {
bpc_strBuf_resize(path, i + 32);
}
if ( stopAtSlash && *pathUM == '/' ) break;
if ( *pathUM != '%' && *pathUM != '/' && *pathUM != '\n' && *pathUM != '\r' ) {
path->s[i++] = *pathUM++;
} else {
path->s[i++] = '%';
bpc_byte2hex(path->s + i, *pathUM++);
i += 2;
}
}
path->s[i] = '\0';
}
void bpc_fileNameEltMangle(bpc_strBuf *path, char *pathUM)
{
bpc_fileNameEltMangle2(path, pathUM, 0, 0);
}
void bpc_fileNameMangle(bpc_strBuf *path, char *pathUM, unsigned int i)
{
char *p;
for ( ; *pathUM ; ) {
bpc_fileNameEltMangle2(path, pathUM, 1, i);
i += strlen(path->s + i);
if ( !(p = strchr(pathUM, '/')) ) break;
for ( pathUM = p + 1 ; *pathUM == '/' ; pathUM++ ) { }
if ( *pathUM ) {
path->s[i++] = '/';
}
}
path->s[i++] = '\0';
}
void bpc_strBuf_init(bpc_strBuf *buf)
{
buf->s = buf->buffer;
buf->size = sizeof(buf->buffer);
buf->s[0] = '\0';
}
#define STRBUF_FREELIST_INCR_ADD 16
static bpc_strBuf *StrBufFreeList;
static int StrBufFreeListLen = 0;
bpc_strBuf *bpc_strBuf_new(void)
{
if ( !StrBufFreeList ) {
int i;
if ( BPC_LogLevel >= 10 ) {
bpc_logMsgf("bpc_strBuf_new: allocating %d more str bufs\n", STRBUF_FREELIST_INCR_ADD);
}
StrBufFreeListLen += STRBUF_FREELIST_INCR_ADD;
StrBufFreeList = malloc(STRBUF_FREELIST_INCR_ADD * sizeof(bpc_strBuf));
if ( !StrBufFreeList ) {
fprintf(stderr, "bpc_strBuf_new: panic: can't alloc %lu bytes\n", STRBUF_FREELIST_INCR_ADD * sizeof(bpc_strBuf));
}
/*
* chain all the buffers together in a linked list
*/
for ( i = 0 ; i < STRBUF_FREELIST_INCR_ADD - 1 ; i++ ) {
bpc_strBuf_init(&StrBufFreeList[i]);
StrBufFreeList[i].next = &StrBufFreeList[i + 1];
}
bpc_strBuf_init(&StrBufFreeList[i]);
StrBufFreeList[i].next = NULL;
}
bpc_strBuf *p = StrBufFreeList;
StrBufFreeList = StrBufFreeList->next;
StrBufFreeListLen--;
p->next = NULL;
if ( BPC_LogLevel >= 11 ) {
bpc_logMsgf("bpc_strBuf_new(p = %p: size = %lu) (FreeListLen = %d)\n", p, p->size, StrBufFreeListLen);
}
return p;
}
void bpc_strBuf_free(bpc_strBuf *buf)
{
StrBufFreeListLen++;
if ( BPC_LogLevel >= 11 ) {
bpc_logMsgf("bpc_strBuf_free(buf = %p: size = %lu, next = %p) (FreeListLen = %d)\n", buf, buf->size, buf->next, StrBufFreeListLen);
}
buf->next = StrBufFreeList;
StrBufFreeList = buf;
}
void bpc_strBuf_resize(bpc_strBuf *buf, size_t needed)
{
size_t oldSize = buf->size;
if ( !buf->s ) {
bpc_strBuf_init(buf);
}
if ( needed < buf->size ) {
return;
}
buf->size = 2 * needed;
if ( buf->s == buf->buffer ) {
buf->s = malloc(buf->size);
/*
* have to use memcpy, not strcpy, since strBuf might have multiple strings
* (ie, contain multiple \0)
*/
memcpy(buf->s, buf->buffer, oldSize);
} else {
buf->s = realloc(buf->s, buf->size);
}
if ( !buf->s ) {
fprintf(stderr, "bpc_bufferResize: panic: can't alloc %lu bytes\n", (unsigned long)buf->size);
}
}
char *bpc_strBuf_strcpy(bpc_strBuf *buf, unsigned int offset, char *str)
{
bpc_strBuf_resize(buf, offset + strlen(str) + 1);
return strcpy(buf->s + offset, str);
}
char *bpc_strBuf_strcat(bpc_strBuf *buf, unsigned int offset, char *str)
{
bpc_strBuf_resize(buf, offset + strlen(buf->s) + strlen(str) + 1);
return strcat(buf->s + offset, str);
}
int bpc_strBuf_vsnprintf(bpc_strBuf *buf, unsigned int offset, char *fmt, va_list args)
{
int strLen = strlen(fmt);
do {
va_list args2;
va_copy(args2, args);
bpc_strBuf_resize(buf, offset + strLen + 1);
strLen = vsnprintf(buf->s + offset, buf->size - offset, fmt, args2);
va_end(args2);
} while ( strLen >= 0 && offset + strLen >= buf->size );
return strLen;
}
int bpc_strBuf_snprintf(bpc_strBuf *buf, unsigned int offset, char *fmt, ...)
{
va_list args;
int strLen;
va_start(args, fmt);
strLen = bpc_strBuf_vsnprintf(buf, offset, fmt, args);
va_end(args);
return strLen;
}
/*
* Simple logging functions. If you register callbacks, they will be called.
* Otherwise, messages are accumulated, and a callback allows the
* log strings to be fetched.
*
* We store the data in a single buffer of '\0'-terminated strings.
*/
typedef struct {
bpc_strBuf mesg;
size_t mesgLen;
unsigned long errorCnt;
} LogMsgData;
static LogMsgData LogData;
static void (*LogMsgCB)(int, char *mesg, size_t mesgLen);
void bpc_logMsgf(char *fmt, ...)
{
int strLen, pad = 0;
va_list args;
va_start(args, fmt);
if ( BPC_TmpFileUnique >= 0 ) pad = 2;
strLen = bpc_strBuf_vsnprintf(&LogData.mesg, LogData.mesgLen + pad, fmt, args);
if ( strLen > 0 ) {
if ( pad ) {
LogData.mesg.s[LogData.mesgLen++] = BPC_TmpFileUnique ? 'G' : 'R';
LogData.mesg.s[LogData.mesgLen++] = ' ';
}
LogData.mesgLen += strLen + 1;
}
if ( LogMsgCB ) {
(*LogMsgCB)(0, LogData.mesg.s, LogData.mesgLen - 1);
LogData.mesgLen = 0;
}
va_end(args);
}
/*
* For now, this is just the same as bpc_logMsgf(). We can't call a common routine that
* does the work, since args might need to be parsed twice when the buffer is grown.
*/
void bpc_logErrf(char *fmt, ...)
{
int strLen, pad = 0;
va_list args;
va_start(args, fmt);
if ( BPC_TmpFileUnique >= 0 ) pad = 2;
strLen = bpc_strBuf_vsnprintf(&LogData.mesg, LogData.mesgLen + pad, fmt, args);
if ( strLen > 0 ) {
if ( pad ) {
LogData.mesg.s[LogData.mesgLen++] = BPC_TmpFileUnique ? 'G' : 'R';
LogData.mesg.s[LogData.mesgLen++] = ' ';
}
LogData.mesgLen += strLen + 1;
}
if ( LogMsgCB ) {
(*LogMsgCB)(0, LogData.mesg.s, LogData.mesgLen - 1);
LogData.mesgLen = 0;
}
va_end(args);
}
void bpc_logMsgGet(char **mesg, size_t *mesgLen)
{
*mesg = LogData.mesg.s;
*mesgLen = LogData.mesgLen;
LogData.mesgLen = 0;
}
void bpc_logMsgErrorCntGet(unsigned long *errorCnt)
{
*errorCnt = LogData.errorCnt;
LogData.errorCnt = 0;
}
void bpc_logMsgCBSet(void (*cb)(int errFlag, char *mesg, size_t mesgLen))
{
LogMsgCB = cb;
}
rsync-bpc-3.1.3.0/backuppc/bpc_poolWrite.c 0000664 0000000 0000000 00000107730 13737671777 0020361 0 ustar 00root root 0000000 0000000 /*
* Routines for matching and writing files in the pool.
*
* Copyright (C) 2013 Craig Barratt.
*
* 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 "backuppc.h"
static uint32 PoolWriteCnt = 0;
/*
* Buffer used in various places for copying, comparing etc
*/
#define COMPARE_BUF_SZ (1 << 20) /* 1.0 MB */
static uchar TempBuf[2 * COMPARE_BUF_SZ];
/*
* A freelist of unused BPC_POOL_WRITE_BUF_SZ sized-buffers.
* We use the first sizeof(void*) bytes of the buffer as a single-linked
* list, with a NULL at the end.
*/
static void *DataBufferFreeList = (void*)NULL;
int bpc_poolWrite_open(bpc_poolWrite_info *info, int compress, bpc_digest *digest)
{
int i;
info->compress = compress;
info->eof = 0;
info->errorCnt = 0;
info->state = 0;
info->bufferIdx = 0;
info->fileSize = 0;
info->matchPosn = 0;
info->candidateList = NULL;
info->fdOpen = 0;
info->retValue = -1;
info->poolFileSize = 0;
info->retryCnt = 0;
info->digestExtOpen = -1;
info->digestExtZeroLen = -1;
info->tmpFileName = bpc_strBuf_new();
for ( i = 0 ; i < BPC_POOL_WRITE_CONCURRENT_MATCH ; i++ ) {
info->match[i].used = 0;
}
if ( DataBufferFreeList ) {
info->buffer = DataBufferFreeList;
DataBufferFreeList = *(void**)DataBufferFreeList;
} else {
info->buffer = malloc(BPC_POOL_WRITE_BUF_SZ);
}
if ( !info->buffer ) {
bpc_logErrf("bpc_poolWrite_open: can't allocate %d bytes for buffer\n", BPC_POOL_WRITE_BUF_SZ);
return -1;
}
if ( digest ) {
info->digest = *digest;
/* TODO: don't have V3 digest at this point! */
info->state = 2;
} else {
info->digest.len = 0;
}
info->digest_v3.len = 0;
bpc_strBuf_snprintf(info->tmpFileName, 0, "%s/%d.%d.%d",
compress ? BPC_CPoolDir.s : BPC_PoolDir.s, (int)getpid(), PoolWriteCnt++,
BPC_TmpFileUnique >= 0 ? BPC_TmpFileUnique : 0);
return 0;
}
/*
* Fill out the array of candidate matching files. Returns the number of active
* matching files.
*/
static int bpc_poolWrite_updateMatches(bpc_poolWrite_info *info)
{
int i, nMatch = 0;
for ( i = 0 ; i < BPC_POOL_WRITE_CONCURRENT_MATCH ; i++ ) {
if ( info->match[i].used ) {
nMatch++;
continue;
}
while ( info->candidateList ) {
int match = 1;
bpc_candidate_file *candidateFile;
candidateFile = info->candidateList;
info->candidateList = candidateFile->next;
if ( bpc_fileZIO_open(&info->match[i].fd, candidateFile->fileName->s, 0, info->compress) ) {
info->errorCnt++;
bpc_logErrf("bpc_poolWrite_updateMatches: can't open candidate file %s for read\n",
candidateFile->fileName->s);
free(candidateFile);
continue;
}
/*
* We need to check that the first info->matchPosn bytes of the candidate file match
* the original file.
*/
if ( info->matchPosn > 0 ) {
if ( info->fdOpen ) {
/*
* Compare the candidate file against the data in the file
*/
uchar *buf0 = TempBuf;
uchar *buf1 = TempBuf + COMPARE_BUF_SZ;
OFF_T idx = 0;
bpc_fileZIO_rewind(&info->fd);
while ( idx < info->matchPosn ) {
OFF_T thisRead = info->matchPosn - idx;
OFF_T nread0, nread1;
if ( thisRead > COMPARE_BUF_SZ ) thisRead = COMPARE_BUF_SZ;
nread0 = bpc_fileZIO_read(&info->fd, buf0, thisRead);
nread1 = bpc_fileZIO_read(&info->match[i].fd, buf1, thisRead);
if ( nread0 != nread1 || memcmp(buf0, buf1, nread0) ) {
/*
* Need to keep reading the original file to get back to matchPosn
*/
match = 0;
}
idx += nread0;
}
} else {
/*
* Compare the candidate file against the data in the buffer
*/
uchar *buf1 = TempBuf;
OFF_T idx = 0;
while ( idx < info->matchPosn ) {
OFF_T thisRead = info->matchPosn - idx;
OFF_T nread1;
if ( thisRead > COMPARE_BUF_SZ ) thisRead = COMPARE_BUF_SZ;
if ( thisRead > info->bufferIdx - idx ) thisRead = info->bufferIdx - idx;
nread1 = bpc_fileZIO_read(&info->match[i].fd, buf1, thisRead);
if ( thisRead != nread1 || memcmp(info->buffer + idx, buf1, thisRead) ) {
match = 0;
break;
}
idx += thisRead;
}
}
}
if ( !match ) {
if ( BPC_LogLevel >= 8 ) bpc_logMsgf("Discarding %s since it doesn't match starting portion\n", candidateFile->fileName->s);
bpc_fileZIO_close(&info->match[i].fd);
free(candidateFile);
continue;
}
info->match[i].used = 1;
info->match[i].digest = candidateFile->digest;
info->match[i].v3File = candidateFile->v3File;
info->match[i].fileSize = candidateFile->fileSize;
info->match[i].fileName = bpc_strBuf_new();
bpc_strBuf_strcpy(info->match[i].fileName, 0, candidateFile->fileName->s);
nMatch++;
if ( BPC_LogLevel >= 9 ) bpc_logMsgf("match[%d] now set to %s\n", i, info->match[i].fileName->s);
bpc_strBuf_free(candidateFile->fileName);
free(candidateFile);
break;
}
}
return nMatch;
}
/*
* Write a chunk to the current pool file.
*
* Call with undef to indicate EOF / close.
*/
int bpc_poolWrite_write(bpc_poolWrite_info *info, uchar *data, size_t dataLen)
{
if ( info->errorCnt ) return -1;
info->fileSize += dataLen;
if ( info->state == 0 ) {
/*
* In this state we are at the start of the file and don't have a digest yet
*/
if ( data ) {
/*
* Cumulate small writes at the start of the file
*/
if ( info->bufferIdx + dataLen <= BPC_POOL_WRITE_BUF_SZ ) {
memcpy(info->buffer + info->bufferIdx, data, dataLen);
info->bufferIdx += dataLen;
return 0;
}
/*
* We have more data than the buffer can fit. Top off the buffer if it has less than
* 1MB of data so that we can compute the V3 digest.
*/
if ( data && info->bufferIdx < (1 << 20) && BPC_POOL_WRITE_BUF_SZ >= (1 << 20) ) {
uint32 addTo1MB = (1 << 20) - info->bufferIdx;
memcpy(info->buffer + info->bufferIdx, data, addTo1MB);
info->bufferIdx += addTo1MB;
data += addTo1MB;
dataLen -= addTo1MB;
}
if ( !info->digest.len ) {
ssize_t writeRet;
/*
* We don't have a digest and the file is bigger than the buffer.
* So we need to write the data to a temp file and compute the MD5
* digest as we write the file.
*/
if ( bpc_fileZIO_open(&info->fd, info->tmpFileName->s, 1, info->compress) ) {
info->errorCnt++;
bpc_logErrf("bpc_poolWrite_write: can't open/create %s for writing", info->tmpFileName->s);
return -1;
}
info->fdOpen = 1;
md5_begin(&info->md5);
if ( info->bufferIdx > 0 ) {
if ( (writeRet = bpc_fileZIO_write(&info->fd, info->buffer, info->bufferIdx)) != (signed)info->bufferIdx ) {
info->errorCnt++;
bpc_logErrf("bpc_poolWrite_write: write of %lu bytes to %s failed, return = %d",
(unsigned long)info->bufferIdx, info->tmpFileName->s, (int)writeRet);
return -1;
}
md5_update(&info->md5, info->buffer, info->bufferIdx);
}
info->state = 1;
} else {
/*
* We have the new digest, so figure out the list of candidate matching files
*/
/* TODO: don't have V3 digest at this point! */
info->state = 2;
}
} else {
/*
* We are at EOF, so we can compute the digests based on the entire file in
* the buffer.
*/
info->eof = 1;
bpc_digest_buffer2MD5(&info->digest, info->buffer, info->bufferIdx);
if ( BPC_PoolV3Enabled ) {
bpc_digest_buffer2MD5_v3(&info->digest_v3, info->buffer, info->bufferIdx);
if ( BPC_LogLevel >= 8 ) {
char hexStr_v3[BPC_DIGEST_LEN_MAX * 2 + 1], hexStr[BPC_DIGEST_LEN_MAX * 2 + 1];
bpc_digest_digest2str(&info->digest, hexStr);
bpc_digest_digest2str(&info->digest_v3, hexStr_v3);
bpc_logMsgf("bpc_poolWrite_write: digest is %s, v3 is %s\n", hexStr, hexStr_v3);
}
} else if ( BPC_LogLevel >= 8 ) {
char hexStr[BPC_DIGEST_LEN_MAX * 2 + 1];
bpc_digest_digest2str(&info->digest, hexStr);
bpc_logMsgf("bpc_poolWrite_write: digest is %s\n", hexStr);
}
info->state = 2;
}
}
if ( info->state == 1 ) {
ssize_t writeRet;
/*
* In this state we are writing the data to a compressed temporary file, and
* accumulating the digests.
*/
if ( dataLen > 0 ) {
if ( (writeRet = bpc_fileZIO_write(&info->fd, data, dataLen)) != (ssize_t)dataLen ) {
info->errorCnt++;
bpc_logErrf("bpc_poolWrite_write: write of %lu bytes to %s failed, return = %d",
(unsigned long)dataLen, info->tmpFileName->s, (int)writeRet);
return -1;
}
md5_update(&info->md5, data, dataLen);
}
if ( !data ) {
/*
* We are at EOF. Close the output file and re-open it for reading.
* Compute the digests too.
*/
bpc_fileZIO_close(&info->fd);
if ( bpc_fileZIO_open(&info->fd, info->tmpFileName->s, 0, info->compress) ) {
info->errorCnt++;
bpc_logErrf("bpc_poolWrite_write: can't open %s for reading", info->tmpFileName->s);
return -1;
}
info->fdOpen = 1;
md5_result(&info->md5, info->digest.digest);
info->digest.len = MD5_DIGEST_LEN;
if ( BPC_PoolV3Enabled ) {
bpc_digest_buffer2MD5_v3(&info->digest_v3, info->buffer, info->fileSize);
if ( BPC_LogLevel >= 8 ) {
char hexStr_v3[BPC_DIGEST_LEN_MAX * 2 + 1], hexStr[BPC_DIGEST_LEN_MAX * 2 + 1];
bpc_digest_digest2str(&info->digest, hexStr);
bpc_digest_digest2str(&info->digest_v3, hexStr_v3);
bpc_logMsgf("bpc_poolWrite_write: digest is %s, v3 is %s\n", hexStr, hexStr_v3);
}
} else if ( BPC_LogLevel >= 8 ) {
char hexStr[BPC_DIGEST_LEN_MAX * 2 + 1];
bpc_digest_digest2str(&info->digest, hexStr);
bpc_logMsgf("bpc_poolWrite_write: digest is %s\n", hexStr);
}
info->state = 2;
}
}
if ( info->state == 2 ) {
uint32 ext = 0;
bpc_strBuf *poolPath = bpc_strBuf_new();
STRUCT_STAT st;
/*
* In this state we have either the full file in info->buffer, or the full file
* is opened for reading with info->fd. We also have digests computed.
*
* We figure out the list of candidate files to match. If there are any
* new digest files then we just try to match them. Otherwise we also
* try to match any old V3 files.
*
* Since the empty file is never stored in the pool, we have to make sure
* that any digest that collides (ie: 0xd41d8cd98f00b204e9800998ecf8427e)
* doesn't use the first slot (ie: make sure it has an extension > 0)
*/
static uchar zeroLenMD5[] = {
0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e
};
if ( info->fileSize > 0 && !memcmp(info->digest.digest, zeroLenMD5, sizeof(zeroLenMD5)) ) {
ext++;
}
info->digestExtZeroLen = -1;
while ( 1 ) {
bpc_digest_append_ext(&info->digest, ext);
bpc_digest_md52path(poolPath, info->compress, &info->digest);
/*
* For >= V4.x pool, don't attempt to match pool files that
* are empty, since in >= V4.x we don't rename pool
* files in a repeated chain and instead replace them
* with an empty file.
* If the candidate has the other execute bit set, we do a safe
* reset of the bit and allow matches to occur. This is used to flag
* pool files that will be deleted next time BackupPC_refCountUpdate
* runs, so resetting that bit prevents the deletion.
*/
if ( stat(poolPath->s, &st) ) break;
if ( S_ISREG(st.st_mode) ) {
if ( st.st_size > 0 ) {
bpc_candidate_file *candidateFile;
if ( (st.st_mode & S_IXOTH) && bpc_poolWrite_unmarkPendingDelete(poolPath->s) ) {
bpc_logErrf("Couldn't unmark candidate matching file %s (skipped; errno = %d)\n", poolPath->s, errno);
info->errorCnt++;
break;
}
candidateFile = malloc(sizeof(bpc_candidate_file));
if ( !candidateFile ) {
info->errorCnt++;
bpc_logErrf("bpc_poolWrite_write: can't allocate bpc_candidate_file\n");
bpc_strBuf_free(poolPath);
return -1;
}
candidateFile->digest = info->digest;
candidateFile->fileSize = st.st_size;
candidateFile->v3File = 0;
candidateFile->fileName = bpc_strBuf_new();
bpc_strBuf_strcpy(candidateFile->fileName, 0, poolPath->s);
candidateFile->next = info->candidateList;
info->candidateList = candidateFile;
if ( BPC_LogLevel >= 7 ) bpc_logMsgf("Candidate matching file %s\n", candidateFile->fileName->s);
} else if ( info->digestExtZeroLen < 0 ) {
/*
* Remember the first empty file in case we have to insert a
* new pool file here.
*/
info->digestExtZeroLen = ext;
}
}
ext++;
}
/*
* Remember the next open slot in case we have to add a new pool
* file here.
*/
info->digestExtOpen = ext;
bpc_digest_append_ext(&info->digest, 0);
if ( BPC_PoolV3Enabled && !info->candidateList ) {
/*
* No matching candidate files so far, so now look in V3 pool
*/
ext = 0;
while ( 1 ) {
bpc_digest_append_ext(&info->digest_v3, ext);
bpc_digest_md52path_v3(poolPath, info->compress, &info->digest_v3);
ext++;
/*
* For V3.x pool, don't attempt to match pool files:
* - that already have too many hardlinks.
* - with only one link since starting in BackupPC v3.0,
* BackupPC_nightly could be running in parallel (and
* removing those files). This doesn't eliminate all
* possible race conditions, but just reduces the
* odds. Other design steps eliminate the remaining
* race conditions of linking vs removing.
*/
if ( stat(poolPath->s, &st) ) break;
if ( S_ISREG(st.st_mode)
&& 1 < st.st_nlink && st.st_nlink < (unsigned)BPC_HardLinkMax ) {
bpc_candidate_file *candidateFile = malloc(sizeof(bpc_candidate_file));
if ( !candidateFile ) {
info->errorCnt++;
bpc_logErrf("bpc_poolWrite_write: can't allocate bpc_candidate_file\n");
bpc_strBuf_free(poolPath);
return -1;
}
candidateFile->digest = info->digest_v3;
candidateFile->fileSize = st.st_size;
candidateFile->v3File = 1;
candidateFile->fileName = bpc_strBuf_new();
bpc_strBuf_strcpy(candidateFile->fileName, 0, poolPath->s);
candidateFile->next = info->candidateList;
info->candidateList = candidateFile;
if ( BPC_LogLevel >= 7 ) bpc_logMsgf("Candidate v3 matching file %s\n", candidateFile->fileName->s);
}
}
bpc_digest_append_ext(&info->digest_v3, 0);
}
bpc_strBuf_free(poolPath);
/*
* Open the first set of candidate files.
*/
bpc_poolWrite_updateMatches(info);
info->state = 3;
}
if ( info->state == 3 ) {
/*
* In this state we are continuing to match against candidate files
*/
while ( 1 ) {
int i, replaceCnt = 0, nMatch = 0;
uchar *buf0 = TempBuf;
uchar *buf1 = TempBuf + COMPARE_BUF_SZ;
uchar *buf;
OFF_T nread0;
if ( info->fdOpen ) {
nread0 = bpc_fileZIO_read(&info->fd, buf0, COMPARE_BUF_SZ);
buf = buf0;
} else {
nread0 = COMPARE_BUF_SZ;
if ( nread0 > info->bufferIdx - info->matchPosn ) nread0 = info->bufferIdx - info->matchPosn;
buf = info->buffer + info->matchPosn;
}
for ( i = 0 ; i < BPC_POOL_WRITE_CONCURRENT_MATCH ; i++ ) {
OFF_T nread1;
if ( !info->match[i].used ) continue;
nMatch++;
/*
* Try to read an extra byte when we expect EOF, to make sure the candidate file is also at EOF
*/
nread1 = bpc_fileZIO_read(&info->match[i].fd, buf1, nread0 > 0 ? nread0 : 1);
if ( BPC_LogLevel >= 9 ) bpc_logMsgf("Read %d bytes of %d from match[%d] (%s)\n", (int)nread1, (int)nread0, i, info->match[i].fileName->s);
if ( nread0 != nread1 || (nread0 > 0 && memcmp(buf, buf1, nread0)) ) {
bpc_fileZIO_close(&info->match[i].fd);
if ( BPC_LogLevel >= 8 ) bpc_logMsgf("match[%d] no longer matches\n", i);
bpc_strBuf_free(info->match[i].fileName);
info->match[i].used = 0;
replaceCnt++;
}
}
info->matchPosn += nread0;
if ( replaceCnt ) {
nMatch = bpc_poolWrite_updateMatches(info);
}
if ( nread0 == 0 || nMatch == 0 ) {
/*
* we are at eof (with a match) or there are no matches
*/
info->state = 4;
break;
}
}
}
if ( info->state == 4 ) {
/*
* see if there is a matching file
*/
int i, nMatch = 0, iMatch = 0;
for ( i = BPC_POOL_WRITE_CONCURRENT_MATCH -1 ; i >= 0 ; i-- ) {
if ( !info->match[i].used ) continue;
nMatch++;
iMatch = i;
}
if ( nMatch == 0 ) {
ssize_t writeRet;
/*
* Need to write a new file if not written already
*/
if ( !info->fdOpen && info->fileSize > 0 ) {
if ( bpc_fileZIO_open(&info->fd, info->tmpFileName->s, 1, info->compress) ) {
info->errorCnt++;
bpc_logErrf("bpc_poolWrite_write: can't open/create %s for writing", info->tmpFileName->s);
return -1;
}
if ( info->bufferIdx > 0 ) {
if ( (writeRet = bpc_fileZIO_write(&info->fd, info->buffer, info->bufferIdx)) != (ssize_t)info->bufferIdx ) {
info->errorCnt++;
bpc_logErrf("bpc_poolWrite_write: write of %u bytes to %s failed, return = %d",
info->bufferIdx, info->tmpFileName->s, (int)writeRet);
return -1;
}
}
bpc_fileZIO_close(&info->fd);
}
if ( info->fileSize > 0 ) {
char hexStr[BPC_DIGEST_LEN_MAX * 2 + 1];
bpc_digest_append_ext(&info->digest, 0);
bpc_digest_digest2str(&info->digest, hexStr);
if ( BPC_LogLevel >= 5 ) bpc_logMsgf("No match... adding %s to pool (digest = %s)\n", info->tmpFileName->s, hexStr);
bpc_poolWrite_addToPool(info, info->tmpFileName->s, 0);
} else {
if ( BPC_LogLevel >= 5 ) bpc_logMsgf("Zero length file - don't match anything\n");
info->digest.len = 0;
info->retValue = 1;
info->poolFileSize = 0;
}
} else {
/*
* We matched a pool file
*/
if ( nMatch > 1 ) {
char hexStr[BPC_DIGEST_LEN_MAX * 2 + 1];
if ( BPC_LogLevel >= 4 ) bpc_logMsgf("Botch - got multiple pool file matches\n");
info->errorCnt++;
bpc_digest_digest2str(&info->digest, hexStr);
bpc_logErrf("bpc_poolWrite_write: got %d matching files for digest %s\n", nMatch, hexStr);
}
if ( BPC_LogLevel >= 7 ) bpc_logMsgf("Found match with match[%d] (%s)\n", iMatch, info->match[iMatch].fileName->s);
if ( info->match[iMatch].v3File ) {
bpc_digest_append_ext(&info->digest, 0);
bpc_poolWrite_addToPool(info, info->match[iMatch].fileName->s, info->match[iMatch].v3File);
} else {
info->digest = info->match[iMatch].digest;
info->retValue = 1;
info->poolFileSize = info->match[iMatch].fileSize;
}
if ( info->fdOpen ) {
bpc_fileZIO_close(&info->fd);
unlink(info->tmpFileName->s);
info->fdOpen = 0;
}
}
}
return 0;
}
int bpc_poolWrite_createPoolDir(bpc_poolWrite_info *info, bpc_digest *digest)
{
bpc_strBuf *path = bpc_strBuf_new();
char *p;
int ret;
/*
* get the full path, and prune off the file name to get the directory
*/
bpc_digest_md52path(path, info->compress, digest);
if ( !(p = strrchr(path->s, '/')) ) {
info->errorCnt++;
bpc_logErrf("bpc_poolWrite_createPoolDir: can't find trailing / in path %s", path->s);
bpc_strBuf_free(path);
return -1;
}
*p = '\0';
if ( (ret = bpc_path_create(path->s)) ) {
info->errorCnt++;
bpc_logErrf("bpc_poolWrite_createPoolDir: can't create directory path %s", path->s);
}
bpc_strBuf_free(path);
return ret;
}
void bpc_poolWrite_cleanup(bpc_poolWrite_info *info)
{
int i;
if ( info->fdOpen ) bpc_fileZIO_close(&info->fd);
info->fdOpen = 0;
while ( info->candidateList ) {
bpc_candidate_file *candidateFile = info->candidateList;
info->candidateList = candidateFile->next;
bpc_strBuf_free(candidateFile->fileName);
free(candidateFile);
}
for ( i = 0 ; i < BPC_POOL_WRITE_CONCURRENT_MATCH ; i++ ) {
if ( !info->match[i].used ) continue;
bpc_fileZIO_close(&info->match[i].fd);
bpc_strBuf_free(info->match[i].fileName);
info->match[i].used = 0;
}
bpc_strBuf_free(info->tmpFileName);
if ( info->buffer ) {
*(void**)info->buffer = DataBufferFreeList;
DataBufferFreeList = info->buffer;
info->buffer = NULL;
}
}
/*
* Called after the data is written. The return information is passed via four arguments:
*
* (match, digest, poolFileSize, errorCnt)
*
* The return values are:
*
* - match:
* If match == 0, then the file doesn't match either the new or old pools.
* The file has been added to the pool.
*
* If match == 1, then the file matches the new pool. No file is
* written.
*
* If match == 2, then the file matches the old pool. The old pool
* file was moved to become the new pool file.
*
* - digest: the 16+ byte binary MD5 digest, possibly appended with
* on or more additional bytes to point to the right pool file in
* case there are MD5 collisions
*
* - poolFileSize: the compressed pool file size
*
* - errorCnt: number of errors
*/
void bpc_poolWrite_close(bpc_poolWrite_info *info, int *match, bpc_digest *digest, OFF_T *poolFileSize, int *errorCnt)
{
bpc_poolWrite_write(info, NULL, 0);
bpc_poolWrite_cleanup(info);
*match = info->retValue;
*digest = info->digest;
*poolFileSize = info->poolFileSize;
*errorCnt = info->errorCnt;
}
void bpc_poolWrite_repeatPoolWrite(bpc_poolWrite_info *info, char *fileNameTmp)
{
bpc_poolWrite_cleanup(info);
if ( BPC_LogLevel >= 5 ) bpc_logMsgf("bpc_poolWrite_repeatPoolWrite: rewriting %s\n", fileNameTmp);
if ( info->retryCnt++ > 8 ) {
bpc_logErrf("bpc_poolWrite_repeatPoolWrite: giving up on %s after %d attempts\n", fileNameTmp, info->retryCnt);
info->errorCnt++;
unlink(fileNameTmp);
return;
}
bpc_strBuf_strcpy(info->tmpFileName, 0, fileNameTmp);
if ( bpc_fileZIO_open(&info->fd, fileNameTmp, 0, info->compress) < 0 ) {
bpc_logErrf("bpc_poolWrite_repeatPoolWrite: can't open %s for reading", fileNameTmp);
info->errorCnt++;
return;
}
info->eof = 1;
info->state = 2;
info->fdOpen = 1;
bpc_poolWrite_write(info, NULL, 0);
}
int bpc_poolWrite_copyToPool(bpc_poolWrite_info *info, char *poolPath, char *fileName)
{
int fdRead, fdWrite;
int nRead, nWrite;
if ( (fdWrite = open(poolPath, O_WRONLY | O_CREAT | O_EXCL, 0666)) < 0 ) {
info->errorCnt++;
bpc_logErrf("bpc_poolWrite_copyToPool: can't open/create %s for writing", poolPath);
return -1;
}
if ( (fdRead = open(fileName, O_RDONLY)) < 0 ) {
info->errorCnt++;
bpc_logErrf("bpc_poolWrite_copyToPool: can't open %s for reading", fileName);
return -1;
}
while ( (nRead = read(fdRead, info->buffer, sizeof(info->buffer))) > 0 ) {
uchar *p = info->buffer;
int thisWrite;
nWrite = 0;
while ( nWrite < nRead ) {
do {
thisWrite = write(fdWrite, p, nRead - nWrite);
} while ( thisWrite < 0 && errno == EINTR );
if ( thisWrite < 0 ) {
info->errorCnt++;
bpc_logErrf("bpc_poolWrite_copyToPool: write to %s failed (errno = %d)", poolPath, errno);
close(fdWrite);
close(fdRead);
unlink(poolPath);
return -1;
}
p += thisWrite;
nWrite += thisWrite;
}
}
close(fdWrite);
close(fdRead);
return 0;
}
void bpc_poolWrite_addToPool(bpc_poolWrite_info *info, char *fileName, int v3PoolFile)
{
STRUCT_STAT st;
bpc_strBuf *poolPath = bpc_strBuf_new();
int redo = 0;
if ( bpc_poolWrite_createPoolDir(info, &info->digest) ) return;
/*
* If originally present, make sure the zero-length file is still there (and still
* zero-length), and the open slot is still open. If not, it probably means someone
* beat us to it, and we should re-do the whole pool matching to see if the newly
* added pool file now matches.
*/
if ( info->digestExtZeroLen >= 0 ) {
bpc_digest_append_ext(&info->digest, info->digestExtZeroLen);
bpc_digest_md52path(poolPath, info->compress, &info->digest);
if ( stat(poolPath->s, &st) || st.st_size != 0 ) {
redo = 1;
}
}
if ( !redo ) {
bpc_digest_append_ext(&info->digest, info->digestExtOpen);
bpc_digest_md52path(poolPath, info->compress, &info->digest);
if ( !stat(poolPath->s, &st) ) {
redo = 1;
}
}
/*
* Try to insert the new file at the zero-length file slot (if present).
*/
if ( !redo && info->digestExtZeroLen >= 0 ) {
bpc_strBuf *lockFile = bpc_strBuf_new();
int lockFd;
/*
* We can replace a zero-length file, but only via locking to
* avoid race conditions. Since the hardlinking code below doesn't
* use a lock, we can't remove the file and use a hardlink
* because of race conditions - another process might be
* inserting with the same digest and grab the slot.
*
* So we make sure we have exclusive access via a lock file,
* check that the file is still zero-length, and then rename
* the file. If that fails then we redo everything.
*/
bpc_digest_append_ext(&info->digest, info->digestExtZeroLen);
bpc_digest_md52path(poolPath, info->compress, &info->digest);
if ( BPC_LogLevel >= 6 ) bpc_logMsgf("bpc_poolWrite_addToPool: replacing empty pool file %s with %s\n", poolPath->s, fileName);
bpc_strBuf_snprintf(lockFile, 0, "%s.lock", poolPath->s);
lockFd = bpc_lockRangeFile(lockFile->s, 0, 1, 1);
/*
* If we don't have the lock, or the file is no longer zero length, or the rename fails,
* then try again.
*/
if ( lockFd < 0 || stat(poolPath->s, &st) || st.st_size != 0 || rename(fileName, poolPath->s) ) {
if ( BPC_LogLevel >= 5 ) {
bpc_logMsgf("bpc_poolWrite_addToPool: lock/rename failed: need to repeat write (lockFd = %d, size = %lu, errno = %d)\n",
lockFd, (unsigned long)st.st_size, errno);
}
if ( lockFd >= 0 ) {
bpc_unlockRangeFile(lockFd);
}
unlink(lockFile->s);
redo = 1;
} else {
chmod(poolPath->s, 0444);
stat(poolPath->s, &st);
info->retValue = v3PoolFile ? 2 : 0;
info->poolFileSize = st.st_size;
bpc_unlockRangeFile(lockFd);
unlink(lockFile->s);
bpc_strBuf_free(poolPath);
bpc_strBuf_free(lockFile);
return;
}
bpc_strBuf_free(lockFile);
}
/*
* Now try to link the file to the new empty slot at the end
*/
if ( !redo ) {
int linkOk, statOk;
ino_t fileIno, poolIno;
/*
* Since this is a new slot, there is no need to do locking since
* the link or open operations below are atomic/exclusive.
*
* First try to hardlink to the empty pool file slot
*/
bpc_digest_append_ext(&info->digest, info->digestExtOpen);
bpc_digest_md52path(poolPath, info->compress, &info->digest);
if ( stat(fileName, &st) ) {
info->errorCnt++;
bpc_logErrf("bpc_poolWrite_addToPool: can't stat %s\n", fileName);
bpc_strBuf_free(poolPath);
return;
}
fileIno = st.st_ino;
linkOk = !link(fileName, poolPath->s);
if ( !(statOk = !stat(poolPath->s, &st)) ) linkOk = 0;
poolIno = st.st_ino;
if ( BPC_LogLevel >= 6 ) bpc_logMsgf("bpc_poolWrite_addToPool: link %s -> %s (linkOk = %d, statOk = %d, ino = %lu/%lu)\n",
poolPath->s, fileName, linkOk, statOk, (unsigned long)fileIno, (unsigned long)poolIno);
/*
* make sure the link really worked by checking inode numbers
* TODO: test these different cases.
*/
if ( statOk && fileIno == poolIno ) {
/*
* remove the original file and return
*/
unlink(fileName);
chmod(poolPath->s, 0444);
info->retValue = v3PoolFile ? 2 : 0;
info->poolFileSize = st.st_size;
bpc_strBuf_free(poolPath);
return;
}
/*
* Something failed. If the stat failed, the hardlink failure wasn't due
* to another file being added by someone else. Perhaps the cpool is
* split across multiple file systems?
*/
if ( !statOk ) {
/*
* The hardlink failed. This could be due to hitting the hardlink
* limit, or the fact that fileName and poolPath are on different
* file systems, or the fileName didn't get written.
* Just copy the file instead (assuming fileName got written).
*/
bpc_poolWrite_copyToPool(info, poolPath->s, fileName);
bpc_strBuf_free(poolPath);
return;
}
}
bpc_strBuf_free(poolPath);
/*
* We need to redo the pool write, since it appears someone else has added
* a pool file with the same digest.
*/
bpc_poolWrite_repeatPoolWrite(info, fileName);
}
/*
* Safely remove the o+x permission that marks a file for future deletion.
* Similar locking is done by BackupPC_refCountUpdate so we can avoid any
* race conditions with the file actually being deleted.
*
* Returns 0 on success.
*/
int bpc_poolWrite_unmarkPendingDelete(char *poolPath)
{
bpc_strBuf *lockFile = bpc_strBuf_new();
char *p;
STRUCT_STAT st;
int lockFd;
/*
* The lock file is in the first level of pool sub directories - one level
* up from the full path. So we need to find the 2nd last '/'.
*/
bpc_strBuf_snprintf(lockFile, 0, "%s", poolPath);
if ( !(p = strrchr(lockFile->s, '/')) ) return -1;
*p = '\0';
if ( !(p = strrchr(lockFile->s, '/')) ) return -1;
bpc_strBuf_strcpy(lockFile, p + 1 - lockFile->s, "LOCK");
if ( (lockFd = bpc_lockRangeFile(lockFile->s, 0, 1, 1)) < 0 ) {
bpc_strBuf_free(lockFile);
return -1;
}
bpc_strBuf_free(lockFile);
if ( !stat(poolPath, &st) && !chmod(poolPath, st.st_mode & ~S_IXOTH & ~S_IFMT) ) {
if ( BPC_LogLevel >= 7 ) bpc_logMsgf("bpc_poolWrite_unmarkPendingDelete(%s) succeeded\n", poolPath);
bpc_unlockRangeFile(lockFd);
return 0;
} else {
bpc_logErrf("bpc_poolWrite_unmarkPendingDelete(%s) failed; errno = %d\n", poolPath, errno);
bpc_unlockRangeFile(lockFd);
return -1;
}
}
rsync-bpc-3.1.3.0/backuppc/bpc_refCount.c 0000664 0000000 0000000 00000040445 13737671777 0020161 0 ustar 00root root 0000000 0000000 /*
* Routines to provide reference counting
*
* Copyright (C) 2013 Craig Barratt.
*
* 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 "backuppc.h"
/*
* magic number that appears at the start of the reference count (or delta count file)
*/
#define BPC_POOL_REF_MAGIC (0x178e553c)
#define CONV_BUF_TO_UINT32(buf) ((buf)[0] << 24 | (buf)[1] << 16 | (buf)[2] << 8 | (buf)[3])
#define CONV_UINT32_TO_BUF(buf, val) { *(buf)++ = ((val) >> 24) & 0xff; \
*(buf)++ = ((val) >> 16) & 0xff; \
*(buf)++ = ((val) >> 8) & 0xff; \
*(buf)++ = ((val) >> 0) & 0xff; }
typedef struct {
bpc_hashtable_key key;
int32 count;
bpc_digest digest;
} DigestInfo;
typedef struct {
int fd;
uchar *bufP;
int errorCnt;
uchar buf[4 * 65536];
} write_info;
void bpc_poolRefInit(bpc_refCount_info *info, int entryCnt)
{
bpc_hashtable_create(&info->ht, entryCnt, sizeof(DigestInfo));
}
void bpc_poolRefDestroy(bpc_refCount_info *info)
{
bpc_hashtable_destroy(&info->ht);
}
void bpc_poolRefSet(bpc_refCount_info *info, bpc_digest *digest, int32 count)
{
DigestInfo *d = bpc_hashtable_find(&info->ht, digest->digest, digest->len, 1);
if ( d->key.key == digest ) {
/*
* new entry - copy in digest
*/
d->digest = *digest;
d->key.key = d->digest.digest;
}
d->count = count;
return;
}
int bpc_poolRefGet(bpc_refCount_info *info, bpc_digest *digest, int32 *count)
{
DigestInfo *d = bpc_hashtable_find(&info->ht, digest->digest, digest->len, 0);
if ( !d ) return -1;
*count = d->count;
return 0;
}
int bpc_poolRefDelete(bpc_refCount_info *info, bpc_digest *digest)
{
DigestInfo *d = bpc_hashtable_find(&info->ht, digest->digest, digest->len, 0);
if ( !d ) return -1;
bpc_hashtable_nodeDelete(&info->ht, d);
return 0;
}
int bpc_poolRefIncr(bpc_refCount_info *info, bpc_digest *digest, int32 delta)
{
DigestInfo *d = bpc_hashtable_find(&info->ht, digest->digest, digest->len, 1);
if ( d->key.key == digest ) {
/*
* new entry - copy in digest
*/
d->digest = *digest;
d->key.key = d->digest.digest;
}
d->count += delta;
if ( BPC_LogLevel >= 8 ) {
char hexStr[BPC_DIGEST_LEN_MAX * 2 + 1];
bpc_digest_digest2str(&d->digest, hexStr);
bpc_logMsgf("bpc_poolRefIncr(%s, %d), count now %d\n", hexStr, delta, d->count);
}
return d->count;
}
int bpc_poolRefIterate(bpc_refCount_info *info, bpc_digest *digest, int32 *count, uint *idx)
{
DigestInfo *d = bpc_hashtable_nextEntry(&info->ht, idx);
if ( !d ) return -1;
*digest = d->digest;
*count = d->count;
return 0;
}
void bpc_poolRefPrintEntry(DigestInfo *info)
{
char hexStr[BPC_DIGEST_LEN_MAX * 2 + 1];
bpc_digest_digest2str(&info->digest, hexStr);
fprintf(stderr, "%-20s %d\n", hexStr, info->count);
}
void bpc_poolRefCountPrint(bpc_refCount_info *info)
{
bpc_hashtable_iterate(&info->ht, (void*)bpc_poolRefPrintEntry, NULL);
}
static void write_file_flush(write_info *out)
{
uchar *p = out->buf;
while ( p < out->bufP ) {
int nWrite = write(out->fd, p, out->bufP - p);
if ( nWrite < 0 ) {
if ( errno == EINTR ) continue;
out->errorCnt++;
return;
}
p += nWrite;
}
out->bufP = out->buf;
}
static int bpc_poolRef_read_more_data(int fd, uchar *buf, size_t bufSize, size_t *nRead, uchar **bufPP, char *fileName)
{
int thisRead;
/*
* move the remaining part of the buffer down, and read more data
*/
*nRead = (buf + *nRead) - *bufPP;
if ( *nRead > 0 ) memmove(buf, *bufPP, *nRead);
*bufPP = buf;
do {
do {
thisRead = read(fd, buf + *nRead, bufSize - *nRead);
} while ( thisRead < 0 && errno == EINTR );
if ( thisRead < 0 ) {
bpc_logErrf("bpc_poolRefFileRead: can't read more bytes from %s (errno %d)\n", fileName, errno);
return -1;
}
if ( BPC_LogLevel >= 8 ) bpc_logMsgf("bpc_poolRef_read_more_data: read %d bytes (nRead = %d, sizeof(buf) = %d)\n", thisRead, *nRead, bufSize);
*nRead += thisRead;
} while ( thisRead > 0 && *nRead < sizeof(buf) );
return 0;
}
/*
* Read variable-length unsigned integer in 7 bit chunks, LSB first.
*
* To handle signed numbers, the very first LSB is a sign bit, meaning the first byte
* stores just 6 bits.
*/
static int64 getVarInt(uchar **bufPP, uchar *bufLast)
{
int64 result = 0;
uchar *bufP = *bufPP, c = '\0';
int i = 6, negative = 0;
if ( bufP < bufLast ) {
c = *bufP++;
negative = c & 0x1;
result = (c & 0x7e) >> 1;
}
while ( bufP < bufLast && (c & 0x80) ) {
c = *bufP++;
result |= (c & 0x7f) << i;
i += 7;
}
*bufPP = bufP;
if ( negative ) result = -result;
return result;
}
/*
* Write variable-length unsigned integer in 7 bit chunks, LSB first.
*
* To handle signed numbers, the very first LSB is a sign bit, meaning the first byte
* stores just 6 bits.
*/
static void setVarInt(uchar **bufPP, uchar *bufLast, int64 value)
{
uchar *bufP = *bufPP;
int negative = 0;
if ( value < 0 ) {
value = -value;
negative = 1;
}
if ( bufP < bufLast ) {
uchar c = ((value & 0x3f) << 1) | negative;
value >>= 6;
if ( value ) c |= 0x80;
*bufP++ = c;
}
while ( value && bufP < bufLast ) {
uchar c = value & 0x7f;
value >>= 7;
if ( value ) c |= 0x80;
*bufP++ = c;
}
*bufPP = bufP;
}
static void bpc_poolRefFileWriteEntry(DigestInfo *info, write_info *out)
{
if ( out->bufP > out->buf + sizeof(out->buf) - BPC_DIGEST_LEN_MAX - 16 ) write_file_flush(out);
*out->bufP++ = (uchar)info->digest.len;
memcpy(out->bufP, info->digest.digest, info->digest.len);
out->bufP += info->digest.len;
setVarInt(&out->bufP, out->buf + sizeof(out->buf), info->count);
}
/*
* Write a pool reference file from the hash table.
*/
int bpc_poolRefFileWrite(bpc_refCount_info *info, char *fileName)
{
write_info out;
out.errorCnt = 0;
out.bufP = out.buf;
out.fd = open(fileName, O_WRONLY | O_CREAT | O_TRUNC, 0666);
if ( out.fd < 0 ) {
/*
* Maybe the directory doesn't exist - try to create it and try again
*/
bpc_strBuf *dir = bpc_strBuf_new();
char *p;
bpc_strBuf_snprintf(dir, 0, "%s", fileName);
if ( (p = strrchr(dir->s, '/')) ) {
*p = '\0';
bpc_path_create(dir->s);
out.fd = open(fileName, O_WRONLY | O_CREAT | O_TRUNC, 0666);
}
bpc_strBuf_free(dir);
if ( out.fd < 0 ) {
bpc_logErrf("bpc_poolRefFileWrite: can't open/create pool delta file name %s (errno %d)\n", fileName, errno);
out.errorCnt++;
return out.errorCnt;
}
}
/*
* start with the magic number, then the total number of entries
*/
CONV_UINT32_TO_BUF(out.bufP, BPC_POOL_REF_MAGIC);
setVarInt(&out.bufP, out.buf + sizeof(out.buf), bpc_hashtable_entryCount(&info->ht));
/*
* now write all the digests and counts
*/
bpc_hashtable_iterate(&info->ht, (void*)bpc_poolRefFileWriteEntry, &out);
if ( out.bufP > out.buf ) write_file_flush(&out);
if ( close(out.fd) < 0 ) {
bpc_logErrf("bpc_poolRefFileWrite: pool delta close failed to %s (errno %d)\n", fileName, errno);
out.errorCnt++;
}
return out.errorCnt;
}
/*
* Read a pool reference file into the hash table, which should be already initialized.
*/
int bpc_poolRefFileRead(bpc_refCount_info *info, char *fileName)
{
int fd = open(fileName, O_RDONLY);
uint32 entryCnt, i;
bpc_digest digest;
int64 count;
size_t nRead = 0;
uint32 magic;
uchar buf[8 * 65536];
uchar *bufP = buf;
if ( fd < 0 ) {
bpc_logErrf("bpc_poolRefFileRead: can't open %s (errno %d)\n", fileName, errno);
return -1;
}
if ( bpc_poolRef_read_more_data(fd, buf, sizeof(buf), &nRead, &bufP, fileName) < 0 ) {
bpc_logErrf("bpc_poolRefFileRead: can't read data from %s (errno %d)\n", fileName, errno);
return -1;
}
magic = CONV_BUF_TO_UINT32(bufP);
bufP += 4;
if ( magic != BPC_POOL_REF_MAGIC ) {
bpc_logErrf("bpc_poolRefFileRead: bad magic number 0x%x (expected 0x%x)\n", magic, BPC_POOL_REF_MAGIC);
return -1;
}
entryCnt = getVarInt(&bufP, buf + nRead);
if ( BPC_LogLevel >= 4 ) bpc_logMsgf("bpc_poolRefFileRead: got %d entries (nRead = %d)\n", entryCnt, nRead);
/*
* make sure the hash table is big enough in one go to avoid multiple doublings
*/
bpc_hashtable_growSize(&info->ht, entryCnt * 4 / 3);
for ( i = 0 ; i < entryCnt ; i++ ) {
DigestInfo *digestInfo;
if ( nRead == sizeof(buf) && bufP > buf + nRead - 64
&& bpc_poolRef_read_more_data(fd, buf, sizeof(buf), &nRead, &bufP, fileName) < 0 ) {
bpc_logErrf("bpc_poolRefFileRead: can't read more data from %s (errno %d)\n", fileName, errno);
return -1;
}
digest.len = *bufP++;
if ( digest.len > (int)sizeof(digest.digest) ) digest.len = sizeof(digest.digest);
memcpy(digest.digest, bufP, digest.len);
bufP += digest.len;
count = getVarInt(&bufP, buf + nRead);
if ( BPC_LogLevel >= 7 ) bpc_logMsgf("bpc_poolRefFileRead: entry %d: digest len = %d, digest = 0x%02x%02x%02x...., count = %d\n",
i, digest.len, digest.digest[0], digest.digest[1], digest.digest[2], count);
digestInfo = bpc_hashtable_find(&info->ht, digest.digest, digest.len, 1);
if ( digestInfo->key.key == digest.digest ) {
/*
* new entry since the key points to our key - copy info into new node and set key locally
*/
digestInfo->digest = digest;
digestInfo->key.key = digestInfo->digest.digest;
}
digestInfo->count = count;
}
close(fd);
return 0;
}
/*
* Mark this host backup as needing an fsck. Multiple requests can be supported with
* unique numbers. ext == 0 is used for the overall backup process, and it is removed when
* the backup finished. Various errors can use other extensions. If any files are
* present, an fsck is done either by the next backup, BackupPC_refCountUpdate or
* BackupPC_fsck.
*/
void bpc_poolRefRequestFsck(char *backupDir, int ext)
{
bpc_strBuf *fileName = bpc_strBuf_new();
int fd;
bpc_strBuf_snprintf(fileName, 0, "%s/refCnt/needFsck%d", backupDir, ext);
if ( (fd = open(fileName->s, O_CREAT | O_WRONLY, 0660)) < 0 ) {
bpc_logErrf("bpc_poolRefRequestFsck: can't open/create fsck request file %s (errno %d)\n", fileName->s, errno);
}
bpc_strBuf_free(fileName);
}
/***********************************************************************
* Reference count deltas - we maintain two hash tables for uncompressed
* and compressed deltas.
***********************************************************************/
/*
* Legacy support for <= 4.0.0beta3.
*/
static bpc_deltaCount_info DeltaInfoOld;
static int OutputFileCnt = 0;
void bpc_poolRefDeltaFileInit(bpc_deltaCount_info *info, char *hostDir)
{
info->targetDir = bpc_strBuf_new();
bpc_strBuf_strcpy(info->targetDir, 0, hostDir);
bpc_poolRefInit(&info->refCnt[0], 256);
bpc_poolRefInit(&info->refCnt[1], 1 << 20);
info->refCnt[0].initDone = info->refCnt[1].initDone = 1;
}
void bpc_poolRefDeltaFileDestroy(bpc_deltaCount_info *info)
{
bpc_strBuf_free(info->targetDir);
bpc_poolRefDestroy(&info->refCnt[0]);
bpc_poolRefDestroy(&info->refCnt[1]);
}
uint32 bpc_poolRefDeltaFileFlush(bpc_deltaCount_info *info)
{
bpc_strBuf *tempFileName, *finalFileName;
int compress;
int errorCnt = 0;
int fd;
if ( !info ) info = &DeltaInfoOld; /* backward compatibility */
if ( !info->refCnt[0].initDone ) return 1;
tempFileName = bpc_strBuf_new();
finalFileName = bpc_strBuf_new();
for ( compress = 0 ; compress < 2 ; compress++ ) {
uint entryCnt = bpc_hashtable_entryCount(&info->refCnt[compress].ht);
if ( entryCnt == 0 ) continue;
do {
bpc_strBuf_snprintf(tempFileName, 0, "%s/refCnt/tpoolCntDelta_%d_%d_%d_%d",
info->targetDir->s, compress, BPC_TmpFileUnique, OutputFileCnt, getpid());
if ( (fd = open(tempFileName->s, O_RDONLY, 0666)) >= 0 ) {
close(fd);
OutputFileCnt++;
}
} while ( fd >= 0 );
errorCnt += bpc_poolRefFileWrite(&info->refCnt[compress], tempFileName->s);
if ( errorCnt ) {
unlink(tempFileName->s);
continue;
}
bpc_strBuf_snprintf(finalFileName, 0, "%s/refCnt/poolCntDelta_%d_%d_%d_%d",
info->targetDir->s, compress, BPC_TmpFileUnique >= 0 ? BPC_TmpFileUnique : 0, OutputFileCnt, getpid());
if ( rename(tempFileName->s, finalFileName->s) != 0 ) {
bpc_logErrf("bpc_poolRefDeltaFileFlush: can't rename %s to %s (errno %d)\n", tempFileName->s, finalFileName->s, errno);
unlink(tempFileName->s);
errorCnt++;
}
if ( !errorCnt ) {
bpc_hashtable_erase(&info->refCnt[compress].ht);
}
}
OutputFileCnt++;
if ( errorCnt ) {
/*
* Need to fsck this particular backup on this host
*/
bpc_poolRefRequestFsck(info->targetDir->s, getpid());
}
bpc_strBuf_free(tempFileName);
bpc_strBuf_free(finalFileName);
return errorCnt;
}
void bpc_poolRefDeltaUpdate(bpc_deltaCount_info *info, int compress, bpc_digest *digest, int32 count)
{
DigestInfo *digestInfo;
if ( !info ) info = &DeltaInfoOld; /* backward compatibility */
if ( !digest || digest->len == 0 ) return;
if ( !info->refCnt[0].initDone ) return;
digestInfo = bpc_hashtable_find(&info->refCnt[compress ? 1 : 0].ht, digest->digest, digest->len, 1);
if ( digestInfo->key.key == digest->digest ) {
/*
* new entry since the key points to our key - copy info into new node and set key locally
*/
digestInfo->digest = *digest;
digestInfo->key.key = digestInfo->digest.digest;
}
digestInfo->count += count;
if ( BPC_LogLevel >= 8 ) {
char hexStr[BPC_DIGEST_LEN_MAX * 2 + 1];
bpc_digest_digest2str(&digestInfo->digest, hexStr);
bpc_logMsgf("bpc_poolRefDeltaUpdate(%s, %d), count now %d\n", hexStr, count, digestInfo->count);
}
if ( bpc_hashtable_entryCount(&info->refCnt[compress ? 1 : 0].ht) > (1 << 20) ) {
bpc_poolRefDeltaFileFlush(info);
}
}
void bpc_poolRefDeltaPrint(bpc_deltaCount_info *info)
{
if ( !info ) info = &DeltaInfoOld; /* backward compatibility */
if ( !info->refCnt[0].initDone ) return;
fprintf(stderr, "Uncompressed HT:\n");
bpc_hashtable_iterate(&info->refCnt[0].ht, (void*)bpc_poolRefPrintEntry, NULL);
fprintf(stderr, "Compressed HT:\n");
bpc_hashtable_iterate(&info->refCnt[1].ht, (void*)bpc_poolRefPrintEntry, NULL);
}
/*
* Legacy support for <= 4.0.0beta3.
*/
void bpc_poolRefDeltaFileInitOld(char *hostDir)
{
bpc_poolRefDeltaFileInit(&DeltaInfoOld, hostDir);
}
uint32 bpc_poolRefDeltaFileFlushOld(void)
{
return bpc_poolRefDeltaFileFlush(&DeltaInfoOld);
}
/*
* Increment/decrement the reference count for the given digest
*/
void bpc_poolRefDeltaUpdateOld(int compress, bpc_digest *digest, int32 count)
{
bpc_poolRefDeltaUpdate(&DeltaInfoOld, compress, digest, count);
}
void bpc_poolRefDeltaPrintOld(void)
{
bpc_poolRefDeltaPrint(&DeltaInfoOld);
}
rsync-bpc-3.1.3.0/batch.c 0000664 0000000 0000000 00000015315 13737671777 0015037 0 ustar 00root root 0000000 0000000 /*
* Support for the batch-file options.
*
* Copyright (C) 1999 Weiss
* Copyright (C) 2004 Chris Shoemaker
* Copyright (C) 2004-2018 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
#include
extern int eol_nulls;
extern int recurse;
extern int xfer_dirs;
extern int preserve_links;
extern int preserve_hard_links;
extern int preserve_devices;
extern int preserve_uid;
extern int preserve_gid;
extern int preserve_acls;
extern int preserve_xattrs;
extern int always_checksum;
extern int do_compression;
extern int inplace;
extern int append_mode;
extern int protocol_version;
extern char *batch_name;
#ifdef ICONV_OPTION
extern char *iconv_opt;
#endif
extern filter_rule_list filter_list;
int batch_stream_flags;
static int tweaked_append;
static int tweaked_append_verify;
static int tweaked_iconv;
static int *flag_ptr[] = {
&recurse, /* 0 */
&preserve_uid, /* 1 */
&preserve_gid, /* 2 */
&preserve_links, /* 3 */
&preserve_devices, /* 4 */
&preserve_hard_links, /* 5 */
&always_checksum, /* 6 */
&xfer_dirs, /* 7 (protocol 29) */
&do_compression, /* 8 (protocol 29) */
&tweaked_iconv, /* 9 (protocol 30) */
&preserve_acls, /* 10 (protocol 30) */
&preserve_xattrs, /* 11 (protocol 30) */
&inplace, /* 12 (protocol 30) */
&tweaked_append, /* 13 (protocol 30) */
&tweaked_append_verify, /* 14 (protocol 30) */
NULL
};
static char *flag_name[] = {
"--recurse (-r)",
"--owner (-o)",
"--group (-g)",
"--links (-l)",
"--devices (-D)",
"--hard-links (-H)",
"--checksum (-c)",
"--dirs (-d)",
"--compress (-z)",
"--iconv",
"--acls (-A)",
"--xattrs (-X)",
"--inplace",
"--append",
"--append-verify",
NULL
};
void write_stream_flags(int fd)
{
int i, flags;
tweaked_append = append_mode == 1;
tweaked_append_verify = append_mode == 2;
#ifdef ICONV_OPTION
tweaked_iconv = iconv_opt != NULL;
#endif
/* Start the batch file with a bitmap of data-stream-affecting
* flags. */
for (i = 0, flags = 0; flag_ptr[i]; i++) {
if (*flag_ptr[i])
flags |= 1 << i;
}
write_int(fd, flags);
}
void read_stream_flags(int fd)
{
batch_stream_flags = read_int(fd);
}
void check_batch_flags(void)
{
int i;
if (protocol_version < 29)
flag_ptr[7] = NULL;
else if (protocol_version < 30)
flag_ptr[9] = NULL;
tweaked_append = append_mode == 1;
tweaked_append_verify = append_mode == 2;
#ifdef ICONV_OPTION
tweaked_iconv = iconv_opt != NULL;
#endif
for (i = 0; flag_ptr[i]; i++) {
int set = batch_stream_flags & (1 << i) ? 1 : 0;
if (*flag_ptr[i] != set) {
if (i == 9) {
rprintf(FERROR,
"%s specify the --iconv option to use this batch file.\n",
set ? "Please" : "Do not");
exit_cleanup(RERR_SYNTAX);
}
if (INFO_GTE(MISC, 1)) {
rprintf(FINFO,
"%sing the %s option to match the batchfile.\n",
set ? "Sett" : "Clear", flag_name[i]);
}
*flag_ptr[i] = set;
}
}
if (protocol_version < 29) {
if (recurse)
xfer_dirs |= 1;
else if (xfer_dirs < 2)
xfer_dirs = 0;
}
if (tweaked_append)
append_mode = 1;
else if (tweaked_append_verify)
append_mode = 2;
}
static int write_arg(int fd, char *arg)
{
char *x, *s;
int len, ret = 0;
if (*arg == '-' && (x = strchr(arg, '=')) != NULL) {
if (write(fd, arg, x - arg + 1) != x - arg + 1)
ret = -1;
arg += x - arg + 1;
}
if (strpbrk(arg, " \"'&;|[]()$#!*?^\\") != NULL) {
if (write(fd, "'", 1) != 1)
ret = -1;
for (s = arg; (x = strchr(s, '\'')) != NULL; s = x + 1) {
if (write(fd, s, x - s + 1) != x - s + 1
|| write(fd, "'", 1) != 1)
ret = -1;
}
len = strlen(s);
if (write(fd, s, len) != len
|| write(fd, "'", 1) != 1)
ret = -1;
return ret;
}
len = strlen(arg);
if (write(fd, arg, len) != len)
ret = -1;
return ret;
}
static void write_filter_rules(int fd)
{
filter_rule *ent;
write_sbuf(fd, " <<'#E#'\n");
for (ent = filter_list.head; ent; ent = ent->next) {
unsigned int plen;
char *p = get_rule_prefix(ent, "- ", 0, &plen);
write_buf(fd, p, plen);
write_sbuf(fd, ent->pattern);
if (ent->rflags & FILTRULE_DIRECTORY)
write_byte(fd, '/');
write_byte(fd, eol_nulls ? 0 : '\n');
}
if (eol_nulls)
write_sbuf(fd, ";\n");
write_sbuf(fd, "#E#");
}
/* This routine tries to write out an equivalent --read-batch command
* given the user's --write-batch args. However, it doesn't really
* understand most of the options, so it uses some overly simple
* heuristics to munge the command line into something that will
* (hopefully) work. */
void write_batch_shell_file(int argc, char *argv[], int file_arg_cnt)
{
int fd, i, len, err = 0;
char *p, filename[MAXPATHLEN];
stringjoin(filename, sizeof filename,
batch_name, ".sh", NULL);
fd = do_open(filename, O_WRONLY | O_CREAT | O_TRUNC,
S_IRUSR | S_IWUSR | S_IXUSR);
if (fd < 0) {
rsyserr(FERROR, errno, "Batch file %s open error",
filename);
exit_cleanup(RERR_FILESELECT);
}
/* Write argvs info to BATCH.sh file */
if (write_arg(fd, argv[0]) < 0)
err = 1;
if (filter_list.head) {
if (protocol_version >= 29)
write_sbuf(fd, " --filter=._-");
else
write_sbuf(fd, " --exclude-from=-");
}
for (i = 1; i < argc - file_arg_cnt; i++) {
p = argv[i];
if (strncmp(p, "--files-from", 12) == 0
|| strncmp(p, "--filter", 8) == 0
|| strncmp(p, "--include", 9) == 0
|| strncmp(p, "--exclude", 9) == 0) {
if (strchr(p, '=') == NULL)
i++;
continue;
}
if (strcmp(p, "-f") == 0) {
i++;
continue;
}
if (write(fd, " ", 1) != 1)
err = 1;
if (strncmp(p, "--write-batch", len = 13) == 0
|| strncmp(p, "--only-write-batch", len = 18) == 0) {
if (write(fd, "--read-batch", 12) != 12)
err = 1;
if (p[len] == '=') {
if (write(fd, "=", 1) != 1
|| write_arg(fd, p + len + 1) < 0)
err = 1;
}
} else {
if (write_arg(fd, p) < 0)
err = 1;
}
}
if (!(p = check_for_hostspec(argv[argc - 1], &p, &i)))
p = argv[argc - 1];
if (write(fd, " ${1:-", 6) != 6
|| write_arg(fd, p) < 0)
err = 1;
write_byte(fd, '}');
if (filter_list.head)
write_filter_rules(fd);
if (write(fd, "\n", 1) != 1 || close(fd) < 0 || err) {
rsyserr(FERROR, errno, "Batch file %s write error",
filename);
exit_cleanup(RERR_FILEIO);
}
}
rsync-bpc-3.1.3.0/bpc_sysCalls.c 0000664 0000000 0000000 00000232656 13737671777 0016410 0 ustar 00root root 0000000 0000000 /*
* Emulate system calls for BackupPC.
*
* Copyright (C) 2013 Craig Barratt.
*
* 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 "backuppc/backuppc.h"
#include "ifuncs.h"
#include "lib/sysxattrs.h"
#define MAX_FD (64)
#define MAX_BUF_SZ (8 << 20) /* 8MB */
/*
* A freelist of unused MAX_BUF_SZ sized-buffers.
* We use the first sizeof(void*) bytes of the buffer as a single-linked
* list, with a NULL at the end
*/
static void *DataBufferFreeList = (void*)NULL;
extern int am_generator;
extern int always_checksum;
extern int preserve_hard_links;
extern int protocol_version;
extern int preserve_times;
static bpc_attribCache_info acNew;
static bpc_attribCache_info acOld;
static int acOldUsed;
static bpc_deltaCount_info DeltaNew;
static bpc_deltaCount_info DeltaOld;
static int LogLevel;
static int DoneInit = 0;
static int CompressLevel;
typedef struct _bpc_sysCall_stats {
ino_t Inode0, InodeCurr;
int64 ErrorCnt;
int64 ExistFileCnt, ExistFileSize, ExistFileCompSize;
int64 NewFileCnt, NewFileSize, NewFileCompSize;
int64 TotalFileCnt, TotalFileSize;
} bpc_sysCall_stats;
static bpc_sysCall_stats Stats;
static void logMsgCB(UNUSED(int errFlag), char *mesg, size_t mesgLen)
{
fwrite(mesg, 1, mesgLen, stderr);
fflush(stderr);
//rwrite(errFlag ? FERROR : FINFO, mesg, mesgLen, 0);
}
void bpc_sysCall_init(
char *topDir, /* backuppc top-level data dir path */
char *hostName, /* host name */
char *shareNameUM, /* unmangled share name */
int newBkupNum, /* new backup number */
int newCompress, /* compression level for new backup */
int prevBkupNum, /* prior backup number (or -1) */
int prevCompress, /* comperssion level for prior backup */
char *mergeBkupInfo, /* which backups to merge together on read */
ino_t inode0, /* starting inode number for this backup */
int attrib_new, /* flag to turn on new-style attrib file names */
int logLevel /* logging level */
)
{
bpc_strBuf *hostDir = bpc_strBuf_new();
extern int BPC_HardLinkMax;
extern int BPC_PoolV3Enabled;
bpc_logMsgCBSet(logMsgCB);
bpc_lib_conf_init(topDir, BPC_HardLinkMax, BPC_PoolV3Enabled, logLevel);
bpc_attribCache_init(&acNew, hostName, newBkupNum, shareNameUM, newCompress);
bpc_strBuf_snprintf(hostDir, 0, "%s/pc/%s/%d", topDir, hostName, newBkupNum);
bpc_poolRefDeltaFileInit(&DeltaNew, hostDir->s);
bpc_attribCache_setDeltaInfo(&acNew, &DeltaNew);
CompressLevel = newCompress;
if ( prevBkupNum >= 0 ) {
bpc_attribCache_init(&acOld, hostName, prevBkupNum, shareNameUM, prevCompress);
bpc_strBuf_snprintf(hostDir, 0, "%s/pc/%s/%d", topDir, hostName, prevBkupNum);
bpc_poolRefDeltaFileInit(&DeltaOld, hostDir->s);
bpc_attribCache_setDeltaInfo(&acOld, &DeltaOld);
acOldUsed = 1;
} else {
acOldUsed = 0;
}
bpc_strBuf_free(hostDir);
Stats.InodeCurr = Stats.Inode0 = inode0;
LogLevel = logLevel;
/*
* If attrib_new, write new-style attrib files (<= 4.0.0beta3 uses old-style), which
* are 0-length files with the digest encoded in the file name (eg: attrib_md5HexDigest).
* We can still read the old-style files, but we upgrade them as we go.
*/
bpc_attrib_backwardCompat(!attrib_new, !attrib_new);
if ( mergeBkupInfo && *mergeBkupInfo ) {
/*
* Count number of backups to merge: 1 + number of commas.
*/
int i, bkupCnt = 1;
char *p = mergeBkupInfo;
bpc_backup_info *bkupList;
while ( (p = strchr(p + 1, ',')) ) {
bkupCnt++;
}
p = mergeBkupInfo;
if ( !(bkupList = calloc(bkupCnt, sizeof(bpc_backup_info))) ) {
bpc_logErrf("bpc_sysCall_init: can't allocate backup list (%d)\n", bkupCnt);
return;
}
for ( i = 0 ; i < bkupCnt ; i++ ) {
if ( sscanf(p, "%d/%d/%d", &bkupList[i].num, &bkupList[i].compress, &bkupList[i].version) != 3 ) {
bpc_logErrf("bpc_sysCall_init: can't parse bkup info string %s\n", p);
return;
}
if ( !(p = strchr(p, ',')) ) break;
p++;
}
bpc_attribCache_setMergeList(&acNew, bkupList, bkupCnt);
}
DoneInit = 1;
}
void bpc_am_generator(int generator, int pid)
{
if ( generator ) {
Stats.InodeCurr = 2 * (Stats.InodeCurr / 2) + 0;
bpc_logMsgf("xferPids %d,%d\n", getpid(), pid);
} else {
Stats.InodeCurr = 2 * (Stats.InodeCurr / 2) + 1;
bpc_attribCache_readOnly(&acNew, 1);
if ( acOldUsed ) bpc_attribCache_readOnly(&acOld, 1);
}
bpc_lib_setTmpFileUnique(generator);
}
int bpc_sysCall_cleanup(void)
{
fflush(stdout);
fflush(stderr);
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_sysCall_cleanup: doneInit = %d\n", DoneInit);
if ( !DoneInit ) return 0;
if ( am_generator ) {
if ( preserve_hard_links ) hard_link_bpc_update_link_count();
bpc_attribCache_flush(&acNew, 1, NULL);
if ( acOldUsed ) bpc_attribCache_flush(&acOld, 1, NULL);
}
if ( LogLevel >= 6 ) {
fprintf(stderr, "RefCnt Deltas for new backup\n");
bpc_poolRefDeltaPrint(&DeltaNew);
if ( acOldUsed ) {
fprintf(stderr, "RefCnt Deltas for prev backup\n");
bpc_poolRefDeltaPrint(&DeltaOld);
}
}
Stats.ErrorCnt += bpc_poolRefDeltaFileFlush(&DeltaNew);
if ( acOldUsed ) {
Stats.ErrorCnt += bpc_poolRefDeltaFileFlush(&DeltaOld);
}
fprintf(stderr, "%s: %llu errors, %llu filesExist, %llu sizeExist, %llu sizeExistComp, %llu filesTotal, %llu sizeTotal, %llu filesNew, %llu sizeNew, %llu sizeNewComp, %llu inode\n",
am_generator ? "DoneGen" : "Done",
(unsigned long long)Stats.ErrorCnt,
(unsigned long long)Stats.ExistFileCnt,
(unsigned long long)Stats.ExistFileSize,
(unsigned long long)Stats.ExistFileCompSize,
(unsigned long long)Stats.TotalFileCnt,
(unsigned long long)Stats.TotalFileSize,
(unsigned long long)Stats.NewFileCnt,
(unsigned long long)Stats.NewFileSize,
(unsigned long long)Stats.NewFileCompSize,
(unsigned long long)Stats.InodeCurr);
fflush(stdout);
fflush(stderr);
return Stats.ErrorCnt;
}
void bpc_progress_fileDone(void)
{
static int fileCnt = 0, fileCntNext = 1;
fileCnt++;
if ( fileCnt < fileCntNext ) return;
fileCntNext = fileCnt + 20;
fprintf(stderr, "__bpc_progress_fileCnt__ %d\n", fileCnt);
}
void bpc_sysCall_statusFileSize(unsigned long fileSize)
{
Stats.TotalFileCnt++;
Stats.TotalFileSize += fileSize;
bpc_progress_fileDone();
}
void bpc_sysCall_setInode0Debug(int inode0, char *hostName, char *shareNameUM, int prevBkupNum, int prevCompress)
{
Stats.Inode0 = inode0;
if ( prevBkupNum >= 0 ) {
bpc_attribCache_init(&acOld, hostName, prevBkupNum, shareNameUM, prevCompress);
acOldUsed = 1;
}
}
/*
* File handling
*/
typedef struct {
int used;
int fdNum;
int flags;
int dirty;
int mode;
int fdUnusedNext;
off_t posn;
off_t fileSize;
int tmpFd;
bpc_strBuf *fileName;
bpc_strBuf *tmpFileName;
char *buffer;
size_t bufferSize;
bpc_digest digest;
} FdInfo;
static FdInfo Fd[MAX_FD];
/*
* We keep a simple integer index free list. This is the head of the free list.
* Fd[i].fdUnusedNext points to the next entry on the free list.
*/
static int FdUnused = -1;
/*
* Find a spare file descriptor. The integer file descriptors we return
* here have no relation to real file descriptors. They are simply handles
* that allow us to index into the $io->{fileDesc} array. So long as the
* caller uses the returned file descriptor only to call these functions
* (ie: not to directly make IO system calls) then we are ok.
*/
static int bpc_fileDescriptorNew(void)
{
int i;
if ( FdUnused < 0 ) {
/*
* initialize the free list
*/
FdUnused = 3;
for ( i = FdUnused ; i < MAX_FD ; i++ ) {
Fd[i].used = 0;
Fd[i].fdNum = i;
Fd[i].tmpFd = -1;
Fd[i].fdUnusedNext = i + 1;
}
Fd[MAX_FD-1].fdUnusedNext = -1;
}
i = FdUnused;
if ( !Fd[i].fileName ) {
Fd[i].fileName = bpc_strBuf_new();
Fd[i].tmpFileName = bpc_strBuf_new();
}
if ( i >= 0 ) {
FdUnused = Fd[i].fdUnusedNext;
return i;
} else {
bpc_logErrf("bpc_fileDescriptorNew: out of file descriptors\n");
Stats.ErrorCnt++;
return -1;
}
}
static void bpc_fileDescFree(FdInfo *fd)
{
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_fileDescFree: fdNum = %d, tmpFd = %d, tmpFileName = %s\n", fd->fdNum, fd->tmpFd, fd->tmpFd >= 0 ? fd->tmpFileName->s : "NULL");
if ( fd->tmpFd >= 0 ) {
close(fd->tmpFd);
unlink(fd->tmpFileName->s);
fd->tmpFd = -1;
}
if ( fd->buffer ) {
*(void**)fd->buffer = DataBufferFreeList;
DataBufferFreeList = fd->buffer;
}
fd->used = 0;
fd->buffer = NULL;
fd->fdUnusedNext = FdUnused;
FdUnused = fd->fdNum;
}
static int TmpFileCnt = 0;
static int bpc_fileWriteBuffer(int fdNum, char *buffer, size_t nBytes)
{
while ( nBytes > 0 ) {
ssize_t nWrite = write(fdNum, buffer, nBytes);
if ( nWrite < 0 ) {
if ( errno == EINTR ) continue;
return -1;
}
buffer += nWrite;
nBytes -= nWrite;
}
return 0;
}
/*
* Create a temporary output file and write the existing data buffer there
*/
static int bpc_fileSwitchToDisk(bpc_attribCache_info *ac, FdInfo *fd)
{
bpc_strBuf_snprintf(fd->tmpFileName, 0, "%s/rsyncTmp.%d.%d.%d", ac->backupTopDir->s, getpid(), am_generator, TmpFileCnt++);
if ( (fd->tmpFd = open(fd->tmpFileName->s, O_RDWR | O_CREAT | O_TRUNC, 0600)) < 0 ) {
bpc_logErrf("bpc_fileSwitchToDisk: can't open/create %s for writing\n", fd->tmpFileName->s);
Stats.ErrorCnt++;
return -1;
}
if ( fd->fileSize > 0 && bpc_fileWriteBuffer(fd->tmpFd, fd->buffer, fd->fileSize) ) return -1;
if ( lseek(fd->tmpFd, fd->posn, SEEK_SET) != fd->posn ) {
bpc_logErrf("bpc_fileSwitchToDisk: unable to seek %s to %lu\n", fd->tmpFileName->s, (unsigned long)fd->posn);
Stats.ErrorCnt++;
return -1;
}
return 0;
}
/*
* Open a file and cache the file handle and information. Returns a pointer
* to an FdInfo structure, or NULL on error.
*
* The file is either stored in memory (fh->buffer) or a regular
* uncompressed unbuffered read-write file with handle fh->tmpFd.
*
* The current seek position is fh->posn.
*
* If you call fileClose() first, then fileOpen() with $write <= 0, you are
* guaranteed to get just the read-only BackupPC::FileZIO handle fh->fhRead
* or the in-memory fh->buffer.
*
* The following flags determine behavior:
* O_RDONLY, O_WRONLY, O_RDWR, O_CREAT, O_TRUNC, O_APPEND
*/
static FdInfo *bpc_fileOpen(bpc_attribCache_info *ac, char *fileName, int flags)
{
bpc_attrib_file *file;
int fdNum;
FdInfo *fd;
file = bpc_attribCache_getFile(&acNew, fileName, 0, 0);
if ( !file && !(flags & O_CREAT) ) return NULL;
if ( (fdNum = bpc_fileDescriptorNew()) < 0 ) return NULL;
fd = &Fd[fdNum];
fd->used = 1;
fd->posn = 0;
fd->fdNum = fdNum;
fd->flags = flags;
fd->dirty = 0;
fd->bufferSize = MAX_BUF_SZ;
if ( DataBufferFreeList ) {
fd->buffer = DataBufferFreeList;
DataBufferFreeList = *(void**)DataBufferFreeList;
} else {
fd->buffer = malloc(fd->bufferSize * sizeof(fd->buffer[0]));
}
fd->fileSize = 0;
if ( !fd->buffer ) {
bpc_logErrf("bpc_fileOpen: fatal error: can't allocate %lu bytes for data buffer\n", MAX_BUF_SZ);
bpc_fileDescFree(fd);
return NULL;
}
bpc_strBuf_strcpy(fd->fileName, 0, fileName);
if ( file && !(flags & O_TRUNC) && !(file->isTemp && file->size == 0) ) {
bpc_strBuf *fullPath = bpc_strBuf_new();
bpc_fileZIO_fd fdz;
/*
* need to read existing file
*/
if ( file->digest.len > 0 || file->size == 0 ) {
/*
* all non-empty V4+ files have digests, so use the digest to look in the pool
*/
if ( file->digest.len > 0 ) {
bpc_digest_md52path(fullPath, file->compress, &file->digest);
} else {
bpc_strBuf_strcpy(fullPath, 0, "/dev/null");
}
if ( bpc_fileZIO_open(&fdz, fullPath->s, 0, file->compress) ) {
bpc_logErrf("bpc_fileOpen: can't open pool file %s (from %s, %d, %d)\n", fullPath->s, fd->fileName->s, file->compress, file->digest.len);
Stats.ErrorCnt++;
bpc_fileDescFree(fd);
bpc_strBuf_free(fullPath);
return NULL;
}
} else {
/*
* either we failed to read the digest (eg, missing inode), or it's a V3 file - look in the backup directory
*/
bpc_attribCache_getFullMangledPath(&acNew, fullPath, (char*)fileName, file->backupNum);
if ( bpc_fileZIO_open(&fdz, fullPath->s, 0, file->compress) ) {
bpc_logErrf("bpc_fileOpen: can't open file %s (from %s, %d, %d, %d)\n",
fullPath->s, fd->fileName->s, file->compress, file->digest.len, file->nlinks);
Stats.ErrorCnt++;
bpc_fileDescFree(fd);
bpc_strBuf_free(fullPath);
return NULL;
}
}
bpc_strBuf_free(fullPath);
fd->fileSize = bpc_fileZIO_read(&fdz, (uchar*)fd->buffer, fd->bufferSize);
if ( fd->fileSize >= (off_t)fd->bufferSize ) {
off_t nRead;
/*
* buffer is full - write to flat disk and then copy the rest of the file
*/
fd->posn = fd->fileSize;
if ( bpc_fileSwitchToDisk(ac, fd) ) {
bpc_fileDescFree(fd);
return NULL;
}
while ( (nRead = bpc_fileZIO_read(&fdz, (uchar*)fd->buffer, fd->bufferSize)) > 0 ) {
if ( bpc_fileWriteBuffer(fd->tmpFd, fd->buffer, nRead) ) {
bpc_logErrf("bpc_fileOpen: bpc_fileWriteBuffer(%d, ..., %lu) failed\n",
fd->tmpFd, nRead);
bpc_fileDescFree(fd);
return NULL;
}
fd->fileSize += nRead;
}
}
bpc_fileZIO_close(&fdz);
}
if ( fd->tmpFd >= 0 ) {
if ( !(flags & O_APPEND) && lseek(fd->tmpFd, 0, SEEK_SET) != 0 ) {
bpc_logErrf("bpc_fileOpen: can't seek to start of file %s\n", fd->tmpFileName->s);
Stats.ErrorCnt++;
bpc_fileDescFree(fd);
return NULL;
}
} else {
if ( (flags & O_APPEND) ) fd->posn = fd->fileSize;
}
return fd;
}
static int bpc_fileWrite(bpc_attribCache_info *ac, FdInfo *fd, char *buf, size_t bufLen)
{
if ( fd->tmpFd < 0 ) {
if ( (size_t)fd->posn + bufLen <= fd->bufferSize ) {
if ( fd->posn + (off_t)bufLen > fd->fileSize || memcmp(fd->buffer + fd->posn, buf, bufLen) ) {
fd->dirty = 1;
memcpy(fd->buffer + fd->posn, buf, bufLen);
}
fd->posn += bufLen;
if ( fd->fileSize < fd->posn ) fd->fileSize = fd->posn;
return 0;
}
/*
* We would overflow the buffer, so write to a file instead
*/
if ( bpc_fileSwitchToDisk(ac, fd) ) return -1;
}
fd->dirty = 1;
return bpc_fileWriteBuffer(fd->tmpFd, buf, bufLen);
}
static int bpc_fileClose(bpc_attribCache_info *ac, FdInfo *fd, int newType, int newMode, char *fileNameLog)
{
bpc_attrib_file *file;
off_t fileSize = 0;
static bpc_poolWrite_info pwInfo;
bpc_digest digest;
int match;
off_t poolFileSize;
int errorCnt;
file = bpc_attribCache_getFile(&acNew, fd->fileName->s, 0, 0);
if ( file && newType < 0 ) newType = file->type;
if ( newType < 0 ) newType = BPC_FTYPE_FILE;
if ( file && file->size != fd->fileSize && ((fd->flags & O_WRONLY) || (fd->flags & O_RDWR)) ) {
fd->dirty = 1;
}
if ( !fd->dirty ) {
if ( (fd->flags & O_WRONLY) || (fd->flags & O_RDWR) ) {
fprintf(stderr, "IOdone: same %s\n", fd->fileName->s);
}
bpc_fileDescFree(fd);
return 0;
}
if ( fd->tmpFd < 0 ) {
fileSize = fd->fileSize;
bpc_poolWrite_open(&pwInfo, ac->compress, NULL);
bpc_poolWrite_write(&pwInfo, (uchar*)fd->buffer, fileSize);
bpc_poolWrite_close(&pwInfo, &match, &digest, &poolFileSize, &errorCnt);
} else {
off_t nRead;
lseek(fd->tmpFd, 0, SEEK_SET);
bpc_poolWrite_open(&pwInfo, ac->compress, NULL);
while ( (nRead = read(fd->tmpFd, fd->buffer, fd->bufferSize)) > 0 ) {
bpc_poolWrite_write(&pwInfo, (uchar*)fd->buffer, nRead);
fileSize += nRead;
}
bpc_poolWrite_close(&pwInfo, &match, &digest, &poolFileSize, &errorCnt);
}
Stats.ErrorCnt += errorCnt;
if ( match ) {
Stats.ExistFileCnt++;
if ( newType == BPC_FTYPE_FILE || newType == BPC_FTYPE_SYMLINK ) {
Stats.ExistFileSize += fileSize;
Stats.ExistFileCompSize += poolFileSize;
}
} else {
Stats.NewFileCnt++;
if ( newType == BPC_FTYPE_FILE || newType == BPC_FTYPE_SYMLINK ) {
Stats.NewFileSize += fileSize;
Stats.NewFileCompSize += poolFileSize;
}
}
if ( file && file->digest.len == digest.len && !memcmp(file->digest.digest, digest.digest, digest.len)
&& file->size == fileSize ) {
/*
* File is unchanged
*/
fprintf(stderr, "IOdone: same %s\n", fd->fileName->s);
bpc_fileDescFree(fd);
return 0;
}
if ( file && !file->isTemp ) {
if ( acOldUsed && file->inode < Stats.Inode0 && !bpc_attribCache_getFile(&acOld, fd->fileName->s, 0, 0) ) {
if ( file->nlinks > 0 ) {
/*
* Only write the inode if it doesn't exist in old;
* in that case increase the pool reference count
*/
if ( bpc_attribCache_setFile(&acOld, fd->fileName->s, file, 1) > 0 ) {
bpc_poolRefDeltaUpdate(&DeltaOld, file->compress, &file->digest, 1);
}
} else {
bpc_attribCache_setFile(&acOld, fd->fileName->s, file, 0);
}
} else {
/*
* The current file is new to this backup and will be replaced below, so reduce
* the ref count of the existing (old) file.
*/
bpc_poolRefDeltaUpdate(&DeltaNew, file->compress, &file->digest, -1);
}
} else if ( acOldUsed && (!file || !file->isTemp) && !bpc_attribCache_getFile(&acOld, fd->fileName->s, 0, 0) ) {
bpc_attrib_file *oldFile = bpc_attribCache_getFile(&acOld, fd->fileName->s, 1, 0);
oldFile->type = BPC_FTYPE_DELETED;
bpc_attribCache_setFile(&acOld, fd->fileName->s, oldFile, 0);
}
if ( !file ) {
file = bpc_attribCache_getFile(&acNew, fd->fileName->s, 1, 0);
file->inode = Stats.InodeCurr;
Stats.InodeCurr += 2;
file->nlinks = 0;
file->mode = fd->mode;
}
file->compress = ac->compress;
file->digest = digest;
if ( newType >= 0 ) file->type = newType;
if ( newMode >= 0 ) file->mode = newMode;
if ( file->type == BPC_FTYPE_FILE || file->type == BPC_FTYPE_SYMLINK ) {
file->size = fileSize;
} else {
file->size = 0;
}
if ( !file->isTemp ) bpc_poolRefDeltaUpdate(&DeltaNew, file->compress, &file->digest, 1);
bpc_attribCache_setFile(&acNew, fd->fileName->s, file, 0);
fprintf(stderr, "IOdone: %s %s\n", match ? "pool" : "new", fileNameLog ? fileNameLog : fd->fileName->s);
bpc_fileDescFree(fd);
return 0;
}
/*
* Read an entire file into the buffer, up until the buffer is full. Returns the number
* of bytes read, or -1 on error.
*/
static off_t bpc_fileReadAll(bpc_attribCache_info *ac, char *fileName, char *buffer, size_t bufferSize)
{
bpc_strBuf *fullPath;
bpc_attrib_file *file;
bpc_fileZIO_fd fd;
off_t nRead;
if ( !(file = bpc_attribCache_getFile(ac, fileName, 0, 0)) ) return -1;
fullPath = bpc_strBuf_new();
if ( file->digest.len > 0 ) {
/*
* V4+ pool file
*/
bpc_digest_md52path(fullPath, file->compress, &file->digest);
} else {
/*
* V3 look in the backup directory
*/
bpc_attribCache_getFullMangledPath(&acNew, fullPath, (char*)fileName, file->backupNum);
}
if ( bpc_fileZIO_open(&fd, fullPath->s, 0, file->compress) ) {
bpc_logErrf("bpc_fileReadAll: can't open %s (from %s)\n", fullPath->s, fileName);
Stats.ErrorCnt++;
bpc_strBuf_free(fullPath);
return -1;
}
nRead = bpc_fileZIO_read(&fd, (uchar*)buffer, bufferSize);
bpc_fileZIO_close(&fd);
bpc_strBuf_free(fullPath);
return nRead;
}
/*
* Directory handling
*/
typedef struct {
struct dirent dirent;
char *entries;
ssize_t entrySize;
ssize_t entryIdx;
} my_DIR;
char *bpc_mktemp(char *template)
{
char *p = template + strlen(template);
int i, xCnt = 0;
while ( p > template && p[-1] == 'X' ) {
p--;
xCnt++;
}
if ( xCnt == 0 ) return NULL;
for ( i = 0 ; i < (1 << (4 * xCnt)) ; i++ ) {
sprintf(p, "%0*x", xCnt, i);
if ( bpc_attribCache_getFile(&acNew, template, 0, 0)
|| (acOldUsed && bpc_attribCache_getFile(&acOld, template, 0, 0)) ) {
continue;
}
if ( LogLevel >= 7 ) bpc_logMsgf("bpc_mktemp: returning %s\n", template);
return template;
}
if ( LogLevel >= 7 ) bpc_logMsgf("bpc_mktemp: returning NULL\n");
return NULL;
}
int bpc_mkstemp(char *template, char *origFileName)
{
char *p = template + strlen(template);
bpc_attrib_file *file, *fileOrig = NULL;
int i, xCnt = 0;
FdInfo *fd;
while ( p > template && p[-1] == 'X' ) {
p--;
xCnt++;
}
if ( xCnt == 0 ) return -1;
for ( i = 0 ; i < (1 << (4 * xCnt)) ; i++ ) {
sprintf(p, "%0*x", xCnt, i);
if ( bpc_attribCache_getFile(&acNew, template, 0, 0)
|| (acOldUsed && bpc_attribCache_getFile(&acOld, template, 0, 0)) ) {
continue;
}
file = bpc_attribCache_getFile(&acNew, template, 1, 0);
if ( origFileName
&& (fileOrig = bpc_attribCache_getFile(&acNew, origFileName, 0, 0))
&& fileOrig->type == BPC_FTYPE_FILE ) {
/*
* We have been told that this temp file is an update of origFileName.
* If it exists, we copy all the attributes, including the digest,
* which is a cheap way to make the temp file look just like
* the orig file.
*/
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_mkstemp: copying attribs from %s to %s\n", origFileName, template);
bpc_attrib_fileCopy(file, fileOrig);
/*
* Make sure the pool file exists; otherwise zero out the digest
*/
if ( file->digest.len > 0 ) {
bpc_strBuf *poolPath = bpc_strBuf_new();
STRUCT_STAT st;
bpc_digest_md52path(poolPath, file->compress, &file->digest);
if ( stat(poolPath->s, &st) ) {
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_mkstemp: %s doesn't exist; ignoring digest for %s\n",
poolPath->s, template);
file->digest.len = 0;
file->size = 0;
}
bpc_strBuf_free(poolPath);
}
file->nlinks = 0;
} else {
/*
* No orig file, so create new attributes
*/
file->type = BPC_FTYPE_FILE;
file->mode = 0600;
file->compress = CompressLevel;
file->inode = Stats.InodeCurr;
Stats.InodeCurr += 2;
}
file->isTemp = 1;
bpc_attribCache_setFile(&acNew, template, file, 0);
if ( !(fd = bpc_fileOpen(&acNew, template, O_RDWR | O_CREAT)) ) {
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_mkstemp: bpc_fileOpen(%s,...) failed, size = %d, digestLen = %d\n",
template, file->size, file->digest.len);
return -1;
}
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_mkstemp: returning %s, fd = %d (size = %d, digestLen = %d)\n",
template, fd->fdNum, file->size, file->digest.len);
return fd->fdNum;
}
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_mkstemp: returning -1\n");
return -1;
}
/*
* Confirm that fileName exists, has the indicated size and MD5 file_sum. If so, mimic
* mkstemp above by creating a temporary file copy, but don't open it.
*
* The is used to implement an optimization in receiver.c: if we are receiving file deltas,
* we check if the deltas show the file is identical. That avoids opening the file
* and copying it to the temp file (which involves a lot of processing given the
* compression overhead, and disk IO for large files).
*/
int bpc_sysCall_checkFileMatch(char *fileName, char *tmpName, struct file_struct *rsyncFile,
char *file_sum, off_t fileSize)
{
bpc_attrib_file *fileOrig, *file;
bpc_strBuf *poolPath;
if ( !(fileOrig = bpc_attribCache_getFile(&acNew, fileName, 0, 0)) ) {
/*
* Hmmm. The file doesn't exist, but we got deltas suggesting the file is
* unchanged. So that means the generator found a matching pool file.
* Let's try the same thing.
*/
if ( bpc_sysCall_poolFileCheck(fileName, rsyncFile)
|| !(fileOrig = bpc_attribCache_getFile(&acNew, fileName, 0, 0)) ) {
if ( fileSize > 0 ) {
bpc_logErrf("bpc_sysCall_checkFileMatch(%s): file doesn't exist\n", fileName);
}
return -1;
}
}
if ( fileOrig->size != fileSize || fileOrig->digest.len < MD5_DIGEST_LEN || memcmp(file_sum, fileOrig->digest.digest, MD5_DIGEST_LEN) ) {
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_sysCall_checkFileMatch(%s): size/digest don't match (%lu/%lu, %d, 0x%02x%02x.../0x%02x%02x...\n",
fileName, (unsigned long)fileOrig->size, (unsigned long)fileSize,
fileOrig->digest.len,
fileOrig->digest.digest[0], fileOrig->digest.digest[1],
((unsigned)file_sum[0]) & 0xff, ((unsigned)file_sum[1]) & 0xff);
return -1;
}
/*
* make sure the pool file exists
*/
poolPath = bpc_strBuf_new();
bpc_digest_md52path(poolPath, CompressLevel, &fileOrig->digest);
if ( fileSize != 0 ) {
STRUCT_STAT st;
if ( stat(poolPath->s, &st) ) {
bpc_logErrf("bpc_sysCall_checkFileMatch(%s): got good match, but pool file %s doesn't exist - rewriting\n",
fileName, poolPath->s);
bpc_strBuf_free(poolPath);
return -1;
}
if ( st.st_mode & S_IXOTH ) {
/*
* pool file is marked for deletion - safely unmark it since we are going to use it
*/
if ( bpc_poolWrite_unmarkPendingDelete(poolPath->s) ) {
bpc_logErrf("bpc_sysCall_checkFileMatch(%s): couldn't unmark pool file %s - rewriting\n",
fileName, poolPath->s);
bpc_strBuf_free(poolPath);
return -1;
}
}
}
bpc_strBuf_free(poolPath);
/*
* Now mimic bpc_mkstemp() above
*/
if ( !get_tmpname(tmpName, fileName, 0) || !bpc_mktemp(tmpName) ) {
bpc_logErrf("bpc_sysCall_checkFileMatch(%s): tmp name failed\n", fileName);
return -1;
}
file = bpc_attribCache_getFile(&acNew, tmpName, 1, 0);
bpc_attrib_fileCopy(file, fileOrig);
file->nlinks = 0;
file->isTemp = 1;
bpc_attribCache_setFile(&acNew, tmpName, file, 0);
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_sysCall_checkFileMatch(%s): good match, made copy in %s\n", fileName, tmpName);
fprintf(stderr, "IOdone: same %s\n", tmpName);
return 0;
}
/*
* This is called by the generator-side to see if there is a matching pool
* file that can be used for the block checksums. This needs to match
* mks_temp above to make sure the same basis file is used by each side.
*
* If there is a match, we create a temp file entry, which will be replaced
* when the receiver does the rename.
*/
int bpc_sysCall_poolFileCheck(char *fileName, struct file_struct *rsyncFile)
{
bpc_digest digest;
bpc_strBuf *poolPath;
unsigned int ext;
int foundPoolFile = 0;
if ( protocol_version < 30 || !always_checksum ) return -1;
poolPath = bpc_strBuf_new();
digest.len = MD5_DIGEST_LEN;
memcpy(digest.digest, F_SUM(rsyncFile), MD5_DIGEST_LEN);
/*
* find the first non-empty pool file in the chain
*/
if ( F_LENGTH(rsyncFile) > 0 ) {
for ( ext = 0 ; !foundPoolFile ; ext++ ) {
STRUCT_STAT st;
bpc_digest_append_ext(&digest, ext);
bpc_digest_md52path(poolPath, CompressLevel, &digest);
if ( stat(poolPath->s, &st) ) break;
if ( st.st_size == 0 ) continue;
if ( st.st_mode & S_IXOTH ) {
/*
* pool file is marked for deletion - safely unmark it since we going to use it
*/
if ( bpc_poolWrite_unmarkPendingDelete(poolPath->s) ) {
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_sysCall_poolFileCheck(%s): couldn't unmark potential match %s\n", fileName, poolPath->s);
continue;
}
}
foundPoolFile = 1;
}
} else {
/*
* For an empty file there is no corresponding pool file, so just say it matches
*/
foundPoolFile = 1;
bpc_strBuf_strcpy(poolPath, 0, "");
}
if ( foundPoolFile ) {
bpc_attrib_file *file = bpc_attribCache_getFile(&acNew, fileName, 1, 0);
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_sysCall_poolFileCheck(%s): potential match %s (len = %lu)\n", fileName, poolPath->s, (unsigned long)F_LENGTH(rsyncFile));
file->type = BPC_FTYPE_FILE;
file->size = F_LENGTH(rsyncFile);
file->mode = 0600;
file->inode = Stats.InodeCurr;
file->compress = CompressLevel;
Stats.InodeCurr += 2;
file->digest = digest;
file->isTemp = 1;
bpc_strBuf_free(poolPath);
return 0;
} else {
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_sysCall_poolFileCheck(%s): no pool file at %s\n", fileName, poolPath->s);
bpc_strBuf_free(poolPath);
return -1;
}
}
/*
* Print file transfer status for retry and fail
*/
void bpc_sysCall_printfileStatus(char *fileName, char *status)
{
fprintf(stderr, "IOdone: %s %s\n", status, fileName);
}
/*
* TODO: do target if symlink?
*/
int bpc_lchmod(const char *fileName, mode_t mode)
{
bpc_attrib_file *file;
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_lchmod(%s, 0%o)\n", fileName, mode);
if ( !(file = bpc_attribCache_getFile(&acNew, (char*)fileName, 0, 0)) ) {
if ( !am_generator ) {
/*
* ignore receive lchmod setting
*/
return 0;
}
errno = ENOENT;
return -1;
}
if ( file->mode == mode ) return 0;
if ( acOldUsed && !file->isTemp && file->inode < Stats.Inode0 && !bpc_attribCache_getFile(&acOld, (char*)fileName, 0, 0) ) {
if ( bpc_attribCache_setFile(&acOld, (char*)fileName, file, 1) ) {
bpc_poolRefDeltaUpdate(&DeltaOld, file->compress, &file->digest, 1);
}
}
file->mode = mode;
bpc_attribCache_setFile(&acNew, (char*)fileName, file, 0);
return 0;
}
int bpc_fchmod(int filedes, mode_t mode)
{
if ( filedes < 0 || filedes >= MAX_FD || !Fd[filedes].used ) {
errno = EBADF;
return -1;
}
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_fchmod(%d (%s), 0%o)\n",
filedes, Fd[filedes].fileName->s, mode);
return bpc_lchmod(Fd[filedes].fileName->s, mode);
}
int bpc_unlink(const char *fileName)
{
bpc_attrib_file *file;
int deleteInode = 0;
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_unlink(%s)\n", fileName);
if ( !(file = bpc_attribCache_getFile(&acNew, (char*)fileName, 0, 0)) ) {
/*
* See if the file is there, but it's the inode that is missing
*/
if ( !(file = bpc_attribCache_getFile(&acNew, (char*)fileName, 0, 1)) ) {
errno = ENOENT;
return -1;
}
/*
* Hmmm, this shouldn't happen (file entry is present, but inode wasn't found)
*/
if ( LogLevel >= 3 ) bpc_logMsgf("bpc_unlink(%s): type %d, size %lu, nlinks %u; inode %u missing; setting nlinks to 0\n",
fileName, file->type, file->size, file->nlinks, file->inode);
file->nlinks = 0;
}
if ( file->type == BPC_FTYPE_DIR ) {
errno = EISDIR;
return -1;
}
if ( file->nlinks > 0 ) {
if ( acOldUsed && !file->isTemp && !bpc_attribCache_getInode(&acOld, file->inode, 0) ) {
/*
* copy the inode to old
*/
if ( LogLevel >= 6 ) bpc_logMsgf("bpc_unlink: setting inode in old (inode = %lu, nlinks = %lu)\n",
(unsigned long)file->inode, (unsigned long)file->nlinks);
bpc_attribCache_setInode(&acOld, file->inode, file);
bpc_poolRefDeltaUpdate(&DeltaOld, file->compress, &file->digest, 1);
}
/*
* If this file is older than this backup, then move it to old
* (don't update the inode, since we know it exists after we just
* copied it).
*/
if ( file && file->inode < Stats.Inode0 && acOldUsed && !file->isTemp && !bpc_attribCache_getFile(&acOld, (char*)fileName, 0, 0) ) {
if ( LogLevel >= 6 ) bpc_logMsgf("bpc_unlink: setting %s in old (inode = %lu, nlinks = %lu)\n",
fileName, (unsigned long)file->inode, (unsigned long)file->nlinks);
bpc_attribCache_setFile(&acOld, (char*)fileName, file, 1);
}
/*
* Now reduce the number of links and update the inode
* ref count is handled above
*/
file->nlinks--;
if ( file->nlinks <= 0 ) {
deleteInode = 1;
bpc_poolRefDeltaUpdate(&DeltaNew, file->compress, &file->digest, -1);
} else {
if ( LogLevel >= 6 ) bpc_logMsgf("bpc_unlink: updating inode in new (inode = %lu, nlinks = %lu)\n", (unsigned long)file->inode, (unsigned long)file->nlinks);
bpc_attribCache_setInode(&acNew, file->inode, file);
}
} else {
/*
* If this file is older than this backup, then move it
* to old. Otherwise just remove it.
*/
if ( !file->isTemp && file->inode < Stats.Inode0 && acOldUsed ) {
bpc_attrib_file *fileOld = bpc_attribCache_getFile(&acOld, (char*)fileName, 0, 0);
if ( !fileOld ) {
if ( LogLevel >= 6 ) bpc_logMsgf("bpc_unlink: setting %s in old (inode = %lu, nlinks = %lu)\n",
fileName, (unsigned long)file->inode, (unsigned long)file->nlinks);
bpc_attribCache_setFile(&acOld, (char*)fileName, file, 0);
bpc_poolRefDeltaUpdate(&DeltaOld, file->compress, &file->digest, 1);
bpc_poolRefDeltaUpdate(&DeltaNew, file->compress, &file->digest, -1);
}
} else if ( !file->isTemp ) {
if ( file->digest.len > 0 ) {
bpc_poolRefDeltaUpdate(&DeltaNew, file->compress, &file->digest, -1);
}
}
}
if ( deleteInode ) {
if ( LogLevel >= 6 ) bpc_logMsgf("bpc_unlink: deleting inode in new (inode = %lu)\n",
(unsigned long)file->inode);
bpc_attribCache_deleteInode(&acNew, file->inode);
}
bpc_attribCache_deleteFile(&acNew, (char*)fileName);
return 0;
}
int bpc_lstat(const char *fileName, struct stat *buf)
{
bpc_attrib_file *file;
dev_t rdev = 0;
/*
* must be in order of BPC_FTYPE_* definitions
*/
static uint fmode[] = {
S_IFREG, /* BPC_FTYPE_FILE */
S_IFREG, /* BPC_FTYPE_HARDLINK */
S_IFLNK, /* BPC_FTYPE_SYMLINK */
S_IFCHR, /* BPC_FTYPE_CHARDEV */
S_IFBLK, /* BPC_FTYPE_BLOCKDEV */
S_IFDIR, /* BPC_FTYPE_DIR */
S_IFIFO, /* BPC_FTYPE_FIFO */
S_IFREG, /* BPC_FTYPE_UNKNOWN */
S_IFSOCK, /* BPC_FTYPE_SOCKET */
S_IFREG, /* BPC_FTYPE_UNKNOWN */
S_IFREG, /* BPC_FTYPE_DELETED */
};
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_lstat(%s)\n", fileName);
if ( !(file = bpc_attribCache_getFile(&acNew, (char*)fileName, 0, 0)) ) {
/*
* See if the file is there, but it's the inode that is missing
*/
if ( !(file = bpc_attribCache_getFile(&acNew, (char*)fileName, 0, 1)) ) {
errno = ENOENT;
return -1;
}
/*
* Hmmm, this shouldn't happen (file entry is present, but inode wasn't found)
* This entry won't have a digest, so we won't be able to open the file.
*/
if ( LogLevel >= 3 ) bpc_logMsgf("bpc_lstat(%s): type %d, size %lu, nlinks %u; inode %u missing; setting nlinks to 0\n",
fileName, file->type, file->size, file->nlinks, file->inode);
file->nlinks = 0;
}
if ( file->type == BPC_FTYPE_DELETED || file->type == BPC_FTYPE_UNKNOWN || file->type >= BPC_FTYPE_INVALID ) {
errno = ENOENT;
return -1;
}
if ( file->type == BPC_FTYPE_CHARDEV || file->type == BPC_FTYPE_BLOCKDEV ) {
char data[BPC_MAXPATHLEN];
int minor = 0, major = 0;
int nRead = bpc_fileReadAll(&acNew, (char*)fileName, data, sizeof(data) - 1);
rdev = 1;
if ( nRead >= 0 ) {
data[nRead] = '\0';
if ( sscanf(data, "%d,%d", &major, &minor) == 2 ) {
rdev = MAKEDEV(major, minor);
}
}
}
buf->st_dev = 1;
buf->st_ino = file->inode;
buf->st_mode = file->mode;
buf->st_nlink = file->nlinks == 0 ? 1 : file->nlinks;
buf->st_uid = file->uid;
buf->st_gid = file->gid;
buf->st_rdev = rdev;
buf->st_atime = file->mtime;
buf->st_mtime = file->mtime;
buf->st_ctime = file->mtime;
buf->st_size = file->size;
buf->st_blocks = (file->size + 1023) / 1024;
buf->st_blksize = 1024;
if ( file->type < sizeof(fmode) / sizeof(fmode[0]) ) {
buf->st_mode |= fmode[file->type];
}
return 0;
}
int bpc_fstat(int filedes, struct stat *buf)
{
int ret;
if ( filedes < 0 || filedes >= MAX_FD || !Fd[filedes].used ) {
errno = EBADF;
return -1;
}
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_fstat(%d (%s))\n", filedes, Fd[filedes].fileName->s);
ret = bpc_lstat(Fd[filedes].fileName->s, buf);
/*
* TODO: needed?? Based on the current write file update the size...
*/
return ret;
}
int bpc_stat(const char *fileName, struct stat *buf)
{
bpc_attrib_file *file;
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_stat(%s)\n", fileName);
if ( (file = bpc_attribCache_getFile(&acNew, (char*)fileName, 0, 0)) && file->type == BPC_FTYPE_SYMLINK ) {
char targetName[BPC_MAXPATHLEN];
int nRead = bpc_fileReadAll(&acNew, (char*)fileName, targetName, sizeof(targetName) - 1);
/*
* TODO: combine fileName and targetName if targetName is relative
* TODO: what happens if $targetName is a symlink?
*/
if ( nRead <= 0 ) {
errno = ENOENT;
return -1;
}
targetName[nRead] = '\0';
return bpc_lstat(targetName, buf);
} else {
return bpc_lstat(fileName, buf);
}
}
int bpc_file_checksum(char *fileName, char *sum, int checksum_len)
{
bpc_attrib_file *file = bpc_attribCache_getFile(&acNew, (char*)fileName, 0, 0);
bpc_strBuf *poolPath;
STRUCT_STAT st;
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_file_checksum(%s)\n", fileName);
if ( !file || file->digest.len < checksum_len ) return -2;
/*
* check the pool file actually exists before returning the digest.
*/
poolPath = bpc_strBuf_new();
bpc_digest_md52path(poolPath, file->compress, &file->digest);
if ( stat(poolPath->s, &st) ) {
bpc_strBuf_free(poolPath);
return -1;
}
if ( st.st_mode & S_IXOTH ) {
/*
* pool file is marked for deletion - safely unmark it since we are using it
*/
if ( bpc_poolWrite_unmarkPendingDelete(poolPath->s) ) {
bpc_logErrf("bpc_file_checksum(%s): couldn't unmark pool file %s - returning no match\n",
fileName, poolPath->s);
bpc_strBuf_free(poolPath);
return -1;
}
}
bpc_strBuf_free(poolPath);
memcpy(sum, file->digest.digest, checksum_len);
return 0;
}
/*
* the link contents (ie: target) are kept in the original client
* charset (ie: not converted to utf8).
*/
int bpc_symlink(const char *fileName, const char *symName)
{
bpc_attrib_file *file;
FdInfo *fd;
int ret = 0;
char logText[2 * BPC_MAXPATHLEN + 32];
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_symlink(%s, %s)\n", fileName, symName);
/*
* it's an error if symname exists
*/
if ( (file = bpc_attribCache_getFile(&acNew, (char*)symName, 0, 0)) ) {
errno = EEXIST;
return -1;
}
/*
* add delete attribute to old if nothing is in old
*/
if ( acOldUsed && !bpc_attribCache_getFile(&acOld, (char*)symName, 0, 0) ) {
file = bpc_attribCache_getFile(&acOld, (char*)symName, 1, 0);
file->type = BPC_FTYPE_DELETED;
bpc_attribCache_setFile(&acOld, (char*)symName, file, 0);
}
if ( !(fd = bpc_fileOpen(&acNew, (char*)symName, O_WRONLY | O_CREAT | O_TRUNC)) ) {
bpc_logErrf("bpc_symlink: open/create of %s failed\n", symName);
Stats.ErrorCnt++;
return -1;
}
if ( bpc_fileWrite(&acNew, fd, (char*)fileName, strlen(fileName)) ) {
bpc_logErrf("bpc_symlink: write failed\n");
ret = -1;
Stats.ErrorCnt++;
}
snprintf(logText, sizeof(logText), "%s -> %s", symName, fileName);
if ( bpc_fileClose(&acNew, fd, BPC_FTYPE_SYMLINK, 0777, logText) ) {
bpc_logErrf("bpc_symlink: close failed\n");
ret = -1;
Stats.ErrorCnt++;
}
return ret;
}
int bpc_link(const char *targetName, const char *linkName)
{
bpc_attrib_file *file;
bpc_strBuf *poolPath;
STRUCT_STAT st;
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_link(%s, %s)\n", targetName, linkName);
if ( bpc_attribCache_getFile(&acNew, (char*)linkName, 0, 0) ) {
errno = EEXIST;
return -1;
}
/*
* check if the target exists. hardlinks to directories are not supported.
*/
if ( !(file = bpc_attribCache_getFile(&acNew, (char*)targetName, 0, 0))
|| file->type == BPC_FTYPE_DIR ) {
errno = ENOENT;
return -1;
}
/*
* reference counts are unchanged in each of these cases (first link and additional link)
*/
if ( file->nlinks == 0 ) {
/*
* first save the original target file (since it a regular file with no links)
*/
if ( acOldUsed && !bpc_attribCache_getFile(&acOld, (char*)targetName, 0, 0) ) {
bpc_attribCache_setFile(&acOld, (char*)targetName, file, 0);
bpc_poolRefDeltaUpdate(&DeltaOld, file->compress, &file->digest, 1);
}
/*
* promote the target to a hardlink; both files are identical
*/
file->nlinks = 2;
bpc_attribCache_setFile(&acNew, (char*)targetName, file, 0);
bpc_attribCache_setFile(&acNew, (char*)linkName, file, 0);
} else {
/*
* save the inode away since the link count is going to increase
*/
if ( acOldUsed && !bpc_attribCache_getInode(&acOld, file->inode, 0) ) {
bpc_attribCache_setInode(&acOld, file->inode, file);
bpc_poolRefDeltaUpdate(&DeltaOld, file->compress, &file->digest, 1);
}
/*
* reference count is unchanged since the inode already points at the pool file
*/
file->nlinks++;
bpc_attribCache_setFile(&acNew, (char*)linkName, file, 0);
}
Stats.ExistFileCnt++;
Stats.ExistFileSize += file->size;
poolPath = bpc_strBuf_new();
bpc_digest_md52path(poolPath, file->compress, &file->digest);
if ( !stat(poolPath->s, &st) ) Stats.ExistFileCompSize += st.st_size;
bpc_strBuf_free(poolPath);
if ( acOldUsed && !bpc_attribCache_getFile(&acOld, (char*)linkName, 0, 0) ) {
file = bpc_attribCache_getFile(&acOld, (char*)linkName, 1, 0);
file->type = BPC_FTYPE_DELETED;
bpc_attribCache_setFile(&acOld, (char*)linkName, file, 0);
}
fprintf(stderr, "IOdone: new %s => %s\n", linkName, targetName);
return 0;
}
/*
* check and set the number of links on a file
*/
int bpc_nlinkSet(const char *targetName, uint32 nlinks)
{
bpc_attrib_file *file;
/*
* check if the target exists.
*/
if ( !(file = bpc_attribCache_getFile(&acNew, (char*)targetName, 0, 0)) ) {
errno = ENOENT;
return -1;
}
if ( file->nlinks == nlinks ) {
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_nlinkSet(%s, %u) -> no change\n", targetName, nlinks);
return 0;
}
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_nlinkSet(%s, %u) -> was %u\n", targetName, nlinks, file->nlinks);
file->nlinks = nlinks;;
bpc_attribCache_setFile(&acNew, (char*)targetName, file, 0);
return 0;
}
#ifdef HAVE_LUTIMES
int bpc_lutimes(const char *fileName, struct timeval *t)
{
bpc_attrib_file *file;
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_lutimes(%s)\n", fileName);
if ( !(file = bpc_attribCache_getFile(&acNew, (char*)fileName, 0, 0)) ) {
if ( !am_generator ) {
/*
* ignore receive lutimes setting
*/
return 0;
}
errno = ENOENT;
return -1;
}
if ( file->mtime == t[1].tv_sec ) return 0;
if ( file->inode < Stats.Inode0 && acOldUsed && !file->isTemp && !bpc_attribCache_getFile(&acOld, (char*)fileName, 0, 0) ) {
if ( bpc_attribCache_setFile(&acOld, (char*)fileName, file, 1) > 0 ) {
bpc_poolRefDeltaUpdate(&DeltaOld, file->compress, &file->digest, 1);
}
}
file->mtime = t[1].tv_sec;
bpc_attribCache_setFile(&acNew, (char*)fileName, file, 0);
return 0;
}
#endif
#ifdef HAVE_UTIMES
int bpc_utimes(const char *fileName, struct timeval *t)
{
bpc_attrib_file *file;
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_utimes(%s)\n", fileName);
if ( (file = bpc_attribCache_getFile(&acNew, (char*)fileName, 0, 0)) && file->type == BPC_FTYPE_SYMLINK ) {
char targetName[BPC_MAXPATHLEN];
int nRead = bpc_fileReadAll(&acNew, (char*)fileName, targetName, sizeof(targetName) - 1);
/*
* TODO: combine fileName and targetName if targetName is relative
* TODO: what happens if $targetName is a symlink?
*/
if ( nRead <= 0 ) {
errno = ENOENT;
return -1;
}
targetName[nRead] = '\0';
return bpc_lutimes(targetName, t);
} else {
return bpc_lutimes(fileName, t);
}
}
#endif
int bpc_lutime(const char *fileName, time_t mtime)
{
bpc_attrib_file *file;
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_lutime(%s)\n", fileName);
if ( !(file = bpc_attribCache_getFile(&acNew, (char*)fileName, 0, 0)) ) {
if ( !am_generator ) {
/*
* ignore receive lutime setting
*/
return 0;
}
errno = ENOENT;
return -1;
}
if ( file->mtime == mtime ) return 0;
if ( file->inode < Stats.Inode0 && acOldUsed && !file->isTemp && !bpc_attribCache_getFile(&acOld, (char*)fileName, 0, 0) ) {
if ( bpc_attribCache_setFile(&acOld, (char*)fileName, file, 1) > 0 ) {
bpc_poolRefDeltaUpdate(&DeltaOld, file->compress, &file->digest, 1);
}
}
file->mtime = mtime;
bpc_attribCache_setFile(&acNew, (char*)fileName, file, 0);
return 0;
}
int bpc_utime(const char *fileName, time_t mtime)
{
bpc_attrib_file *file;
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_utime(%s)\n", fileName);
if ( (file = bpc_attribCache_getFile(&acNew, (char*)fileName, 0, 0)) && file->type == BPC_FTYPE_SYMLINK ) {
char targetName[BPC_MAXPATHLEN];
int nRead = bpc_fileReadAll(&acNew, (char*)fileName, targetName, sizeof(targetName) - 1);
/*
* TODO: combine fileName and targetName if targetName is relative
* TODO: what happens if $targetName is a symlink?
*/
if ( nRead <= 0 ) {
errno = ENOENT;
return -1;
}
targetName[nRead] = '\0';
return bpc_lutime(targetName, mtime);
} else {
return bpc_lutime(fileName, mtime);
}
}
int bpc_lchown(const char *fileName, uid_t uid, gid_t gid)
{
bpc_attrib_file *file;
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_lchown(%s, %lu, %lu)\n",
fileName, (unsigned long)uid, (unsigned long)gid);
if ( !(file = bpc_attribCache_getFile(&acNew, (char*)fileName, 0, 0)) ) {
if ( !am_generator ) {
/*
* ignore receive lchown setting
*/
return 0;
}
errno = ENOENT;
return -1;
}
if ( file->uid == uid && file->gid == gid ) return 0;
if ( file->inode < Stats.Inode0 && acOldUsed && !file->isTemp && !bpc_attribCache_getFile(&acOld, (char*)fileName, 0, 0) ) {
if ( bpc_attribCache_setFile(&acOld, (char*)fileName, file, 1) > 0 ) {
bpc_poolRefDeltaUpdate(&DeltaOld, file->compress, &file->digest, 1);
}
}
file->uid = uid;
file->gid = gid;
bpc_attribCache_setFile(&acNew, (char*)fileName, file, 0);
return 0;
}
int bpc_rename(const char *oldName, const char *newName)
{
bpc_attrib_file *file, *fileNew;
int oldIsTemp, fileAttrChanged = 0;
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_rename(%s, %s)\n", oldName, newName);
if ( !(file = bpc_attribCache_getFile(&acNew, (char*)oldName, 0, 0)) ) {
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_rename: %s doesn't exist\n", oldName);
errno = ENOENT;
return -1;
}
if ( !am_generator ) {
/*
* We don't do renames on the receiver, since it's too hard to keep attribute updates on
* both the generator and receiver sycnhronized. Send the attributes to the generator so
* it can do the rename.
*/
static xbuf rename_msg = EMPTY_XBUF;
char *bufP, *bufPnew;
uint32 oldLen = strlen(oldName) + 1, newLen = strlen(newName) + 1;
if ( !rename_msg.size ) {
alloc_xbuf(&rename_msg, 4096);
}
if ( rename_msg.size < 3 * sizeof(uint32) + oldLen + newLen + 1024 ) {
realloc_xbuf(&rename_msg, 3 * sizeof(uint32) + oldLen + newLen + 1024);
}
bufP = rename_msg.buf;
SIVAL(bufP, 0, oldLen); bufP += sizeof(uint32);
SIVAL(bufP, 0, newLen); bufP += sizeof(uint32);
SIVAL(bufP, 0, file->isTemp); bufP += sizeof(uint32);
memcpy(bufP, oldName, oldLen); bufP += oldLen;
memcpy(bufP, newName, newLen); bufP += newLen;
bufPnew = (char*)bpc_attrib_file2buf(file, (uchar*)bufP, (uchar*)rename_msg.buf + rename_msg.size);
if ( bufPnew > rename_msg.buf + rename_msg.size ) {
ssize_t used = bufP - rename_msg.buf;
realloc_xbuf(&rename_msg, (bufPnew - rename_msg.buf) + 4096);
bufPnew = (char*)bpc_attrib_file2buf(file, (uchar*)rename_msg.buf + used, (uchar*)rename_msg.buf + rename_msg.size);
}
if ( LogLevel >= 6 ) bpc_logMsgf("Sending rename request (len=%d)\n", bufPnew - rename_msg.buf);
send_msg(MSG_RENAME, rename_msg.buf, bufPnew - rename_msg.buf, 0);
bpc_attribCache_setFile(&acNew, (char*)newName, file, 0);
bpc_attribCache_deleteFile(&acNew, (char*)oldName);
return 0;
}
oldIsTemp = file->isTemp;
file->isTemp = 0;
if ( (fileNew = bpc_attribCache_getFile(&acNew, (char*)newName, 0, 0)) ) {
/*
* If fileNew is a temporary file, just delete it
*/
if ( fileNew->isTemp ) {
bpc_attribCache_deleteFile(&acNew, (char*)newName);
fileNew = NULL;
} else {
/*
* If newName exists, and has different attributes, then we unlink the file.
*/
if ( fileNew->nlinks > 0 ) {
/*
* We are updating a file with hardlinks. unlink() will break the existing hardlink.
* Give the oldName a new inode number, so that the hardlink will be re-established later
* if the files are still meant to be linked.
*/
file->inode = Stats.InodeCurr;
Stats.InodeCurr += 2;
}
if ( (fileAttrChanged = bpc_attrib_fileCompare(file, fileNew)) ) {
if ( bpc_unlink(newName) ) return -1;
}
}
}
if ( file->type == BPC_FTYPE_DIR ) {
bpc_strBuf *path = bpc_strBuf_new(), *pathOld = bpc_strBuf_new();
bpc_attribCache_getFullMangledPath(&acNew, path, (char*)newName, file->backupNum);
bpc_attribCache_getFullMangledPath(&acNew, pathOld, (char*)oldName, file->backupNum);
if ( rename(pathOld->s, path->s) ) {
bpc_logErrf("bpc_rename: directory rename %s -> %s failed\n", pathOld->s, path->s);
errno = EACCES;
bpc_strBuf_free(path);
bpc_strBuf_free(pathOld);
return -1;
}
bpc_strBuf_free(path);
bpc_strBuf_free(pathOld);
}
if ( acOldUsed ) {
if ( !oldIsTemp && !bpc_attribCache_getFile(&acOld, (char*)oldName, 0, 0) ) {
if ( bpc_attribCache_setFile(&acOld, (char*)oldName, file, 1) > 0 ) {
bpc_poolRefDeltaUpdate(&DeltaOld, file->compress, &file->digest, 1);
}
}
if ( !fileNew && !bpc_attribCache_getFile(&acOld, (char*)newName, 0, 0) ) {
bpc_attrib_file *fileOld = bpc_attribCache_getFile(&acOld, (char*)newName, 1, 0);
fileOld->type = BPC_FTYPE_DELETED;
bpc_attribCache_setFile(&acOld, (char*)newName, fileOld, 0);
}
}
if ( !fileNew || fileAttrChanged ) {
if ( oldIsTemp ) {
bpc_poolRefDeltaUpdate(&DeltaNew, file->compress, &file->digest, 1);
}
bpc_attribCache_setFile(&acNew, (char*)newName, file, 0);
}
bpc_attribCache_deleteFile(&acNew, (char*)oldName);
fprintf(stderr, "IOrename: %lu %s%s\n", (unsigned long)strlen(oldName), oldName, newName);
return 0;
}
int bpc_rename_request(char *oldName, char *newName, uint32 isTemp, char *bufP, char *bufEnd)
{
bpc_attrib_file *file = bpc_attribCache_getFile(&acNew, (char*)oldName, 1, 0);
if ( (bufP = (char*)bpc_attrib_buf2fileFull(file, (uchar*)bufP, (uchar*)bufEnd)) != bufEnd ) {
bpc_logErrf("bpc_rename_request(%s,%s) got to %p vs end = %p\n", oldName, newName, bufP, bufEnd);
}
file->isTemp = isTemp;
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_rename_request: name = %s, xattr cnt = %d\n", file->name, bpc_hashtable_entryCount(&file->xattrHT));
return bpc_rename(oldName, newName);
}
int bpc_mknod(const char *fileName, mode_t mode, dev_t dev)
{
bpc_attrib_file *file;
int type;
int ret = 0;
FdInfo *fd;
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_mknod(%s, 0%o, %lu)\n",
fileName, mode, (unsigned long)dev);
if ( (file = bpc_attribCache_getFile(&acNew, (char*)fileName, 0, 0)) ) {
errno = EEXIST;
return -1;
}
if ( acOldUsed && !bpc_attribCache_getFile(&acOld, (char*)fileName, 0, 0) ) {
file = bpc_attribCache_getFile(&acOld, (char*)fileName, 1, 0);
file->type = BPC_FTYPE_DELETED;
bpc_attribCache_setFile(&acOld, (char*)fileName, file, 0);
}
type = BPC_FTYPE_FILE;
if ( (mode & S_IFMT) == S_IFIFO ) type = BPC_FTYPE_FIFO;
if ( (mode & S_IFMT) == S_IFBLK ) type = BPC_FTYPE_BLOCKDEV;
if ( (mode & S_IFMT) == S_IFCHR ) type = BPC_FTYPE_CHARDEV;
if ( (mode & S_IFMT) == S_IFSOCK ) type = BPC_FTYPE_SOCKET;
if ( type == BPC_FTYPE_BLOCKDEV || type == BPC_FTYPE_CHARDEV ) {
bpc_strBuf *data = bpc_strBuf_new();
if ( !(fd = bpc_fileOpen(&acNew, (char*)fileName, O_WRONLY | O_CREAT | O_TRUNC)) ) {
bpc_logErrf("bpc_mknod: open/create of %s failed\n", fileName);
Stats.ErrorCnt++;
return -1;
}
bpc_strBuf_snprintf(data, 0, "%lu,%lu", (unsigned long)major(dev), (unsigned long)minor(dev));
if ( bpc_fileWrite(&acNew, fd, data->s, strlen(data->s)) ) {
bpc_logErrf("bpc_mknod: write failed\n");
ret = -1;
Stats.ErrorCnt++;
}
bpc_strBuf_free(data);
if ( bpc_fileClose(&acNew, fd, type, mode & ~S_IFMT, (char*)fileName) ) {
bpc_logErrf("bpc_mknod: close failed\n");
ret = -1;
Stats.ErrorCnt++;
}
} else {
/*
* empty file - just write attributes
*/
file = bpc_attribCache_getFile(&acNew, (char*)fileName, 1, 0);
file->type = type;
file->mode = mode & ~S_IFMT;
file->inode = Stats.InodeCurr;
file->size = 0;
Stats.InodeCurr += 2;
bpc_attribCache_setFile(&acNew, (char*)fileName, file, 0);
fprintf(stderr, "IOdone: new %s\n", fileName);
}
return ret;
}
int bpc_open(const char *fileName, int flags, mode_t mode)
{
bpc_attrib_file *file;
FdInfo *fd;
/*
* handle a special case of opening a directory. If a directory
* is being replaced by a file, the generator has removed the
* directory already, but we (ie: the receiver) don't know
* that yet.
*/
if ( !am_generator && (file = bpc_attribCache_getFile(&acNew, (char*)fileName, 0, 0))
&& file->type == BPC_FTYPE_DIR ) {
if ( acOldUsed ) bpc_attribCache_setFile(&acOld, (char*)fileName, file, 1);
bpc_attribCache_deleteFile(&acNew, (char*)fileName);
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_open(%s, 0x%x, 0%o) opening directory -> -1\n", fileName, flags, mode);
return -1;
}
if ( !(fd = bpc_fileOpen(&acNew, (char*)fileName, flags)) ) {
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_open(%s, 0x%x, 0%o) -> -1\n", fileName, flags, mode);
return -1;
}
fd->mode = mode;
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_open(%s, 0x%x, 0%o) -> %d\n", fileName, flags, mode, fd->fdNum);
return fd->fdNum;
}
int bpc_close(int fdNum)
{
if ( fdNum < 0 || fdNum >= MAX_FD || !Fd[fdNum].used ) {
errno = EBADF;
return -1;
}
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_close(%d (%s))\n", fdNum, Fd[fdNum].fileName->s);
return bpc_fileClose(&acNew, &Fd[fdNum], -1, -1, NULL);
}
off_t bpc_lseek(int fdNum, off_t offset, int whence)
{
FdInfo *fd;
if ( fdNum < 0 || fdNum >= MAX_FD || !Fd[fdNum].used ) {
errno = EBADF;
return -1;
}
fd = &Fd[fdNum];
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_lseek(%d (%s), %lu, %d)\n", fdNum, fd->fileName->s, offset, whence);
if ( fd->tmpFd < 0 ) {
off_t newPosn = -1;
if ( whence == SEEK_SET ) newPosn = offset;
else if ( whence == SEEK_CUR ) newPosn = fd->posn + offset;
else if ( whence == SEEK_END ) newPosn = fd->fileSize + offset;
if ( newPosn < 0 ) {
errno = EINVAL;
return -1;
}
if ( (size_t)newPosn < fd->bufferSize ) {
fd->posn = newPosn;
return fd->posn;
}
/*
* We need to seek off the end of our in-memory buffer.
* Switch to a file instead.
*/
if ( bpc_fileSwitchToDisk(&acNew, fd) ) return -1;
}
return lseek(fd->tmpFd, offset, whence);
}
off_t bpc_ftruncate(int fdNum, off_t length)
{
FdInfo *fd;
if ( fdNum < 0 || fdNum >= MAX_FD || !Fd[fdNum].used ) {
errno = EBADF;
return -1;
}
fd = &Fd[fdNum];
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_ftruncate(%d (%s), %lu)\n", fdNum, fd->fileName->s, length);
if ( fd->tmpFd < 0 ) {
if ( length < 0 ) {
errno = EINVAL;
return -1;
}
if ( length == fd->fileSize ) {
return 0;
}
if ( (size_t)length < fd->bufferSize ) {
fd->dirty = 1;
fd->fileSize = length;
if ( fd->posn > fd->fileSize ) fd->posn = fd->fileSize;
return 0;
}
/*
* We need to make the file larger than the in-memory buffer.
* Switch to a file instead.
*/
if ( bpc_fileSwitchToDisk(&acNew, fd) ) return -1;
}
fd->dirty = 1;
return ftruncate(fd->tmpFd, length);
}
ssize_t bpc_read(int fdNum, void *buf, size_t readSize)
{
FdInfo *fd;
if ( fdNum < 0 || fdNum >= MAX_FD || !Fd[fdNum].used ) {
errno = EBADF;
return -1;
}
fd = &Fd[fdNum];
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_read(%d (%s), buf, %lu) tmpFd = %d\n",
fdNum, fd->fileName->s, readSize, fd->tmpFd);
if ( fd->tmpFd < 0 ) {
if ( fd->posn >= fd->fileSize || (size_t)fd->posn >= fd->bufferSize ) {
bpc_logMsgf("bpc_read: read past EOF; readSize = %lu, posn = %lu, fileSize = %lu, bufferSize = %lu\n",
readSize, fd->posn, fd->fileSize, fd->bufferSize);
return 0;
}
if ( readSize > (size_t)fd->fileSize - fd->posn ) readSize = fd->fileSize - fd->posn;
if ( readSize > (size_t)fd->bufferSize - fd->posn ) readSize = fd->bufferSize - fd->posn;
memcpy(buf, fd->buffer + fd->posn, readSize);
fd->posn += readSize;
return readSize;
} else {
return read(fd->tmpFd, buf, readSize);
}
}
ssize_t bpc_write(int fdNum, const void *buf, size_t writeSize)
{
FdInfo *fd;
if ( fdNum < 0 || fdNum >= MAX_FD || !Fd[fdNum].used ) {
errno = EBADF;
return -1;
}
fd = &Fd[fdNum];
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_write(%d (%s), buf, %lu)\n",
fdNum, fd->fileName->s, writeSize);
if ( bpc_fileWrite(&acNew, fd, (char*)buf, writeSize) ) return -1;
return writeSize;
}
ssize_t bpc_readlink(const char *fileName, char *buffer, size_t bufferSize)
{
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_readlink(%s, buf, %lu)\n",
fileName, bufferSize);
return bpc_fileReadAll(&acNew, (char*)fileName, buffer, bufferSize);
}
int bpc_access(const char *fileName, int mode)
{
bpc_attrib_file *file = bpc_attribCache_getFile(&acNew, (char*)fileName, 0, 0);
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_access(%s, %d) -> %d\n",
fileName, mode, file ? 0 : -1);
if ( !file ) {
errno = ENOENT;
return -1;
} else {
return 0;
}
}
void bpc_tmpNameFlagSet(const char *tmpName)
{
bpc_attrib_file *file = bpc_attribCache_getFile(&acNew, (char*)tmpName, 0, 0);
if ( file && !file->isTemp ) {
file->isTemp = 1;
if ( file->digest.len > 0 ) {
bpc_poolRefDeltaUpdate(&DeltaNew, file->compress, &file->digest, -1);
}
}
}
int bpc_chdir(const char *dirName)
{
bpc_attrib_file *file;
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_chdir(%s)\n", dirName);
if ( !(file = bpc_attribCache_getFile(&acNew, (char*)dirName, 0, 0)) || file->type != BPC_FTYPE_DIR ) {
errno = ENOENT;
return -1;
}
bpc_attribCache_setCurrentDirectory(&acNew, (char*)dirName);
if ( acOldUsed ) bpc_attribCache_setCurrentDirectory(&acOld, (char*)dirName);
return 0;
}
int bpc_mkdir(const char *dirName, mode_t mode)
{
bpc_strBuf *path = bpc_strBuf_new();
bpc_attrib_file *file;
int ret;
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_mkdir(%s, 0%o)\n", dirName, mode);
bpc_attribCache_getFullMangledPath(&acNew, path, (char*)dirName, -1);
if ( bpc_attribCache_getFile(&acNew, (char*)dirName, 0, 0) ) {
errno = EEXIST;
bpc_strBuf_free(path);
return -1;
}
if ( acOldUsed && !bpc_attribCache_getFile(&acOld, (char*)dirName, 0, 0) ) {
file = bpc_attribCache_getFile(&acOld, (char*)dirName, 1, 0);
file->type = BPC_FTYPE_DELETED;
bpc_attribCache_setFile(&acOld, (char*)dirName, file, 0);
}
if ( (ret = bpc_path_create(path->s)) ) {
bpc_strBuf_free(path);
return ret;
}
file = bpc_attribCache_getFile(&acNew, (char*)dirName, 1, 0);
file->type = BPC_FTYPE_DIR;
file->mode = mode;
file->inode = Stats.InodeCurr;
if ( !(preserve_times & PRESERVE_DIR_TIMES) ) {
/*
* Normally dir mtimes are set later. But if --omit-dir-times was
* specified, then we need to set to a reasonable value, ie now.
*/
file->mtime = time(NULL);
}
Stats.InodeCurr += 2;
bpc_attribCache_setFile(&acNew, (char*)dirName, file, 0);
if ( !*dirName ) {
fprintf(stderr, "IOdone: new .\n");
} else {
fprintf(stderr, "IOdone: new %s\n", dirName);
}
bpc_strBuf_free(path);
return 0;
}
int bpc_rmdir(const char *dirName)
{
bpc_strBuf *path = bpc_strBuf_new();
bpc_attrib_file *file;
STRUCT_STAT st;
int statOk, cnt;
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_rmdir(%s)\n", dirName);
file = bpc_attribCache_getFile(&acNew, (char*)dirName, 0, 0);
bpc_attribCache_getFullMangledPath(&acNew, path, (char*)dirName, file->backupNum);
statOk = !stat(path->s, &st);
if ( (!file || file->type != BPC_FTYPE_DIR) && (!statOk || !S_ISDIR(st.st_mode)) ) {
errno = ENOENT;
bpc_strBuf_free(path);
return -1;
}
if ( (cnt = bpc_attribCache_getDirEntryCnt(&acNew, (char*)dirName)) > 0 ) {
errno = ENOTEMPTY;
bpc_strBuf_free(path);
return -1;
}
/*
* Remove the directory (and update reference counts). We need
* to first flush the attrib cache below this directory.
* If this directory is older than this backup, then move the
* attributes to old.
*
* TODO: is dirName in the right charset?
*/
bpc_attribCache_flush(&acNew, 0, (char*)dirName);
if ( statOk ) bpc_path_remove(&DeltaNew, path->s, acNew.compress);
if ( file && file->inode < Stats.Inode0 && acOldUsed && !bpc_attribCache_getFile(&acOld, (char*)dirName, 0, 0) ) {
bpc_attribCache_setFile(&acOld, (char*)dirName, file, 0);
}
bpc_attribCache_deleteFile(&acNew, (char*)dirName);
bpc_strBuf_free(path);
return 0;
}
DIR *bpc_opendir(const char *path)
{
my_DIR *d;
ssize_t entrySize;
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_opendir(%s)\n", path);
/*
* Get the total number of bytes needed to store all the file names and inode numbers
*/
if ( (entrySize = bpc_attribCache_getDirEntries(&acNew, (char*)path, NULL, 0)) < 0 ) return NULL;
if ( !(d = calloc(1, sizeof(my_DIR))) ) return NULL;
if ( !(d->entries = malloc(entrySize)) ) {
free(d);
return NULL;
}
/*
* Now populate entries with all the file names, each NULL terminated, followed by the inode number.
*/
d->entrySize = entrySize;
if ( bpc_attribCache_getDirEntries(&acNew, (char*)path, d->entries, d->entrySize) != d->entrySize ) {
free(d);
free(d->entries);
return NULL;
}
d->entryIdx = 0;
return (DIR*)d;
}
struct dirent *bpc_readdir(DIR *dir)
{
my_DIR *d = (my_DIR*)dir;
if ( d->entryIdx >= d->entrySize ) {
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_readdir -> NULL\n");
return NULL;
}
strncpy(d->dirent.d_name, d->entries + d->entryIdx, sizeof(d->dirent.d_name));
d->dirent.d_name[sizeof(d->dirent.d_name)-1] = '\0';
d->entryIdx += strlen(d->entries + d->entryIdx) + 1;
memcpy(&d->dirent.d_ino, d->entries + d->entryIdx, sizeof(ino_t));
d->entryIdx += sizeof(ino_t);
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_readdir -> %s\n", d->dirent.d_name);
return &d->dirent;
}
int bpc_closedir(DIR *dir)
{
my_DIR *d = (my_DIR*)dir;
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_closedir()\n");
if ( d->entries) free(d->entries);
free(d);
return 0;
}
/*
* xattr handling
*/
ssize_t bpc_lgetxattr(const char *path, const char *name, void *value, size_t size)
{
bpc_attrib_file *file = bpc_attribCache_getFile(&acNew, (char*)path, 0, 0);
bpc_attrib_xattr *xattr;
if ( !file ) {
if ( !am_generator ) {
errno = ENOATTR;
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_lgetxattr(%s, %s, %lu) -> no file, but return no xattr found\n", path, name, size);
return -1;
}
errno = ENOENT;
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_lgetxattr(%s, %s, %lu) -> file not found\n", path, name, size);
return -1;
}
if ( !(xattr = bpc_attrib_xattrGet(file, (char*)name, strlen(name) + 1, 0)) ) {
errno = ENOATTR;
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_lgetxattr(%s, %s, %lu) -> xattr not found\n", path, name, size);
return -1;
}
if ( !value || size == 0 ) return xattr->valueLen;
if ( xattr->valueLen <= size ) {
memcpy(value, xattr->value, xattr->valueLen);
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_lgetxattr(%s, %s, %lu) -> returning value len %u\n", path, name, size, xattr->valueLen);
return xattr->valueLen;
} else {
errno = ERANGE;
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_lgetxattr(%s, %s, %lu) -> return buffer too small (len %u)\n", path, name, size, xattr->valueLen);
return -1;
}
}
ssize_t bpc_fgetxattr(int filedes, const char *name, void *value, size_t size)
{
if ( filedes < 0 || filedes >= MAX_FD || !Fd[filedes].used ) {
errno = EBADF;
return -1;
}
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_fgetxattr(%d (%s), %s)\n", filedes, Fd[filedes].fileName->s, name);
return bpc_lgetxattr(Fd[filedes].fileName->s, name, value, size);
}
int bpc_lsetxattr(const char *path, const char *name, const void *value, size_t size, UNUSED(int flags))
{
bpc_attrib_file *file = bpc_attribCache_getFile(&acNew, (char*)path, 0, 0);
bpc_attrib_xattr *xattr;
int ret;
if ( !am_generator && (!file || !file->isTemp) ) {
/*
* We don't set xattrs for non-temp files on the receiver, since it's too hard to keep
* attribute updates on both the generator and receiver sycnhronized. Send the xattr
* setting to the generator so it can do the setting.
*/
static xbuf rename_msg = EMPTY_XBUF;
char *bufP;
uint32 pathLen = strlen(path) + 1, nameLen = strlen(name) + 1;
if ( !rename_msg.size ) {
alloc_xbuf(&rename_msg, 4096);
}
if ( rename_msg.size < 3 * sizeof(uint32) + pathLen + nameLen + size + 1024 ) {
realloc_xbuf(&rename_msg, 3 * sizeof(uint32) + pathLen + nameLen + size + 1024);
}
bufP = rename_msg.buf;
SIVAL(bufP, 0, pathLen); bufP += sizeof(uint32);
SIVAL(bufP, 0, nameLen); bufP += sizeof(uint32);
SIVAL(bufP, 0, size); bufP += sizeof(uint32);
memcpy(bufP, path, pathLen); bufP += pathLen;
memcpy(bufP, name, nameLen); bufP += nameLen;
memcpy(bufP, value, size); bufP += size;
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_lsetxattr(%s, %s, %lu) -> sending to gen (len=%d)\n", path, name, size, bufP - rename_msg.buf);
send_msg(MSG_XATTR_SET, rename_msg.buf, bufP - rename_msg.buf, 0);
return 0;
}
if ( !file ) {
errno = ENOENT;
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_lsetxattr(%s, %s, %lu) -> file not found\n", path, name, size);
return -1;
}
/*
* Check if the attribute is unchanged (we can't just call bpc_attribCache_setFile(),
* since it updates in place, meaning we then don't have the original version).
*/
if ( (xattr = bpc_attrib_xattrGet(file, (char*)name, strlen(name) + 1, 0)) ) {
if ( xattr->valueLen == size && !memcmp(xattr->value, value, xattr->valueLen) ) {
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_lsetxattr(%s, %s, %lu) -> xattr unchanged\n", path, name, size);
return 0;
}
}
/*
* Save away the attributes in old if not recently set and not present already
*/
if ( acOldUsed && !file->isTemp && file->inode < Stats.Inode0 && !bpc_attribCache_getFile(&acOld, (char*)path, 0, 0) ) {
if ( bpc_attribCache_setFile(&acOld, (char*)path, file, 1) > 0 ) {
bpc_poolRefDeltaUpdate(&DeltaOld, file->compress, &file->digest, 1);
}
}
/*
* now set the new attribute value
*/
ret = bpc_attrib_xattrSetValue(file, (char*)name, strlen(name) + 1, (void*)value, size);
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_lsetxattr(%s, %s, %lu, %d) -> return %d\n", path, name, size, ret, file->isTemp);
bpc_attribCache_setFile(&acNew, (char*)path, file, 0);
return ret < 0 ? ret : 0;
}
int bpc_lremovexattr(const char *path, const char *name)
{
bpc_attrib_file *file = bpc_attribCache_getFile(&acNew, (char*)path, 0, 0);
bpc_attrib_xattr *xattr;
int ret;
if ( !am_generator && (!file || !file->isTemp) ) {
/*
* We don't remove xattrs for non-temp files on the receiver, since it's too hard to keep
* attribute updates on both the generator and receiver sycnhronized. Send the xattr
* setting to the generator so it can do the setting.
*/
static xbuf rename_msg = EMPTY_XBUF;
char *bufP;
uint32 pathLen = strlen(path) + 1, nameLen = strlen(name) + 1;
if ( !rename_msg.size ) {
alloc_xbuf(&rename_msg, 4096);
}
if ( rename_msg.size < 3 * sizeof(uint32) + pathLen + nameLen + 1024 ) {
realloc_xbuf(&rename_msg, 3 * sizeof(uint32) + pathLen + nameLen + 1024);
}
bufP = rename_msg.buf;
SIVAL(bufP, 0, pathLen); bufP += sizeof(uint32);
SIVAL(bufP, 0, nameLen); bufP += sizeof(uint32);
memcpy(bufP, path, pathLen); bufP += pathLen;
memcpy(bufP, name, nameLen); bufP += nameLen;
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_lremovexattr(%s, %s) -> sending to gen (len=%d)\n", path, name, bufP - rename_msg.buf);
send_msg(MSG_XATTR_REMOVE, rename_msg.buf, bufP - rename_msg.buf, 0);
return 0;
}
if ( !file ) {
errno = ENOENT;
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_lremovexattr(%s, %s) -> file not found\n", path, name);
return -1;
}
/*
* Check if the attribute is exists - if not then quietly return.
*/
if ( !(xattr = bpc_attrib_xattrGet(file, (char*)name, strlen(name) + 1, 0)) ) {
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_lremovexattr(%s, %s) -> xattr not found\n", path, name);
errno = ENOATTR;
return -1;
}
/*
* Save away the attributes in old if not recently set and not present already
*/
if ( acOldUsed && !file->isTemp && file->inode < Stats.Inode0 && !bpc_attribCache_getFile(&acOld, (char*)path, 0, 0) ) {
if ( bpc_attribCache_setFile(&acOld, (char*)path, file, 1) > 0 ) {
bpc_poolRefDeltaUpdate(&DeltaOld, file->compress, &file->digest, 1);
}
}
/*
* now remove the attribute
*/
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_lremovexattr(%s, %s) -> xattr removed\n", path, name);
ret = bpc_attrib_xattrDelete(file, (char*)name, strlen(name) + 1);
bpc_attribCache_setFile(&acNew, (char*)path, file, 0);
return ret;
}
ssize_t bpc_llistxattr(const char *path, char *list, size_t size)
{
bpc_attrib_file *file = bpc_attribCache_getFile(&acNew, (char*)path, 0, 0);
if ( !file ) {
if ( !am_generator ) {
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_llistxattr(%s) -> no file, but return 0\n", path);
return 0;
}
errno = ENOENT;
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_llistxattr(%s) -> file not found\n", path);
return -1;
}
if ( LogLevel >= 4 ) bpc_logMsgf("bpc_llistxattr(%s):\n", path);
return bpc_attrib_xattrList(file, list, size, 1);
}
rsync-bpc-3.1.3.0/byteorder.h 0000664 0000000 0000000 00000006211 13737671777 0015755 0 ustar 00root root 0000000 0000000 /*
* Simple byteorder handling.
*
* Copyright (C) 1992-1995 Andrew Tridgell
* Copyright (C) 2007-2018 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
#undef AVOID_BYTEORDER_INLINE
/* We know that the x86 can handle misalignment and has the same
* byte order (LSB-first) as the 32-bit numbers we transmit. */
#if defined __i386__ || defined __i486__ || defined __i586__ || defined __i686__ || __amd64
#define CAREFUL_ALIGNMENT 1
#endif
#ifndef CAREFUL_ALIGNMENT
#define CAREFUL_ALIGNMENT 1
#endif
#define CVAL(buf,pos) (((unsigned char *)(buf))[pos])
#define UVAL(buf,pos) ((uint32)CVAL(buf,pos))
#if CAREFUL_ALIGNMENT
#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 IVAL64(buf,pos) (IVAL(buf,pos)|(int64)IVAL(buf,(pos)+4)<<32)
#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))
#define SIVAL64(buf,pos,val) (SIVAL(buf,pos,val),SIVAL(buf,(pos)+4,(val)>>32))
#define IVALu(buf,pos) IVAL(buf,pos)
#define SIVALu(buf,pos,val) SIVAL(buf,pos,val)
#else /* !CAREFUL_ALIGNMENT */
/* This handles things for architectures like the 386 that can handle alignment errors.
* WARNING: This section is dependent on the length of an int32 (and thus a uint32)
* being correct (4 bytes)! Set CAREFUL_ALIGNMENT if it is not. */
# ifdef AVOID_BYTEORDER_INLINE
#define IVAL(buf,pos) (*(uint32 *)((char *)(buf) + (pos)))
#define SIVAL(buf,pos,val) IVAL(buf,pos)=((uint32)(val))
#define IVALu(buf,pos) IVAL(buf,pos)
#define SIVALu(buf,pos,val) SIVAL(buf,pos,val)
# else /* !AVOID_BYTEORDER_INLINE */
static inline uint32
IVALu(const uchar *buf, int pos)
{
union {
const uchar *b;
const uint32 *num;
} u;
u.b = buf + pos;
return *u.num;
}
static inline void
SIVALu(uchar *buf, int pos, uint32 val)
{
union {
uchar *b;
uint32 *num;
} u;
u.b = buf + pos;
*u.num = val;
}
static inline uint32
IVAL(const char *buf, int pos)
{
return IVALu((uchar*)buf, pos);
}
static inline void
SIVAL(char *buf, int pos, uint32 val)
{
SIVALu((uchar*)buf, pos, val);
}
static inline int64
IVAL64(const char *buf, int pos)
{
union {
const char *b;
const int64 *num;
} u;
u.b = buf + pos;
return *u.num;
}
static inline void
SIVAL64(char *buf, int pos, int64 val)
{
union {
char *b;
int64 *num;
} u;
u.b = buf + pos;
*u.num = val;
}
# endif /* !AVOID_BYTEORDER_INLINE */
#endif /* !CAREFUL_ALIGNMENT */
rsync-bpc-3.1.3.0/case_N.h 0000664 0000000 0000000 00000004634 13737671777 0015155 0 ustar 00root root 0000000 0000000 /*
* Allow an arbitrary sequence of case labels.
*
* Copyright (C) 2006-2018 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 multiple times, once for every segement in a switch statement.
* This produces the next "case N:" statement in sequence. */
#if !defined CASE_N_STATE_0
#define CASE_N_STATE_0
/* FALLTHROUGH */
case 0:
#elif !defined CASE_N_STATE_1
#define CASE_N_STATE_1
/* FALLTHROUGH */
case 1:
#elif !defined CASE_N_STATE_2
#define CASE_N_STATE_2
/* FALLTHROUGH */
case 2:
#elif !defined CASE_N_STATE_3
#define CASE_N_STATE_3
/* FALLTHROUGH */
case 3:
#elif !defined CASE_N_STATE_4
#define CASE_N_STATE_4
/* FALLTHROUGH */
case 4:
#elif !defined CASE_N_STATE_5
#define CASE_N_STATE_5
/* FALLTHROUGH */
case 5:
#elif !defined CASE_N_STATE_6
#define CASE_N_STATE_6
/* FALLTHROUGH */
case 6:
#elif !defined CASE_N_STATE_7
#define CASE_N_STATE_7
/* FALLTHROUGH */
case 7:
#elif !defined CASE_N_STATE_8
#define CASE_N_STATE_8
/* FALLTHROUGH */
case 8:
#elif !defined CASE_N_STATE_9
#define CASE_N_STATE_9
/* FALLTHROUGH */
case 9:
#elif !defined CASE_N_STATE_10
#define CASE_N_STATE_10
/* FALLTHROUGH */
case 10:
#elif !defined CASE_N_STATE_11
#define CASE_N_STATE_11
/* FALLTHROUGH */
case 11:
#elif !defined CASE_N_STATE_12
#define CASE_N_STATE_12
/* FALLTHROUGH */
case 12:
#elif !defined CASE_N_STATE_13
#define CASE_N_STATE_13
/* FALLTHROUGH */
case 13:
#elif !defined CASE_N_STATE_14
#define CASE_N_STATE_14
/* FALLTHROUGH */
case 14:
#elif !defined CASE_N_STATE_15
#define CASE_N_STATE_15
/* FALLTHROUGH */
case 15:
#elif !defined CASE_N_STATE_16
#define CASE_N_STATE_16
/* FALLTHROUGH */
case 16:
#else
#error Need to add more case statements!
#endif
rsync-bpc-3.1.3.0/checksum.c 0000664 0000000 0000000 00000023162 13737671777 0015557 0 ustar 00root root 0000000 0000000 /*
* Routines to support checksumming of bytes.
*
* Copyright (C) 1996 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2004-2018 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 checksum_seed;
extern int protocol_version;
extern int proper_seed_order;
extern char *checksum_choice;
#define CSUM_NONE 0
#define CSUM_MD4_ARCHAIC 1
#define CSUM_MD4_BUSTED 2
#define CSUM_MD4_OLD 3
#define CSUM_MD4 4
#define CSUM_MD5 5
int xfersum_type = 0; /* used for the file transfer checksums */
int checksum_type = 0; /* used for the pre-transfer (--checksum) checksums */
/* Returns 1 if --whole-file must be enabled. */
int parse_checksum_choice(void)
{
char *cp = checksum_choice ? strchr(checksum_choice, ',') : NULL;
if (cp) {
xfersum_type = parse_csum_name(checksum_choice, cp - checksum_choice);
checksum_type = parse_csum_name(cp+1, -1);
} else
xfersum_type = checksum_type = parse_csum_name(checksum_choice, -1);
return xfersum_type == CSUM_NONE;
}
int parse_csum_name(const char *name, int len)
{
if (len < 0 && name)
len = strlen(name);
if (!name || (len == 4 && strncasecmp(name, "auto", 4) == 0)) {
if (protocol_version >= 30)
return CSUM_MD5;
if (protocol_version >= 27)
return CSUM_MD4_OLD;
if (protocol_version >= 21)
return CSUM_MD4_BUSTED;
return CSUM_MD4_ARCHAIC;
}
if (len == 3 && strncasecmp(name, "md4", 3) == 0)
return CSUM_MD4;
if (len == 3 && strncasecmp(name, "md5", 3) == 0)
return CSUM_MD5;
if (len == 4 && strncasecmp(name, "none", 4) == 0)
return CSUM_NONE;
rprintf(FERROR, "unknown checksum name: %s\n", name);
exit_cleanup(RERR_UNSUPPORTED);
}
int csum_len_for_type(int cst, BOOL flist_csum)
{
switch (cst) {
case CSUM_NONE:
return 1;
case CSUM_MD4_ARCHAIC:
/* The oldest checksum code is rather weird: the file-list code only sent
* 2-byte checksums, but all other checksums were full MD4 length. */
return flist_csum ? 2 : MD4_DIGEST_LEN;
case CSUM_MD4:
case CSUM_MD4_OLD:
case CSUM_MD4_BUSTED:
return MD4_DIGEST_LEN;
case CSUM_MD5:
return MD5_DIGEST_LEN;
default: /* paranoia to prevent missing case values */
exit_cleanup(RERR_UNSUPPORTED);
}
return 0;
}
int canonical_checksum(int csum_type)
{
return csum_type >= CSUM_MD4 ? 1 : 0;
}
/*
a simple 32 bit checksum that can be upadted from either end
(inspired by Mark Adler's Adler-32 checksum)
*/
uint32 get_checksum1(char *buf1, int32 len)
{
int32 i;
uint32 s1, s2;
schar *buf = (schar *)buf1;
s1 = s2 = 0;
for (i = 0; i < (len-4); i+=4) {
s2 += 4*(s1 + buf[i]) + 3*buf[i+1] + 2*buf[i+2] + buf[i+3] +
10*CHAR_OFFSET;
s1 += (buf[i+0] + buf[i+1] + buf[i+2] + buf[i+3] + 4*CHAR_OFFSET);
}
for (; i < len; i++) {
s1 += (buf[i]+CHAR_OFFSET); s2 += s1;
}
return (s1 & 0xffff) + (s2 << 16);
}
void get_checksum2(char *buf, int32 len, char *sum)
{
md_context m;
switch (xfersum_type) {
case CSUM_MD5: {
uchar seedbuf[4];
md5_begin(&m);
if (proper_seed_order) {
if (checksum_seed) {
SIVALu(seedbuf, 0, checksum_seed);
md5_update(&m, seedbuf, 4);
}
md5_update(&m, (uchar *)buf, len);
} else {
md5_update(&m, (uchar *)buf, len);
if (checksum_seed) {
SIVALu(seedbuf, 0, checksum_seed);
md5_update(&m, seedbuf, 4);
}
}
md5_result(&m, (uchar *)sum);
break;
}
case CSUM_MD4:
case CSUM_MD4_OLD:
case CSUM_MD4_BUSTED:
case CSUM_MD4_ARCHAIC: {
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 || xfersum_type > CSUM_MD4_BUSTED)
mdfour_update(&m, (uchar *)(buf1+i), len-i);
mdfour_result(&m, (uchar *)sum);
break;
}
default: /* paranoia to prevent missing case values */
exit_cleanup(RERR_UNSUPPORTED);
}
}
int file_checksum(const char *fname, const STRUCT_STAT *st_p, char *sum)
{
struct map_struct *buf;
OFF_T i, len = st_p->st_size;
md_context m;
int32 remainder;
int fd;
memset(sum, 0, MAX_DIGEST_LEN);
/*
* Try to grab the digest from the attributes, which are both MD5 for protocol >= 30.
* Otherwise fall through and do it the slow way.
*/
if ( protocol_version >= 30 ) {
if ( !bpc_file_checksum((char *)fname, sum, MD5_DIGEST_LEN) ) return 0;
/*
* if bpc_file_checksum() fails on an empty file it likely means we have a wrong
* digest, so don't recompute; this will cause the file to get re-transferred and
* the digest will be updated.
*/
if ( len == 0 ) return -1;
}
fd = do_open(fname, O_RDONLY, 0);
if (fd == -1)
return -1;
buf = map_file(fd, len, MAX_MAP_SIZE, CSUM_CHUNK);
switch (checksum_type) {
case CSUM_MD5:
md5_begin(&m);
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);
break;
case CSUM_MD4:
case CSUM_MD4_OLD:
case CSUM_MD4_BUSTED:
case CSUM_MD4_ARCHAIC:
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 || checksum_type > CSUM_MD4_BUSTED)
mdfour_update(&m, (uchar *)map_ptr(buf, i, remainder), remainder);
mdfour_result(&m, (uchar *)sum);
break;
default:
rprintf(FERROR, "invalid checksum-choice for the --checksum option (%d)\n", checksum_type);
exit_cleanup(RERR_UNSUPPORTED);
}
bpc_close(fd);
unmap_file(buf);
return 0;
}
static int32 sumresidue;
static md_context md;
static int cursum_type;
void sum_init(int csum_type, int seed)
{
char s[4];
if (csum_type < 0)
csum_type = parse_csum_name(NULL, 0);
cursum_type = csum_type;
switch (csum_type) {
case CSUM_MD5:
md5_begin(&md);
break;
case CSUM_MD4:
mdfour_begin(&md);
sumresidue = 0;
break;
case CSUM_MD4_OLD:
case CSUM_MD4_BUSTED:
case CSUM_MD4_ARCHAIC:
mdfour_begin(&md);
sumresidue = 0;
SIVAL(s, 0, seed);
sum_update(s, 4);
break;
case CSUM_NONE:
break;
default: /* paranoia to prevent missing case values */
exit_cleanup(RERR_UNSUPPORTED);
}
}
/**
* Feed data into an MD4 accumulator, md. The results may be
* retrieved using sum_end(). md is used for different purposes at
* different points during execution.
*
* @todo Perhaps get rid of md and just pass in the address each time.
* Very slightly clearer and slower.
**/
void sum_update(const char *p, int32 len)
{
switch (cursum_type) {
case CSUM_MD5:
md5_update(&md, (uchar *)p, len);
break;
case CSUM_MD4:
case CSUM_MD4_OLD:
case CSUM_MD4_BUSTED:
case CSUM_MD4_ARCHAIC:
if (len + sumresidue < CSUM_CHUNK) {
memcpy(md.buffer + sumresidue, p, len);
sumresidue += len;
break;
}
if (sumresidue) {
int32 i = CSUM_CHUNK - sumresidue;
memcpy(md.buffer + sumresidue, p, i);
mdfour_update(&md, (uchar *)md.buffer, CSUM_CHUNK);
len -= i;
p += i;
}
while (len >= CSUM_CHUNK) {
mdfour_update(&md, (uchar *)p, CSUM_CHUNK);
len -= CSUM_CHUNK;
p += CSUM_CHUNK;
}
sumresidue = len;
if (sumresidue)
memcpy(md.buffer, p, sumresidue);
break;
case CSUM_NONE:
break;
default: /* paranoia to prevent missing case values */
exit_cleanup(RERR_UNSUPPORTED);
}
}
/* NOTE: all the callers of sum_end() pass in a pointer to a buffer that is
* MAX_DIGEST_LEN in size, so even if the csum-len is shorter that that (i.e.
* CSUM_MD4_ARCHAIC), we don't have to worry about limiting the data we write
* into the "sum" buffer. */
int sum_end(char *sum)
{
switch (cursum_type) {
case CSUM_MD5:
md5_result(&md, (uchar *)sum);
break;
case CSUM_MD4:
case CSUM_MD4_OLD:
mdfour_update(&md, (uchar *)md.buffer, sumresidue);
mdfour_result(&md, (uchar *)sum);
break;
case CSUM_MD4_BUSTED:
case CSUM_MD4_ARCHAIC:
if (sumresidue)
mdfour_update(&md, (uchar *)md.buffer, sumresidue);
mdfour_result(&md, (uchar *)sum);
break;
case CSUM_NONE:
*sum = '\0';
break;
default: /* paranoia to prevent missing case values */
exit_cleanup(RERR_UNSUPPORTED);
}
return csum_len_for_type(cursum_type, 0);
}
rsync-bpc-3.1.3.0/chmod.c 0000664 0000000 0000000 00000012737 13737671777 0015055 0 ustar 00root root 0000000 0000000 /*
* Implement the core of the --chmod option.
*
* Copyright (C) 2002 Scott Howard
* Copyright (C) 2005-2018 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 "itypes.h"
extern mode_t orig_umask;
#define FLAG_X_KEEP (1<<0)
#define FLAG_DIRS_ONLY (1<<1)
#define FLAG_FILES_ONLY (1<<2)
struct chmod_mode_struct {
struct chmod_mode_struct *next;
int ModeAND, ModeOR;
char flags;
};
#define CHMOD_ADD 1
#define CHMOD_SUB 2
#define CHMOD_EQ 3
#define CHMOD_SET 4
#define STATE_ERROR 0
#define STATE_1ST_HALF 1
#define STATE_2ND_HALF 2
#define STATE_OCTAL_NUM 3
/* Parse a chmod-style argument, and break it down into one or more AND/OR
* pairs in a linked list. We return a pointer to new items on succcess
* (appending the items to the specified list), or NULL on error. */
struct chmod_mode_struct *parse_chmod(const char *modestr,
struct chmod_mode_struct **root_mode_ptr)
{
int state = STATE_1ST_HALF;
int where = 0, what = 0, op = 0, topbits = 0, topoct = 0, flags = 0;
struct chmod_mode_struct *first_mode = NULL, *curr_mode = NULL,
*prev_mode = NULL;
while (state != STATE_ERROR) {
if (!*modestr || *modestr == ',') {
int bits;
if (!op) {
state = STATE_ERROR;
break;
}
prev_mode = curr_mode;
curr_mode = new_array(struct chmod_mode_struct, 1);
if (prev_mode)
prev_mode->next = curr_mode;
else
first_mode = curr_mode;
curr_mode->next = NULL;
if (where)
bits = where * what;
else {
where = 0111;
bits = (where * what) & ~orig_umask;
}
switch (op) {
case CHMOD_ADD:
curr_mode->ModeAND = CHMOD_BITS;
curr_mode->ModeOR = bits + topoct;
break;
case CHMOD_SUB:
curr_mode->ModeAND = CHMOD_BITS - bits - topoct;
curr_mode->ModeOR = 0;
break;
case CHMOD_EQ:
curr_mode->ModeAND = CHMOD_BITS - (where * 7) - (topoct ? topbits : 0);
curr_mode->ModeOR = bits + topoct;
break;
case CHMOD_SET:
curr_mode->ModeAND = 0;
curr_mode->ModeOR = bits;
break;
}
curr_mode->flags = flags;
if (!*modestr)
break;
modestr++;
state = STATE_1ST_HALF;
where = what = op = topoct = topbits = flags = 0;
}
switch (state) {
case STATE_1ST_HALF:
switch (*modestr) {
case 'D':
if (flags & FLAG_FILES_ONLY)
state = STATE_ERROR;
flags |= FLAG_DIRS_ONLY;
break;
case 'F':
if (flags & FLAG_DIRS_ONLY)
state = STATE_ERROR;
flags |= FLAG_FILES_ONLY;
break;
case 'u':
where |= 0100;
topbits |= 04000;
break;
case 'g':
where |= 0010;
topbits |= 02000;
break;
case 'o':
where |= 0001;
break;
case 'a':
where |= 0111;
break;
case '+':
op = CHMOD_ADD;
state = STATE_2ND_HALF;
break;
case '-':
op = CHMOD_SUB;
state = STATE_2ND_HALF;
break;
case '=':
op = CHMOD_EQ;
state = STATE_2ND_HALF;
break;
default:
if (isDigit(modestr) && *modestr < '8' && !where) {
op = CHMOD_SET;
state = STATE_OCTAL_NUM;
where = 1;
what = *modestr - '0';
} else
state = STATE_ERROR;
break;
}
break;
case STATE_2ND_HALF:
switch (*modestr) {
case 'r':
what |= 4;
break;
case 'w':
what |= 2;
break;
case 'X':
flags |= FLAG_X_KEEP;
/* FALL THROUGH */
case 'x':
what |= 1;
break;
case 's':
if (topbits)
topoct |= topbits;
else
topoct = 04000;
break;
case 't':
topoct |= 01000;
break;
default:
state = STATE_ERROR;
break;
}
break;
case STATE_OCTAL_NUM:
if (isDigit(modestr) && *modestr < '8') {
what = what*8 + *modestr - '0';
if (what > CHMOD_BITS)
state = STATE_ERROR;
} else
state = STATE_ERROR;
break;
}
modestr++;
}
if (state == STATE_ERROR) {
free_chmod_mode(first_mode);
return NULL;
}
if (!(curr_mode = *root_mode_ptr))
*root_mode_ptr = first_mode;
else {
while (curr_mode->next)
curr_mode = curr_mode->next;
curr_mode->next = first_mode;
}
return first_mode;
}
/* Takes an existing file permission and a list of AND/OR changes, and
* create a new permissions. */
int tweak_mode(int mode, struct chmod_mode_struct *chmod_modes)
{
int IsX = mode & 0111;
int NonPerm = mode & ~CHMOD_BITS;
for ( ; chmod_modes; chmod_modes = chmod_modes->next) {
if ((chmod_modes->flags & FLAG_DIRS_ONLY) && !S_ISDIR(NonPerm))
continue;
if ((chmod_modes->flags & FLAG_FILES_ONLY) && S_ISDIR(NonPerm))
continue;
mode &= chmod_modes->ModeAND;
if ((chmod_modes->flags & FLAG_X_KEEP) && !IsX && !S_ISDIR(NonPerm))
mode |= chmod_modes->ModeOR & ~0111;
else
mode |= chmod_modes->ModeOR;
}
return mode | NonPerm;
}
/* Free the linked list created by parse_chmod. */
int free_chmod_mode(struct chmod_mode_struct *chmod_modes)
{
struct chmod_mode_struct *next;
while (chmod_modes) {
next = chmod_modes->next;
free(chmod_modes);
chmod_modes = next;
}
return 0;
}
rsync-bpc-3.1.3.0/cleanup.c 0000664 0000000 0000000 00000017044 13737671777 0015406 0 ustar 00root root 0000000 0000000 /*
* End-of-run cleanup routines.
*
* Copyright (C) 1996-2000 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2002 Martin Pool
* Copyright (C) 2003-2018 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 dry_run;
extern int am_server;
extern int am_daemon;
extern int am_receiver;
extern int am_generator;
extern int io_error;
extern int keep_partial;
extern int got_xfer_error;
extern int protocol_version;
extern int output_needs_newline;
extern char *partial_dir;
extern char *logfile_name;
BOOL shutting_down = False;
BOOL flush_ok_after_signal = False;
#ifdef HAVE_SIGACTION
static struct sigaction sigact;
#endif
/**
* Close all open sockets and files, allowing a (somewhat) graceful
* shutdown() of socket connections. This eliminates the abortive
* TCP RST sent by a Winsock-based system when the close() occurs.
**/
void close_all(void)
{
#ifdef SHUTDOWN_ALL_SOCKETS
int max_fd;
int fd;
int ret;
STRUCT_STAT st;
max_fd = sysconf(_SC_OPEN_MAX) - 1;
for (fd = max_fd; fd >= 0; fd--) {
if ((ret = do_fstat(fd, &st)) == 0) {
if (is_a_socket(fd))
ret = shutdown(fd, 2);
ret = close(fd);
}
}
#endif
}
/**
* @file cleanup.c
*
* Code for handling interrupted transfers. Depending on the @c
* --partial option, we may either delete the temporary file, or go
* ahead and overwrite the destination. This second behaviour only
* occurs if we've sent literal data and therefore hopefully made
* progress on the transfer.
**/
/**
* Set to True once literal data has been sent across the link for the
* current file. (????)
*
* Handling the cleanup when a transfer is interrupted is tricky when
* --partial is selected. We need to ensure that the partial file is
* kept if any real data has been transferred.
**/
int cleanup_got_literal = 0;
static const char *cleanup_fname;
static const char *cleanup_new_fname;
static struct file_struct *cleanup_file;
static int cleanup_fd_r = -1, cleanup_fd_w = -1;
static pid_t cleanup_pid = 0;
pid_t cleanup_child_pid = -1;
/**
* Eventually calls exit(), passing @p code, therefore does not return.
*
* @param code one of the RERR_* codes from errcode.h.
**/
NORETURN void _exit_cleanup(int code, const char *file, int line)
{
static int switch_step = 0;
static int exit_code = 0, exit_line = 0;
static const char *exit_file = NULL;
static int first_code = 0;
SIGACTION(SIGUSR1, SIG_IGN);
SIGACTION(SIGUSR2, SIG_IGN);
if (!exit_code) { /* Preserve first error exit info when recursing. */
exit_code = code;
exit_file = file;
exit_line = line < 0 ? -line : line;
}
/* If this is the exit at the end of the run, the server side
* should not attempt to output a message (see log_exit()). */
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 (switch_step) {
#include "case_N.h" /* case 0: */
switch_step++;
first_code = code;
if (output_needs_newline) {
fputc('\n', stdout);
output_needs_newline = 0;
}
if (DEBUG_GTE(EXIT, 2)) {
rprintf(FINFO,
"[%s] _exit_cleanup(code=%d, file=%s, line=%d): entered\n",
who_am_i(), code, file, line);
}
/* FALLTHROUGH */
#include "case_N.h"
switch_step++;
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 > exit_code)
exit_code = status;
}
}
/* FALLTHROUGH */
#include "case_N.h"
switch_step++;
if (cleanup_got_literal && (cleanup_fname || cleanup_fd_w != -1)) {
if (cleanup_fd_r != -1) {
bpc_close(cleanup_fd_r);
cleanup_fd_r = -1;
}
if (cleanup_fd_w != -1) {
flush_write_file(cleanup_fd_w);
bpc_close(cleanup_fd_w);
cleanup_fd_w = -1;
}
if (cleanup_fname && cleanup_new_fname && keep_partial
&& handle_partial_dir(cleanup_new_fname, PDIR_CREATE)) {
int tweak_modtime = 0;
const char *fname = cleanup_fname;
cleanup_fname = NULL;
if (!partial_dir) {
/* We don't want to leave a partial file with a modern time or it
* could be skipped via --update. Setting the time to something
* really old also helps it to stand out as unfinished in an ls. */
tweak_modtime = 1;
cleanup_file->modtime = 0;
}
finish_transfer(cleanup_new_fname, fname, NULL, NULL,
cleanup_file, tweak_modtime, !partial_dir);
}
}
/* FALLTHROUGH */
#include "case_N.h"
switch_step++;
if (flush_ok_after_signal) {
flush_ok_after_signal = False;
if (code == RERR_SIGNAL)
io_flush(FULL_FLUSH);
}
if (!exit_code && !code)
io_flush(FULL_FLUSH);
/* FALLTHROUGH */
#include "case_N.h"
switch_step++;
bpc_sysCall_cleanup();
if (cleanup_fname)
do_unlink(cleanup_fname);
if (exit_code)
kill_all(SIGUSR1);
if (cleanup_pid && cleanup_pid == getpid()) {
char *pidf = lp_pid_file();
if (pidf && *pidf)
unlink(lp_pid_file());
}
if (exit_code == 0) {
if (code)
exit_code = code;
if (io_error & IOERR_DEL_LIMIT)
exit_code = RERR_DEL_LIMIT;
if (io_error & IOERR_VANISHED)
exit_code = RERR_VANISHED;
if (io_error & IOERR_GENERAL || got_xfer_error)
exit_code = RERR_PARTIAL;
}
/* If line < 0, this exit is after a MSG_ERROR_EXIT event, so
* we don't want to output a duplicate error. */
if ((exit_code && line > 0)
|| am_daemon || (logfile_name && (am_server || !INFO_GTE(STATS, 1))))
log_exit(exit_code, exit_file, exit_line);
/* FALLTHROUGH */
#include "case_N.h"
switch_step++;
if (DEBUG_GTE(EXIT, 1)) {
rprintf(FINFO,
"[%s] _exit_cleanup(code=%d, file=%s, line=%d): "
"about to call exit(%d)%s\n",
who_am_i(), first_code, exit_file, exit_line, exit_code,
dry_run ? " (DRY RUN)" : "");
}
/* FALLTHROUGH */
#include "case_N.h"
switch_step++;
if (exit_code && exit_code != RERR_SOCKETIO && exit_code != RERR_STREAMIO && exit_code != RERR_SIGNAL1
&& exit_code != RERR_TIMEOUT && !shutting_down && (protocol_version >= 31 || am_receiver)) {
if (line > 0) {
if (DEBUG_GTE(EXIT, 3)) {
rprintf(FINFO, "[%s] sending MSG_ERROR_EXIT with exit_code %d\n",
who_am_i(), exit_code);
}
send_msg_int(MSG_ERROR_EXIT, exit_code);
}
noop_io_until_death();
}
/* FALLTHROUGH */
#include "case_N.h"
switch_step++;
if (am_server && exit_code)
msleep(100);
close_all();
/* FALLTHROUGH */
default:
break;
}
exit(exit_code);
}
void cleanup_disable(void)
{
cleanup_fname = cleanup_new_fname = NULL;
cleanup_fd_r = cleanup_fd_w = -1;
cleanup_got_literal = 0;
}
void cleanup_set(const char *fnametmp, const char *fname, struct file_struct *file,
int fd_r, int fd_w)
{
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;
}
void cleanup_set_pid(pid_t pid)
{
cleanup_pid = pid;
}
rsync-bpc-3.1.3.0/clientname.c 0000664 0000000 0000000 00000022305 13737671777 0016072 0 ustar 00root root 0000000 0000000 /*
* Functions for looking up the remote name or addr of a socket.
*
* Copyright (C) 1992-2001 Andrew Tridgell
* Copyright (C) 2001, 2002 Martin Pool
* Copyright (C) 2002-2018 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"
static const char default_name[] = "UNKNOWN";
extern int am_server;
/**
* Return the IP addr of the client as a string
**/
char *client_addr(int fd)
{
static char addr_buf[100];
static int initialised;
struct sockaddr_storage ss;
socklen_t length = sizeof ss;
if (initialised)
return addr_buf;
initialised = 1;
if (am_server) { /* daemon over --rsh mode */
char *env_str;
strlcpy(addr_buf, "0.0.0.0", sizeof addr_buf);
if ((env_str = getenv("REMOTE_HOST")) != NULL
|| (env_str = getenv("SSH_CONNECTION")) != NULL
|| (env_str = getenv("SSH_CLIENT")) != NULL
|| (env_str = getenv("SSH2_CLIENT")) != NULL) {
char *p;
strlcpy(addr_buf, env_str, sizeof addr_buf);
/* Truncate the value to just the IP address. */
if ((p = strchr(addr_buf, ' ')) != NULL)
*p = '\0';
}
} else {
client_sockaddr(fd, &ss, &length);
getnameinfo((struct sockaddr *)&ss, length,
addr_buf, sizeof addr_buf, NULL, 0, NI_NUMERICHOST);
}
return addr_buf;
}
static int get_sockaddr_family(const struct sockaddr_storage *ss)
{
return ((struct sockaddr *) ss)->sa_family;
}
/**
* Return the DNS name of the client.
*
* The name is statically cached so that repeated lookups are quick,
* so there is a limit of one lookup per customer.
*
* If anything goes wrong, including the name->addr->name check, then
* we just use "UNKNOWN", so you can use that value in hosts allow
* lines.
*
* After translation from sockaddr to name we do a forward lookup to
* make sure nobody is spoofing PTR records.
**/
char *client_name(int fd)
{
static char name_buf[100];
static char port_buf[100];
static int initialised;
struct sockaddr_storage ss;
socklen_t ss_len;
if (initialised)
return name_buf;
strlcpy(name_buf, default_name, sizeof name_buf);
initialised = 1;
memset(&ss, 0, sizeof ss);
if (am_server) { /* daemon over --rsh mode */
char *addr = client_addr(fd);
struct addrinfo hint, *answer;
int err;
if (strcmp(addr, "0.0.0.0") == 0)
return name_buf;
memset(&hint, 0, sizeof hint);
#ifdef AI_NUMERICHOST
hint.ai_flags = AI_NUMERICHOST;
#endif
hint.ai_socktype = SOCK_STREAM;
if ((err = getaddrinfo(addr, NULL, &hint, &answer)) != 0) {
rprintf(FLOG, "malformed address %s: %s\n",
addr, gai_strerror(err));
return name_buf;
}
switch (answer->ai_family) {
case AF_INET:
ss_len = sizeof (struct sockaddr_in);
memcpy(&ss, answer->ai_addr, ss_len);
break;
#ifdef INET6
case AF_INET6:
ss_len = sizeof (struct sockaddr_in6);
memcpy(&ss, answer->ai_addr, ss_len);
break;
#endif
default:
exit_cleanup(RERR_SOCKETIO);
}
freeaddrinfo(answer);
} else {
ss_len = sizeof ss;
client_sockaddr(fd, &ss, &ss_len);
}
if (lookup_name(fd, &ss, ss_len, name_buf, sizeof name_buf,
port_buf, sizeof port_buf) == 0)
check_name(fd, &ss, name_buf, sizeof name_buf);
return name_buf;
}
/**
* Get the sockaddr for the client.
*
* If it comes in as an ipv4 address mapped into IPv6 format then we
* convert it back to a regular IPv4.
**/
void client_sockaddr(int fd,
struct sockaddr_storage *ss,
socklen_t *ss_len)
{
memset(ss, 0, sizeof *ss);
if (getpeername(fd, (struct sockaddr *) ss, ss_len)) {
/* FIXME: Can we really not continue? */
rsyserr(FLOG, errno, "getpeername on fd%d failed", fd);
exit_cleanup(RERR_SOCKETIO);
}
#ifdef INET6
if (get_sockaddr_family(ss) == AF_INET6 &&
IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)ss)->sin6_addr)) {
/* OK, so ss is in the IPv6 family, but it is really
* an IPv4 address: something like
* "::ffff:10.130.1.2". If we use it as-is, then the
* reverse lookup might fail or perhaps something else
* bad might happen. So instead we convert it to an
* equivalent address in the IPv4 address family. */
struct sockaddr_in6 sin6;
struct sockaddr_in *sin;
memcpy(&sin6, ss, sizeof sin6);
sin = (struct sockaddr_in *)ss;
memset(sin, 0, sizeof *sin);
sin->sin_family = AF_INET;
*ss_len = sizeof (struct sockaddr_in);
#ifdef HAVE_SOCKADDR_IN_LEN
sin->sin_len = *ss_len;
#endif
sin->sin_port = sin6.sin6_port;
/* There is a macro to extract the mapped part
* (IN6_V4MAPPED_TO_SINADDR ?), but it does not seem
* to be present in the Linux headers. */
memcpy(&sin->sin_addr, &sin6.sin6_addr.s6_addr[12],
sizeof sin->sin_addr);
}
#endif
}
/**
* Look up a name from @p ss into @p name_buf.
*
* @param fd file descriptor for client socket.
**/
int lookup_name(int fd, const struct sockaddr_storage *ss,
socklen_t ss_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_size,
port_buf, port_buf_size,
NI_NAMEREQD | NI_NUMERICSERV);
if (name_err != 0) {
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;
}
return 0;
}
/**
* Compare an addrinfo from the resolver to a sockinfo.
*
* Like strcmp, returns 0 for identical.
**/
int compare_addrinfo_sockaddr(const struct addrinfo *ai,
const struct sockaddr_storage *ss)
{
int ss_family = get_sockaddr_family(ss);
const char fn[] = "compare_addrinfo_sockaddr";
if (ai->ai_family != ss_family) {
rprintf(FLOG, "%s: response family %d != %d\n",
fn, ai->ai_family, ss_family);
return 1;
}
/* The comparison method depends on the particular AF. */
if (ss_family == AF_INET) {
const struct sockaddr_in *sin1, *sin2;
sin1 = (const struct sockaddr_in *) ss;
sin2 = (const struct sockaddr_in *) ai->ai_addr;
return memcmp(&sin1->sin_addr, &sin2->sin_addr,
sizeof sin1->sin_addr);
}
#ifdef INET6
if (ss_family == AF_INET6) {
const struct sockaddr_in6 *sin1, *sin2;
sin1 = (const struct sockaddr_in6 *) ss;
sin2 = (const struct sockaddr_in6 *) ai->ai_addr;
if (ai->ai_addrlen < sizeof (struct sockaddr_in6)) {
rprintf(FLOG, "%s: too short sockaddr_in6; length=%d\n",
fn, (int)ai->ai_addrlen);
return 1;
}
if (memcmp(&sin1->sin6_addr, &sin2->sin6_addr,
sizeof sin1->sin6_addr))
return 1;
#ifdef HAVE_SOCKADDR_IN6_SCOPE_ID
if (sin1->sin6_scope_id != sin2->sin6_scope_id)
return 1;
#endif
return 0;
}
#endif /* INET6 */
/* don't know */
return 1;
}
/**
* Do a forward lookup on @p name_buf and make sure it corresponds to
* @p ss -- otherwise we may be being spoofed. If we suspect we are,
* then we don't abort the connection but just emit a warning, and
* change @p name_buf to be "UNKNOWN".
*
* We don't do anything with the service when checking the name,
* because it doesn't seem that it could be spoofed in any way, and
* getaddrinfo on random service names seems to cause problems on AIX.
**/
int check_name(int fd,
const struct sockaddr_storage *ss,
char *name_buf, size_t name_buf_size)
{
struct addrinfo hints, *res, *res0;
int error;
int ss_family = get_sockaddr_family(ss);
memset(&hints, 0, sizeof hints);
hints.ai_family = ss_family;
hints.ai_flags = AI_CANONNAME;
hints.ai_socktype = SOCK_STREAM;
error = getaddrinfo(name_buf, NULL, &hints, &res0);
if (error) {
rprintf(FLOG, "forward name lookup for %s failed: %s\n",
name_buf, gai_strerror(error));
strlcpy(name_buf, default_name, name_buf_size);
return error;
}
/* Given all these results, we expect that one of them will be
* the same as ss. The comparison is a bit complicated. */
for (res = res0; res; res = res->ai_next) {
if (!compare_addrinfo_sockaddr(res, ss))
break; /* OK, identical */
}
if (!res0) {
/* We hit the end of the list without finding an
* address that was the same as ss. */
rprintf(FLOG, "no known address for \"%s\": "
"spoofed address?\n", name_buf);
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);
strlcpy(name_buf, default_name, name_buf_size);
}
freeaddrinfo(res0);
return 0;
}
rsync-bpc-3.1.3.0/clientserver.c 0000664 0000000 0000000 00000077606 13737671777 0016476 0 ustar 00root root 0000000 0000000 /*
* The socket based protocol for setting up a connection with rsyncd.
*
* Copyright (C) 1998-2001 Andrew Tridgell
* Copyright (C) 2001-2002 Martin Pool
* Copyright (C) 2002-2018 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 "itypes.h"
extern int quiet;
extern int dry_run;
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 protect_args;
extern int ignore_errors;
extern int preserve_xattrs;
extern int kluge_around_eof;
extern int daemon_over_rsh;
extern int munge_symlinks;
extern int sanitize_paths;
extern int numeric_ids;
extern int filesfrom_fd;
extern int remote_protocol;
extern int protocol_version;
extern int io_timeout;
extern int no_detach;
extern int write_batch;
extern int default_af_hint;
extern int logfile_format_has_i;
extern int logfile_format_has_o_or_i;
extern char *bind_address;
extern char *config_file;
extern char *logfile_format;
extern char *files_from;
extern char *tmpdir;
extern struct chmod_mode_struct *chmod_modes;
extern filter_rule_list daemon_filter_list;
#ifdef ICONV_OPTION
extern char *iconv_opt;
extern iconv_t ic_send, ic_recv;
#endif
extern uid_t our_uid;
extern gid_t our_gid;
char *auth_user;
int read_only = 0;
int module_id = -1;
struct chmod_mode_struct *daemon_chmod_modes;
/* module_dirlen is the length of the module_dir string when in daemon
* mode and module_dir is not "/"; otherwise 0. (Note that a chroot-
* enabled module can have a non-"/" module_dir these days.) */
char *module_dir = NULL;
unsigned int module_dirlen = 0;
char *full_module_path;
static int rl_nulls = 0;
#ifdef HAVE_SIGACTION
static struct sigaction sigact;
#endif
static item_list gid_list = EMPTY_ITEM_LIST;
/* Used when "reverse lookup" is off. */
const char undetermined_hostname[] = "UNDETERMINED";
/**
* Run a client connected to an rsyncd. The alternative to this
* function for remote-shell connections is do_cmd().
*
* After negotiating which module to use and reading the server's
* motd, this hands over to client_run(). Telling the server the
* module will cause it to chroot/setuid/etc.
*
* Instead of doing a transfer, the client may at this stage instead
* get a listing of remote modules and exit.
*
* @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, int remote_argc, char *remote_argv[],
int argc, char *argv[])
{
int fd, ret;
char *p, *user = NULL;
/* 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 (**remote_argv == '/') {
rprintf(FERROR,
"ERROR: The remote path must start with a module name not a /\n");
return -1;
}
if ((p = strrchr(host, '@')) != NULL) {
user = host;
host = p+1;
*p = '\0';
}
fd = open_socket_out_wrapped(host, rsync_port, bind_address,
default_af_hint);
if (fd == -1)
exit_cleanup(RERR_SOCKETIO);
#ifdef ICONV_CONST
setup_iconv();
#endif
ret = start_inband_exchange(fd, fd, user, remote_argc, remote_argv);
return ret ? ret : client_run(fd, fd, -1, argc, argv);
}
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, 0)) {
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, modlen;
char line[BIGPATHBUFLEN];
char *sargs[MAX_ARGS];
int sargc = 0;
char *p, *modname;
assert(argc > 0 && *argv != NULL);
if (**argv == '/') {
rprintf(FERROR,
"ERROR: The remote path must start with a module name\n");
return -1;
}
if (!(p = strchr(*argv, '/')))
modlen = strlen(*argv);
else
modlen = p - *argv;
if (!(modname = new_array(char, modlen+1+1))) /* room for '/' & '\0' */
out_of_memory("start_inband_exchange");
strlcpy(modname, *argv, modlen + 1);
modname[modlen] = '/';
modname[modlen+1] = '\0';
if (!user)
user = getenv("USER");
if (!user)
user = getenv("LOGNAME");
if (exchange_protocols(f_in, f_out, line, sizeof line, 1) < 0)
return -1;
/* set daemon_over_rsh to false since we need to build the
* true set of args passed through the rsh/ssh connection;
* this is a no-op for direct-socket-connection mode */
daemon_over_rsh = 0;
server_options(sargs, &sargc);
if (sargc >= MAX_ARGS - 2)
goto arg_overflow;
sargs[sargc++] = ".";
while (argc > 0) {
if (sargc >= MAX_ARGS - 1) {
arg_overflow:
rprintf(FERROR, "internal: args[] overflowed in do_cmd()\n");
exit_cleanup(RERR_SYNTAX);
}
if (strncmp(*argv, modname, modlen) == 0
&& argv[0][modlen] == '\0')
sargs[sargc++] = modname; /* we send "modname/" */
else if (**argv == '-') {
if (asprintf(sargs + sargc++, "./%s", *argv) < 0)
out_of_memory("start_inband_exchange");
} else
sargs[sargc++] = *argv;
argv++;
argc--;
}
sargs[sargc] = NULL;
if (DEBUG_GTE(CMD, 1))
print_child_argv("sending daemon args:", sargs);
io_printf(f_out, "%.*s\n", modlen, modname);
/* Old servers may just drop the connection here,
rather than sending a proper EXIT command. Yuck. */
kluge_around_eof = list_only && protocol_version < 25 ? 1 : 0;
while (1) {
if (!read_line_old(f_in, line, sizeof line, 0)) {
rprintf(FERROR, "rsync: didn't get server startup line\n");
return -1;
}
if (strncmp(line,"@RSYNCD: AUTHREQD ",18) == 0) {
auth_client(f_out, user, line+18);
continue;
}
if (strcmp(line,"@RSYNCD: OK") == 0)
break;
if (strcmp(line,"@RSYNCD: EXIT") == 0) {
/* This is sent by recent versions of the
* server to terminate the listing of modules.
* We don't want to go on and transfer
* anything; just exit. */
exit(0);
}
if (strncmp(line, "@ERROR", 6) == 0) {
rprintf(FERROR, "%s\n", line);
/* This is always fatal; the server will now
* close the socket. */
return -1;
}
/* 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;
if (rl_nulls) {
for (i = 0; i < sargc; i++) {
if (!sargs[i]) /* stop at --protect-args NULL */
break;
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");
}
if (protect_args)
send_protected_args(f_out, sargs);
if (protocol_version < 23) {
if (protocol_version == 22 || !am_sender)
io_start_multiplex_in(f_in);
}
free(modname);
return 0;
}
static char *finish_pre_exec(pid_t pid, int write_fd, int read_fd, char *request,
char **early_argv, char **argv)
{
char buf[BIGPATHBUFLEN], *bp;
int j = 0, status = -1, msglen = sizeof buf - 1;
if (!request)
request = "(NONE)";
write_buf(write_fd, request, strlen(request)+1);
if (early_argv) {
for ( ; *early_argv; early_argv++)
write_buf(write_fd, *early_argv, strlen(*early_argv)+1);
j = 1; /* Skip arg0 name in argv. */
}
for ( ; argv[j]; j++)
write_buf(write_fd, argv[j], strlen(argv[j])+1);
write_byte(write_fd, 0);
close(write_fd);
/* Read the stdout from the pre-xfer exec program. This it is only
* displayed to the user if the script also returns an error status. */
for (bp = buf; msglen > 0; msglen -= j) {
if ((j = read(read_fd, bp, msglen)) <= 0) {
if (j == 0)
break;
if (errno == EINTR)
continue;
break; /* Just ignore the read error for now... */
}
bp += j;
if (j > 1 && bp[-1] == '\n' && bp[-2] == '\r') {
bp--;
j--;
bp[-1] = '\n';
}
}
*bp = '\0';
close(read_fd);
if (wait_process(pid, &status, 0) < 0
|| !WIFEXITED(status) || WEXITSTATUS(status) != 0) {
char *e;
if (asprintf(&e, "pre-xfer exec returned failure (%d)%s%s%s\n%s",
status, status < 0 ? ": " : "",
status < 0 ? strerror(errno) : "",
*buf ? ":" : "", buf) < 0)
return "out_of_memory in finish_pre_exec\n";
return e;
}
return NULL;
}
#ifdef HAVE_PUTENV
static int read_arg_from_pipe(int fd, char *buf, int limit)
{
char *bp = buf, *eob = buf + limit - 1;
while (1) {
int got = read(fd, bp, 1);
if (got != 1) {
if (got < 0 && errno == EINTR)
continue;
return -1;
}
if (*bp == '\0')
break;
if (bp < eob)
bp++;
}
*bp = '\0';
return bp - buf;
}
#endif
static int path_failure(int f_out, const char *dir, BOOL was_chdir)
{
if (was_chdir)
rsyserr(FLOG, errno, "chdir %s failed", dir);
else
rprintf(FLOG, "normalize_path(%s) failed\n", dir);
io_printf(f_out, "@ERROR: chdir failed\n");
return -1;
}
static int add_a_group(int f_out, const char *gname)
{
gid_t gid, *gid_p;
if (!group_to_gid(gname, &gid, True)) {
rprintf(FLOG, "Invalid gid %s\n", gname);
io_printf(f_out, "@ERROR: invalid gid %s\n", gname);
return -1;
}
gid_p = EXPAND_ITEM_LIST(&gid_list, gid_t, -32);
*gid_p = gid;
return 0;
}
#ifdef HAVE_GETGROUPLIST
static int want_all_groups(int f_out, uid_t uid)
{
const char *err;
if ((err = getallgroups(uid, &gid_list)) != NULL) {
rsyserr(FLOG, errno, "%s", err);
io_printf(f_out, "@ERROR: %s\n", err);
return -1;
}
return 0;
}
#elif defined HAVE_INITGROUPS
static struct passwd *want_all_groups(int f_out, uid_t uid)
{
struct passwd *pw;
gid_t *gid_p;
if ((pw = getpwuid(uid)) == NULL) {
rsyserr(FLOG, errno, "getpwuid failed");
io_printf(f_out, "@ERROR: getpwuid failed\n");
return NULL;
}
/* Start with the default group and initgroups() will add the rest. */
gid_p = EXPAND_ITEM_LIST(&gid_list, gid_t, -32);
*gid_p = pw->pw_gid;
return pw;
}
#endif
static void set_env_str(const char *var, const char *str)
{
#ifdef HAVE_PUTENV
char *mem;
if (asprintf(&mem, "%s=%s", var, str) < 0)
out_of_memory("set_env_str");
putenv(mem);
#endif
}
#ifdef HAVE_PUTENV
static void set_env_num(const char *var, long num)
{
char *mem;
if (asprintf(&mem, "%s=%ld", var, num) < 0)
out_of_memory("set_env_num");
putenv(mem);
}
#endif
static int rsync_module(int f_in, int f_out, int i, const char *addr, const char *host)
{
int argc;
char **argv, **orig_argv, **orig_early_argv, *module_chdir;
char line[BIGPATHBUFLEN];
#if defined HAVE_INITGROUPS && !defined HAVE_GETGROUPLIST
struct passwd *pw = NULL;
#endif
uid_t uid;
int set_uid;
char *p, *err_msg = NULL;
char *name = lp_name(i);
int use_chroot = lp_use_chroot(i);
int ret, pre_exec_arg_fd = -1, pre_exec_error_fd = -1;
int save_munge_symlinks;
pid_t pre_exec_pid = 0;
char *request = NULL;
set_env_str("RSYNC_MODULE_NAME", name);
#ifdef ICONV_OPTION
iconv_opt = lp_charset(i);
if (*iconv_opt)
setup_iconv();
iconv_opt = NULL;
#endif
/* If reverse lookup is disabled globally but enabled for this module,
* we need to do it now before the access check. */
if (host == undetermined_hostname && lp_reverse_lookup(i))
host = client_name(f_in);
set_env_str("RSYNC_HOST_NAME", host);
set_env_str("RSYNC_HOST_ADDR", addr);
if (!allow_access(addr, &host, i)) {
rprintf(FLOG, "rsync denied on module %s from %s (%s)\n",
name, host, addr);
if (!lp_list(i))
io_printf(f_out, "@ERROR: Unknown module '%s'\n", name);
else {
io_printf(f_out,
"@ERROR: access denied to %s from %s (%s)\n",
name, host, addr);
}
return -1;
}
if (am_daemon && am_server) {
rprintf(FLOG, "rsync allowed access on module %s from %s (%s)\n",
name, host, addr);
}
if (!claim_connection(lp_lock_file(i), lp_max_connections(i))) {
if (errno) {
rsyserr(FLOG, errno, "failed to open lock file %s",
lp_lock_file(i));
io_printf(f_out, "@ERROR: failed to open lock file\n");
} else {
rprintf(FLOG, "max connections (%d) reached\n",
lp_max_connections(i));
io_printf(f_out, "@ERROR: max connections (%d) reached -- try again later\n",
lp_max_connections(i));
}
return -1;
}
read_only = lp_read_only(i); /* may also be overridden by auth_server() */
auth_user = auth_server(f_in, f_out, i, host, addr, "@RSYNCD: AUTHREQD ");
if (!auth_user) {
io_printf(f_out, "@ERROR: auth failed on module %s\n", name);
return -1;
}
set_env_str("RSYNC_USER_NAME", auth_user);
module_id = i;
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;
uid = MY_UID();
am_root = (uid == 0);
p = *lp_uid(i) ? lp_uid(i) : am_root ? NOBODY_USER : NULL;
if (p) {
if (!user_to_uid(p, &uid, True)) {
rprintf(FLOG, "Invalid uid %s\n", p);
io_printf(f_out, "@ERROR: invalid uid %s\n", p);
return -1;
}
set_uid = 1;
} else
set_uid = 0;
p = *lp_gid(i) ? conf_strtok(lp_gid(i)) : NULL;
if (p) {
/* The "*" gid must be the first item in the list. */
if (strcmp(p, "*") == 0) {
#ifdef HAVE_GETGROUPLIST
if (want_all_groups(f_out, uid) < 0)
return -1;
#elif defined HAVE_INITGROUPS
if ((pw = want_all_groups(f_out, uid)) == NULL)
return -1;
#else
rprintf(FLOG, "This rsync does not support a gid of \"*\"\n");
io_printf(f_out, "@ERROR: invalid gid setting.\n");
return -1;
#endif
} else if (add_a_group(f_out, p) < 0)
return -1;
while ((p = conf_strtok(NULL)) != NULL) {
#if defined HAVE_INITGROUPS && !defined HAVE_GETGROUPLIST
if (pw) {
rprintf(FLOG, "This rsync cannot add groups after \"*\".\n");
io_printf(f_out, "@ERROR: invalid gid setting.\n");
return -1;
}
#endif
if (add_a_group(f_out, p) < 0)
return -1;
}
} else if (am_root) {
if (add_a_group(f_out, NOBODY_GROUP) < 0)
return -1;
}
module_dir = lp_path(i);
if (*module_dir == '\0') {
rprintf(FLOG, "No path specified for module %s\n", name);
io_printf(f_out, "@ERROR: no path setting.\n");
return -1;
}
if (use_chroot) {
if ((p = strstr(module_dir, "/./")) != NULL) {
*p = '\0'; /* Temporary... */
if (!(module_chdir = normalize_path(module_dir, True, NULL)))
return path_failure(f_out, module_dir, False);
*p = '/';
if (!(p = normalize_path(p + 2, True, &module_dirlen)))
return path_failure(f_out, strstr(module_dir, "/./"), False);
if (!(full_module_path = normalize_path(module_dir, False, NULL)))
full_module_path = module_dir;
module_dir = p;
} else {
if (!(module_chdir = normalize_path(module_dir, False, NULL)))
return path_failure(f_out, module_dir, False);
full_module_path = module_chdir;
module_dir = "/";
module_dirlen = 1;
}
} else {
if (!(module_chdir = normalize_path(module_dir, False, &module_dirlen)))
return path_failure(f_out, module_dir, False);
full_module_path = module_dir = module_chdir;
}
set_env_str("RSYNC_MODULE_PATH", full_module_path);
if (module_dirlen == 1) {
module_dirlen = 0;
set_filter_dir("/", 1);
} else
set_filter_dir(module_dir, module_dirlen);
p = lp_filter(i);
parse_filter_str(&daemon_filter_list, p, rule_template(FILTRULE_WORD_SPLIT),
XFLG_ABS_IF_SLASH | XFLG_DIR2WILD3);
p = lp_include_from(i);
parse_filter_file(&daemon_filter_list, p, rule_template(FILTRULE_INCLUDE),
XFLG_ABS_IF_SLASH | XFLG_DIR2WILD3 | XFLG_OLD_PREFIXES | XFLG_FATAL_ERRORS);
p = lp_include(i);
parse_filter_str(&daemon_filter_list, p,
rule_template(FILTRULE_INCLUDE | FILTRULE_WORD_SPLIT),
XFLG_ABS_IF_SLASH | XFLG_DIR2WILD3 | XFLG_OLD_PREFIXES);
p = lp_exclude_from(i);
parse_filter_file(&daemon_filter_list, p, rule_template(0),
XFLG_ABS_IF_SLASH | XFLG_DIR2WILD3 | XFLG_OLD_PREFIXES | XFLG_FATAL_ERRORS);
p = lp_exclude(i);
parse_filter_str(&daemon_filter_list, p, rule_template(FILTRULE_WORD_SPLIT),
XFLG_ABS_IF_SLASH | XFLG_DIR2WILD3 | XFLG_OLD_PREFIXES);
log_init(1);
#ifdef HAVE_PUTENV
if (*lp_prexfer_exec(i) || *lp_postxfer_exec(i)) {
int status;
/* For post-xfer exec, fork a new process to run the rsync
* daemon while this process waits for the exit status and
* runs the indicated command at that point. */
if (*lp_postxfer_exec(i)) {
pid_t pid = fork();
if (pid < 0) {
rsyserr(FLOG, errno, "fork failed");
io_printf(f_out, "@ERROR: fork failed\n");
return -1;
}
if (pid) {
close(f_in);
if (f_out != f_in)
close(f_out);
set_env_num("RSYNC_PID", (long)pid);
if (wait_process(pid, &status, 0) < 0)
status = -1;
set_env_num("RSYNC_RAW_STATUS", status);
if (WIFEXITED(status))
status = WEXITSTATUS(status);
else
status = -1;
set_env_num("RSYNC_EXIT_STATUS", status);
if (system(lp_postxfer_exec(i)) < 0)
status = -1;
_exit(status);
}
}
/* For pre-xfer exec, fork a child process to run the indicated
* command, though it first waits for the parent process to
* send us the user's request via a pipe. */
if (*lp_prexfer_exec(i)) {
int arg_fds[2], error_fds[2];
set_env_num("RSYNC_PID", (long)getpid());
if (pipe(arg_fds) < 0 || pipe(error_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");
return -1;
}
if (pre_exec_pid == 0) {
char buf[BIGPATHBUFLEN];
int j, len;
close(arg_fds[1]);
close(error_fds[0]);
pre_exec_arg_fd = arg_fds[0];
pre_exec_error_fd = error_fds[1];
set_blocking(pre_exec_arg_fd);
set_blocking(pre_exec_error_fd);
len = read_arg_from_pipe(pre_exec_arg_fd, buf, BIGPATHBUFLEN);
if (len <= 0)
_exit(1);
set_env_str("RSYNC_REQUEST", buf);
for (j = 0; ; j++) {
len = read_arg_from_pipe(pre_exec_arg_fd, buf,
BIGPATHBUFLEN);
if (len <= 0) {
if (!len)
break;
_exit(1);
}
if (asprintf(&p, "RSYNC_ARG%d=%s", j, buf) >= 0)
putenv(p);
}
close(pre_exec_arg_fd);
close(STDIN_FILENO);
dup2(pre_exec_error_fd, STDOUT_FILENO);
close(pre_exec_error_fd);
status = system(lp_prexfer_exec(i));
if (!WIFEXITED(status))
_exit(1);
_exit(WEXITSTATUS(status));
}
close(arg_fds[0]);
close(error_fds[1]);
pre_exec_arg_fd = arg_fds[1];
pre_exec_error_fd = error_fds[0];
set_blocking(pre_exec_arg_fd);
set_blocking(pre_exec_error_fd);
}
}
#endif
if (use_chroot) {
/*
* XXX: The 'use chroot' flag is a fairly reliable
* source of confusion, because it fails under two
* important circumstances: running as non-root,
* running on Win32 (or possibly others). On the
* other hand, if you are running as root, then it
* might be better to always use chroot.
*
* So, perhaps if we can't chroot we should just issue
* a warning, unless a "require chroot" flag is set,
* in which case we fail.
*/
if (chroot(module_chdir)) {
rsyserr(FLOG, errno, "chroot %s failed", module_chdir);
io_printf(f_out, "@ERROR: chroot failed\n");
return -1;
}
module_chdir = module_dir;
}
if (!change_dir(module_chdir, CD_NORMAL))
return path_failure(f_out, module_chdir, True);
if (module_dirlen || (!use_chroot && !*lp_daemon_chroot()))
sanitize_paths = 1;
if ((munge_symlinks = lp_munge_symlinks(i)) < 0)
munge_symlinks = !use_chroot || module_dirlen;
if (munge_symlinks) {
STRUCT_STAT st;
char prefix[SYMLINK_PREFIX_LEN]; /* NOT +1 ! */
strlcpy(prefix, SYMLINK_PREFIX, sizeof prefix); /* trim the trailing slash */
if (do_stat(prefix, &st) == 0 && S_ISDIR(st.st_mode)) {
rprintf(FLOG, "Symlink munging is unsafe when a %s directory exists.\n",
prefix);
io_printf(f_out, "@ERROR: daemon security issue -- contact admin\n", name);
exit_cleanup(RERR_UNSUPPORTED);
}
}
if (gid_list.count) {
gid_t *gid_array = gid_list.items;
if (setgid(gid_array[0])) {
rsyserr(FLOG, errno, "setgid %ld failed", (long)gid_array[0]);
io_printf(f_out, "@ERROR: setgid failed\n");
return -1;
}
#ifdef HAVE_SETGROUPS
/* Set the group(s) we want to be active. */
if (setgroups(gid_list.count, gid_array)) {
rsyserr(FLOG, errno, "setgroups failed");
io_printf(f_out, "@ERROR: setgroups failed\n");
return -1;
}
#endif
#if defined HAVE_INITGROUPS && !defined HAVE_GETGROUPLIST
/* pw is set if the user wants all the user's groups. */
if (pw && initgroups(pw->pw_name, pw->pw_gid) < 0) {
rsyserr(FLOG, errno, "initgroups failed");
io_printf(f_out, "@ERROR: initgroups failed\n");
return -1;
}
#endif
our_gid = MY_GID();
}
if (set_uid) {
if (setuid(uid) < 0
#ifdef HAVE_SETEUID
|| seteuid(uid) < 0
#endif
) {
rsyserr(FLOG, errno, "setuid %ld failed", (long)uid);
io_printf(f_out, "@ERROR: setuid failed\n");
return -1;
}
our_uid = MY_UID();
am_root = (our_uid == 0);
}
if (lp_temp_dir(i) && *lp_temp_dir(i)) {
tmpdir = lp_temp_dir(i);
if (strlen(tmpdir) >= MAXPATHLEN - 10) {
rprintf(FLOG,
"the 'temp dir' value for %s is WAY too long -- ignoring.\n",
name);
tmpdir = NULL;
}
}
io_printf(f_out, "@RSYNCD: OK\n");
read_args(f_in, name, line, sizeof line, rl_nulls, &argv, &argc, &request);
orig_argv = argv;
save_munge_symlinks = munge_symlinks;
reset_output_levels(); /* future verbosity is controlled by client options */
ret = parse_arguments(&argc, (const char ***) &argv);
if (protect_args && ret) {
orig_early_argv = orig_argv;
protect_args = 2;
read_args(f_in, name, line, sizeof line, 1, &argv, &argc, &request);
orig_argv = argv;
ret = parse_arguments(&argc, (const char ***) &argv);
} else
orig_early_argv = NULL;
munge_symlinks = save_munge_symlinks; /* The client mustn't control this. */
if (pre_exec_pid) {
err_msg = finish_pre_exec(pre_exec_pid, pre_exec_arg_fd, pre_exec_error_fd,
request, orig_early_argv, orig_argv);
}
if (orig_early_argv)
free(orig_early_argv);
am_server = 1; /* Don't let someone try to be tricky. */
quiet = 0;
if (lp_ignore_errors(module_id))
ignore_errors = 1;
if (write_batch < 0)
dry_run = 1;
if (lp_fake_super(i)) {
if (preserve_xattrs > 1)
preserve_xattrs = 1;
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;
if (request) {
if (*auth_user) {
rprintf(FLOG, "rsync %s %s from %s@%s (%s)\n",
am_sender ? "on" : "to",
request, auth_user, host, addr);
} else {
rprintf(FLOG, "rsync %s %s from %s (%s)\n",
am_sender ? "on" : "to",
request, host, addr);
}
free(request);
}
#ifndef DEBUG
/* don't allow the logs to be flooded too fast */
limit_output_verbosity(lp_max_verbosity(i));
#endif
if (protocol_version < 23
&& (protocol_version == 22 || am_sender))
io_start_multiplex_out(f_out);
else if (!ret || err_msg) {
/* We have to get I/O multiplexing started so that we can
* get the error back to the client. This means getting
* the protocol setup finished first in later versions. */
setup_protocol(f_out, f_in);
if (!am_sender) {
/* Since we failed in our option parsing, we may not
* have finished parsing that the client sent us a
* --files-from option, so look for it manually.
* Without this, the socket would be in the wrong
* state for the upcoming error message. */
if (!files_from) {
int i;
for (i = 0; i < argc; i++) {
if (strncmp(argv[i], "--files-from", 12) == 0) {
files_from = "";
break;
}
}
}
if (files_from)
write_byte(f_out, 0);
}
io_start_multiplex_out(f_out);
}
if (!ret || err_msg) {
if (err_msg) {
while ((p = strchr(err_msg, '\n')) != NULL) {
int len = p - err_msg + 1;
rwrite(FERROR, err_msg, len, 0);
err_msg += len;
}
if (*err_msg)
rprintf(FERROR, "%s\n", err_msg);
} else
option_error();
msleep(400);
exit_cleanup(RERR_UNSUPPORTED);
}
#ifdef ICONV_OPTION
if (!iconv_opt) {
if (ic_send != (iconv_t)-1) {
iconv_close(ic_send);
ic_send = (iconv_t)-1;
}
if (ic_recv != (iconv_t)-1) {
iconv_close(ic_recv);
ic_recv = (iconv_t)-1;
}
}
#endif
if (!numeric_ids
&& (use_chroot ? lp_numeric_ids(i) != False : lp_numeric_ids(i) == True))
numeric_ids = -1; /* Set --numeric-ids w/o breaking protocol. */
if (lp_timeout(i) && (!io_timeout || lp_timeout(i) < io_timeout))
set_io_timeout(lp_timeout(i));
/* If we have some incoming/outgoing chmod changes, append them to
* any user-specified changes (making our changes have priority).
* We also get a pointer to just our changes so that a receiver
* process can use them separately if --perms wasn't specified. */
if (am_sender)
p = lp_outgoing_chmod(i);
else
p = lp_incoming_chmod(i);
if (*p && !(daemon_chmod_modes = parse_chmod(p, &chmod_modes))) {
rprintf(FLOG, "Invalid \"%sing chmod\" directive: %s\n",
am_sender ? "outgo" : "incom", p);
}
start_server(f_in, f_out, argc, argv);
return 0;
}
/* send a list of available modules to the client. Don't list those
with "list = False". */
static void send_listing(int fd)
{
int n = lp_num_modules();
int i;
for (i = 0; i < n; i++) {
if (lp_list(i))
io_printf(fd, "%-15s\t%s\n", lp_name(i), lp_comment(i));
}
if (protocol_version >= 25)
io_printf(fd,"@RSYNCD: EXIT\n");
}
static int load_config(int globals_only)
{
if (!config_file) {
if (am_server && am_root <= 0)
config_file = RSYNCD_USERCONF;
else
config_file = RSYNCD_SYSCONF;
}
return lp_load(config_file, globals_only);
}
/* this is called when a connection is established to a client
and we want to start talking. The setup of the system is done from
here */
int start_daemon(int f_in, int f_out)
{
char line[1024];
const char *addr, *host;
char *p;
int i;
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 (!load_config(0))
exit_cleanup(RERR_SYNTAX);
p = lp_daemon_chroot();
if (*p) {
log_init(0); /* Make use we've initialized syslog before chrooting. */
if (chroot(p) < 0 || chdir("/") < 0) {
rsyserr(FLOG, errno, "daemon chroot %s failed", p);
return -1;
}
}
p = lp_daemon_gid();
if (*p) {
gid_t gid;
if (!group_to_gid(p, &gid, True)) {
rprintf(FLOG, "Invalid daemon gid: %s\n", p);
return -1;
}
if (setgid(gid) < 0) {
rsyserr(FLOG, errno, "Unable to set group to daemon gid %ld", (long)gid);
return -1;
}
our_gid = MY_GID();
}
p = lp_daemon_uid();
if (*p) {
uid_t uid;
if (!user_to_uid(p, &uid, True)) {
rprintf(FLOG, "Invalid daemon uid: %s\n", p);
return -1;
}
if (setuid(uid) < 0) {
rsyserr(FLOG, errno, "Unable to set user to daemon uid %ld", (long)uid);
return -1;
}
our_uid = MY_UID();
am_root = (our_uid == 0);
}
addr = client_addr(f_in);
host = lp_reverse_lookup(-1) ? client_name(f_in) : undetermined_hostname;
rprintf(FLOG, "connect from %s (%s)\n", host, addr);
if (!am_server) {
set_socket_options(f_in, "SO_KEEPALIVE");
set_nonblocking(f_in);
}
if (exchange_protocols(f_in, f_out, line, sizeof line, 0) < 0)
return -1;
line[0] = 0;
if (!read_line_old(f_in, line, sizeof line, 0))
return -1;
if (!*line || strcmp(line, "#list") == 0) {
rprintf(FLOG, "module-list request from %s (%s)\n",
host, addr);
send_listing(f_out);
return -1;
}
if (*line == '#') {
/* it's some sort of command that I don't understand */
io_printf(f_out, "@ERROR: Unknown command '%s'\n", line);
return -1;
}
if ((i = lp_number(line)) < 0) {
rprintf(FLOG, "unknown module '%s' tried from %s (%s)\n",
line, host, addr);
io_printf(f_out, "@ERROR: Unknown module '%s'\n", line);
return -1;
}
#ifdef HAVE_SIGACTION
sigact.sa_flags = SA_NOCLDSTOP;
#endif
SIGACTION(SIGCHLD, remember_children);
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, len;
if (!pid_file || !*pid_file)
return;
cleanup_set_pid(pid);
if ((fd = do_open(pid_file, O_WRONLY|O_CREAT|O_EXCL, 0666)) == -1) {
failure:
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, "%d\n", (int)pid);
len = strlen(pidbuf);
if (write(fd, pidbuf, len) != len)
goto failure;
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)
{
if (is_a_socket(STDIN_FILENO)) {
int i;
/* we are running via inetd - close off stdout and
* stderr so that library functions (and getopt) don't
* try to use them. Redirect them to /dev/null */
for (i = 1; i < 3; i++) {
close(i);
open("/dev/null", O_RDWR);
}
return start_daemon(STDIN_FILENO, STDIN_FILENO);
}
if (!load_config(1)) {
fprintf(stderr, "Failed to parse config file: %s\n", config_file);
exit_cleanup(RERR_SYNTAX);
}
set_dparams(0);
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(0);
rprintf(FLOG, "rsyncd version %s starting, listening on port %d\n",
RSYNC_VERSION, rsync_port);
/* TODO: If listening on a particular address, then show that
* address too. In fact, why not just do getnameinfo on the
* local address??? */
start_accept_loop(rsync_port, start_daemon);
return -1;
}
rsync-bpc-3.1.3.0/compat.c 0000664 0000000 0000000 00000023500 13737671777 0015234 0 ustar 00root root 0000000 0000000 /*
* Compatibility routines for older rsync protocol versions.
*
* Copyright (C) Andrew Tridgell 1996
* Copyright (C) Paul Mackerras 1996
* Copyright (C) 2004-2018 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;
int compat_flags = 0;
int use_safe_inc_flist = 0;
int want_xattr_optim = 0;
int proper_seed_order = 0;
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 preallocate_files;
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;
extern char *partial_dir;
extern char *dest_option;
extern char *files_from;
extern char *filesfrom_host;
extern filter_rule_list filter_list;
extern int need_unsorted_flist;
#ifdef ICONV_OPTION
extern iconv_t ic_send, ic_recv;
extern char *iconv_opt;
#endif
/* These index values are for the file-list's extra-attribute array. */
int uid_ndx, gid_ndx, acls_ndx, xattrs_ndx, unsort_ndx;
int receiver_symlink_times = 0; /* receiver can set the time on a symlink */
int sender_symlink_iconv = 0; /* sender should convert symlink content */
#ifdef ICONV_OPTION
int filesfrom_convert = 0;
#endif
#define CF_INC_RECURSE (1<<0)
#define CF_SYMLINK_TIMES (1<<1)
#define CF_SYMLINK_ICONV (1<<2)
#define CF_SAFE_FLIST (1<<3)
#define CF_AVOID_XATTR_OPTIM (1<<4)
#define CF_CHKSUM_SEED_FIX (1<<5)
static const char *client_info;
/* 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
/* client_info starts with VER.SUB string if client is a pre-release. */
if (!(their_protocol = atoi(client_info))
|| !(dot = strchr(client_info, '.'))
|| !(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 set_allow_inc_recurse(void)
{
client_info = shell_cmd ? shell_cmd : "";
if (!recurse || use_qsort)
allow_inc_recurse = 0;
else if (!am_sender
&& (delete_before || delete_after
|| delay_updates || prune_empty_dirs))
allow_inc_recurse = 0;
else if (am_server && !local_server
&& (strchr(client_info, 'i') == NULL))
allow_inc_recurse = 0;
}
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 (am_server)
set_allow_inc_recurse();
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);
if (protocol_version > remote_protocol)
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",
remote_protocol, protocol_version);
exit_cleanup(RERR_PROTOCOL);
}
if (DEBUG_GTE(PROTO, 1)) {
rprintf(FINFO, "(%s) Protocol versions: remote=%d, negotiated=%d\n",
am_server? "Server" : "Client", remote_protocol, protocol_version);
}
if (remote_protocol < MIN_PROTOCOL_VERSION
|| remote_protocol > MAX_PROTOCOL_VERSION) {
rprintf(FERROR,"protocol version mismatch -- is your shell clean?\n");
rprintf(FERROR,"(see the rsync man page for an explanation)\n");
exit_cleanup(RERR_PROTOCOL);
}
if (remote_protocol < OLD_PROTOCOL_VERSION) {
rprintf(FINFO,"%s is very old version of rsync, upgrade recommended.\n",
am_server? "Client" : "Server");
}
if (protocol_version < MIN_PROTOCOL_VERSION) {
rprintf(FERROR, "--protocol must be at least %d on the %s.\n",
MIN_PROTOCOL_VERSION, am_server? "Server" : "Client");
exit_cleanup(RERR_PROTOCOL);
}
if (protocol_version > PROTOCOL_VERSION) {
rprintf(FERROR, "--protocol must be no more than %d on the %s.\n",
PROTOCOL_VERSION, am_server? "Server" : "Client");
exit_cleanup(RERR_PROTOCOL);
}
if (read_batch)
check_batch_flags();
#ifndef SUPPORT_PREALLOCATION
if (preallocate_files && !am_sender) {
rprintf(FERROR, "preallocation is not supported on this %s\n",
am_server ? "Server" : "Client");
exit_cleanup(RERR_SYNTAX);
}
#endif
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,
"--fuzzy requires protocol 29 or higher"
" (negotiated %d).\n",
protocol_version);
exit_cleanup(RERR_PROTOCOL);
}
if (basis_dir_cnt && inplace) {
rprintf(FERROR,
"%s with --inplace requires protocol 29 or higher"
" (negotiated %d).\n",
dest_option, protocol_version);
exit_cleanup(RERR_PROTOCOL);
}
if (basis_dir_cnt > 1) {
rprintf(FERROR,
"Using more than one %s option requires protocol"
" 29 or higher (negotiated %d).\n",
dest_option, protocol_version);
exit_cleanup(RERR_PROTOCOL);
}
if (prune_empty_dirs) {
rprintf(FERROR,
"--prune-empty-dirs requires protocol 29 or higher"
" (negotiated %d).\n",
protocol_version);
exit_cleanup(RERR_PROTOCOL);
}
} else if (protocol_version >= 30) {
if (am_server) {
compat_flags = allow_inc_recurse ? CF_INC_RECURSE : 0;
#ifdef CAN_SET_SYMLINK_TIMES
compat_flags |= CF_SYMLINK_TIMES;
#endif
#ifdef ICONV_OPTION
compat_flags |= CF_SYMLINK_ICONV;
#endif
if (local_server || strchr(client_info, 'f') != NULL)
compat_flags |= CF_SAFE_FLIST;
if (local_server || strchr(client_info, 'x') != NULL)
compat_flags |= CF_AVOID_XATTR_OPTIM;
if (local_server || strchr(client_info, 'C') != NULL)
compat_flags |= CF_CHKSUM_SEED_FIX;
write_byte(f_out, compat_flags);
} else
compat_flags = read_byte(f_in);
/* The inc_recurse var MUST be set to 0 or 1. */
inc_recurse = compat_flags & CF_INC_RECURSE ? 1 : 0;
want_xattr_optim = protocol_version >= 31 && !(compat_flags & CF_AVOID_XATTR_OPTIM);
proper_seed_order = compat_flags & CF_CHKSUM_SEED_FIX ? 1 : 0;
if (am_sender) {
receiver_symlink_times = am_server
? strchr(client_info, 'L') != NULL
: !!(compat_flags & CF_SYMLINK_TIMES);
}
#ifdef CAN_SET_SYMLINK_TIMES
else
receiver_symlink_times = 1;
#endif
#ifdef ICONV_OPTION
sender_symlink_iconv = iconv_opt && (am_server
? local_server || strchr(client_info, 's') != NULL
: !!(compat_flags & CF_SYMLINK_ICONV));
#endif
if (inc_recurse && !allow_inc_recurse) {
/* This should only be able to happen in a batch. */
fprintf(stderr,
"Incompatible options specified for inc-recursive %s.\n",
read_batch ? "batch file" : "connection");
exit_cleanup(RERR_SYNTAX);
}
use_safe_inc_flist = (compat_flags & CF_SAFE_FLIST) || protocol_version >= 31;
need_messages_from_generator = 1;
#ifdef CAN_SET_SYMLINK_TIMES
} else if (!am_sender) {
receiver_symlink_times = 1;
#endif
}
if (need_unsorted_flist && (!am_sender || inc_recurse))
unsort_ndx = ++file_extra_cnt;
if (partial_dir && *partial_dir != '/' && (!am_server || local_server)) {
int rflags = FILTRULE_NO_PREFIXES | FILTRULE_DIRECTORY;
if (!am_sender || protocol_version >= 30)
rflags |= FILTRULE_PERISHABLE;
parse_filter_str(&filter_list, partial_dir, rule_template(rflags), 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) ^ (getpid() << 6);
write_int(f_out, checksum_seed);
} else {
checksum_seed = read_int(f_in);
}
init_flist();
}
rsync-bpc-3.1.3.0/config.guess 0000664 0000000 0000000 00000130145 13737671777 0016126 0 ustar 00root root 0000000 0000000 #! /bin/sh
# Attempt to guess a canonical system name.
# Copyright 1992-2013 Free Software Foundation, Inc.
timestamp='2013-05-16'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# 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, see .
#
# 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. This Exception is an additional permission under section 7
# of the GNU General Public License, version 3 ("GPLv3").
#
# Originally written by Per Bothner.
#
# You can get the latest version of this script from:
# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
#
# Please send patches with a ChangeLog entry to config-patches@gnu.org.
me=`echo "$0" | sed -e 's,.*/,,'`
usage="\
Usage: $0 [OPTION]
Output the configuration name of the system \`$me' is run on.
Operation modes:
-h, --help print this help, then exit
-t, --time-stamp print date of last modification, then exit
-v, --version print version number, then exit
Report bugs and patches to ."
version="\
GNU config.guess ($timestamp)
Originally written by Per Bothner.
Copyright 1992-2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
help="
Try \`$me --help' for more information."
# Parse command line
while test $# -gt 0 ; do
case $1 in
--time-stamp | --time* | -t )
echo "$timestamp" ; exit ;;
--version | -v )
echo "$version" ; exit ;;
--help | --h* | -h )
echo "$usage"; exit ;;
-- ) # Stop option processing
shift; break ;;
- ) # Use stdin as input.
break ;;
-* )
echo "$me: invalid option $1$help" >&2
exit 1 ;;
* )
break ;;
esac
done
if test $# != 0; then
echo "$me: too many arguments$help" >&2
exit 1
fi
trap 'exit 1' 1 2 15
# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
# compiler to aid in system detection is discouraged as it requires
# temporary files to be created and, as you can see below, it is a
# headache to deal with in a portable fashion.
# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
# use `HOST_CC' if defined, but it is deprecated.
# Portable tmp directory creation inspired by the Autoconf team.
set_cc_for_build='
trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
: ${TMPDIR=/tmp} ;
{ tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
{ test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
{ tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
{ echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
dummy=$tmp/dummy ;
tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
case $CC_FOR_BUILD,$HOST_CC,$CC in
,,) echo "int x;" > $dummy.c ;
for c in cc gcc c89 c99 ; do
if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
CC_FOR_BUILD="$c"; break ;
fi ;
done ;
if test x"$CC_FOR_BUILD" = x ; then
CC_FOR_BUILD=no_compiler_found ;
fi
;;
,,*) CC_FOR_BUILD=$CC ;;
,*,*) CC_FOR_BUILD=$HOST_CC ;;
esac ; set_cc_for_build= ;'
# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
# (ghazi@noc.rutgers.edu 1994-08-24)
if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
PATH=$PATH:/.attbin ; export PATH
fi
UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
case "${UNAME_SYSTEM}" in
Linux|GNU|GNU/*)
# If the system lacks a compiler, then just pick glibc.
# We could probably try harder.
LIBC=gnu
eval $set_cc_for_build
cat <<-EOF > $dummy.c
#include
#if defined(__UCLIBC__)
LIBC=uclibc
#elif defined(__dietlibc__)
LIBC=dietlibc
#else
LIBC=gnu
#endif
EOF
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'`
;;
esac
# Note: order is significant - the case branches are not exclusive.
case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
*:NetBSD:*:*)
# NetBSD (nbsd) targets should (where applicable) match one or
# more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*,
# *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
# switched to ELF, *-*-netbsd* would select the old
# object file format. This provides both forward
# compatibility and a consistent mechanism for selecting the
# object file format.
#
# Note: NetBSD doesn't particularly care about the vendor
# portion of the name. We always set it to "unknown".
sysctl="sysctl -n hw.machine_arch"
UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
/usr/sbin/$sysctl 2>/dev/null || echo unknown)`
case "${UNAME_MACHINE_ARCH}" in
armeb) machine=armeb-unknown ;;
arm*) machine=arm-unknown ;;
sh3el) machine=shl-unknown ;;
sh3eb) machine=sh-unknown ;;
sh5el) machine=sh5le-unknown ;;
*) machine=${UNAME_MACHINE_ARCH}-unknown ;;
esac
# The Operating System including object format, if it has switched
# to ELF recently, or will in the future.
case "${UNAME_MACHINE_ARCH}" in
arm*|i386|m68k|ns32k|sh3*|sparc|vax)
eval $set_cc_for_build
if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
| grep -q __ELF__
then
# Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
# Return netbsd for either. FIX?
os=netbsd
else
os=netbsdelf
fi
;;
*)
os=netbsd
;;
esac
# The OS release
# Debian GNU/NetBSD machines have a different userland, and
# thus, need a distinct triplet. However, they do not need
# kernel version information, so it can be replaced with a
# suitable tag, in the style of linux-gnu.
case "${UNAME_VERSION}" in
Debian*)
release='-gnu'
;;
*)
release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
;;
esac
# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
# contains redundant information, the shorter form:
# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
echo "${machine}-${os}${release}"
exit ;;
*:Bitrig:*:*)
UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE}
exit ;;
*:OpenBSD:*:*)
UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
exit ;;
*:ekkoBSD:*:*)
echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
exit ;;
*:SolidBSD:*:*)
echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
exit ;;
macppc:MirBSD:*:*)
echo powerpc-unknown-mirbsd${UNAME_RELEASE}
exit ;;
*:MirBSD:*:*)
echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
exit ;;
alpha:OSF1:*:*)
case $UNAME_RELEASE in
*4.0)
UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
;;
*5.*)
UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
;;
esac
# According to Compaq, /usr/sbin/psrinfo has been available on
# OSF/1 and Tru64 systems produced since 1995. I hope that
# covers most systems running today. This code pipes the CPU
# types through head -n 1, so we only detect the type of CPU 0.
ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
case "$ALPHA_CPU_TYPE" in
"EV4 (21064)")
UNAME_MACHINE="alpha" ;;
"EV4.5 (21064)")
UNAME_MACHINE="alpha" ;;
"LCA4 (21066/21068)")
UNAME_MACHINE="alpha" ;;
"EV5 (21164)")
UNAME_MACHINE="alphaev5" ;;
"EV5.6 (21164A)")
UNAME_MACHINE="alphaev56" ;;
"EV5.6 (21164PC)")
UNAME_MACHINE="alphapca56" ;;
"EV5.7 (21164PC)")
UNAME_MACHINE="alphapca57" ;;
"EV6 (21264)")
UNAME_MACHINE="alphaev6" ;;
"EV6.7 (21264A)")
UNAME_MACHINE="alphaev67" ;;
"EV6.8CB (21264C)")
UNAME_MACHINE="alphaev68" ;;
"EV6.8AL (21264B)")
UNAME_MACHINE="alphaev68" ;;
"EV6.8CX (21264D)")
UNAME_MACHINE="alphaev68" ;;
"EV6.9A (21264/EV69A)")
UNAME_MACHINE="alphaev69" ;;
"EV7 (21364)")
UNAME_MACHINE="alphaev7" ;;
"EV7.9 (21364A)")
UNAME_MACHINE="alphaev79" ;;
esac
# A Pn.n version is a patched version.
# A Vn.n version is a released version.
# A Tn.n version is a released field test version.
# A Xn.n version is an unreleased experimental baselevel.
# 1.2 uses "1.2" for uname -r.
echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
# Reset EXIT trap before exiting to avoid spurious non-zero exit code.
exitcode=$?
trap '' 0
exit $exitcode ;;
Alpha\ *:Windows_NT*:*)
# How do we know it's Interix rather than the generic POSIX subsystem?
# Should we change UNAME_MACHINE based on the output of uname instead
# of the specific Alpha model?
echo alpha-pc-interix
exit ;;
21064:Windows_NT:50:3)
echo alpha-dec-winnt3.5
exit ;;
Amiga*:UNIX_System_V:4.0:*)
echo m68k-unknown-sysv4
exit ;;
*:[Aa]miga[Oo][Ss]:*:*)
echo ${UNAME_MACHINE}-unknown-amigaos
exit ;;
*:[Mm]orph[Oo][Ss]:*:*)
echo ${UNAME_MACHINE}-unknown-morphos
exit ;;
*:OS/390:*:*)
echo i370-ibm-openedition
exit ;;
*:z/VM:*:*)
echo s390-ibm-zvmoe
exit ;;
*:OS400:*:*)
echo powerpc-ibm-os400
exit ;;
arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
echo arm-acorn-riscix${UNAME_RELEASE}
exit ;;
arm*:riscos:*:*|arm*:RISCOS:*:*)
echo arm-unknown-riscos
exit ;;
SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
echo hppa1.1-hitachi-hiuxmpp
exit ;;
Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
# akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
if test "`(/bin/universe) 2>/dev/null`" = att ; then
echo pyramid-pyramid-sysv3
else
echo pyramid-pyramid-bsd
fi
exit ;;
NILE*:*:*:dcosx)
echo pyramid-pyramid-svr4
exit ;;
DRS?6000:unix:4.0:6*)
echo sparc-icl-nx6
exit ;;
DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
case `/usr/bin/uname -p` in
sparc) echo sparc-icl-nx7; exit ;;
esac ;;
s390x:SunOS:*:*)
echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit ;;
sun4H:SunOS:5.*:*)
echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit ;;
sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit ;;
i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
echo i386-pc-auroraux${UNAME_RELEASE}
exit ;;
i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
eval $set_cc_for_build
SUN_ARCH="i386"
# If there is a compiler, see if it is configured for 64-bit objects.
# Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
# This test works for both compilers.
if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
(CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
grep IS_64BIT_ARCH >/dev/null
then
SUN_ARCH="x86_64"
fi
fi
echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit ;;
sun4*:SunOS:6*:*)
# According to config.sub, this is the proper way to canonicalize
# SunOS6. Hard to guess exactly what SunOS6 will be like, but
# it's likely to be more like Solaris than SunOS4.
echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit ;;
sun4*:SunOS:*:*)
case "`/usr/bin/arch -k`" in
Series*|S4*)
UNAME_RELEASE=`uname -v`
;;
esac
# Japanese Language versions have a version number like `4.1.3-JL'.
echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
exit ;;
sun3*:SunOS:*:*)
echo m68k-sun-sunos${UNAME_RELEASE}
exit ;;
sun*:*:4.2BSD:*)
UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
case "`/bin/arch`" in
sun3)
echo m68k-sun-sunos${UNAME_RELEASE}
;;
sun4)
echo sparc-sun-sunos${UNAME_RELEASE}
;;
esac
exit ;;
aushp:SunOS:*:*)
echo sparc-auspex-sunos${UNAME_RELEASE}
exit ;;
# The situation for MiNT is a little confusing. The machine name
# can be virtually everything (everything which is not
# "atarist" or "atariste" at least should have a processor
# > m68000). The system name ranges from "MiNT" over "FreeMiNT"
# to the lowercase version "mint" (or "freemint"). Finally
# the system name "TOS" denotes a system which is actually not
# MiNT. But MiNT is downward compatible to TOS, so this should
# be no problem.
atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
echo m68k-atari-mint${UNAME_RELEASE}
exit ;;
atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
echo m68k-atari-mint${UNAME_RELEASE}
exit ;;
*falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
echo m68k-atari-mint${UNAME_RELEASE}
exit ;;
milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
echo m68k-milan-mint${UNAME_RELEASE}
exit ;;
hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
echo m68k-hades-mint${UNAME_RELEASE}
exit ;;
*:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
echo m68k-unknown-mint${UNAME_RELEASE}
exit ;;
m68k:machten:*:*)
echo m68k-apple-machten${UNAME_RELEASE}
exit ;;
powerpc:machten:*:*)
echo powerpc-apple-machten${UNAME_RELEASE}
exit ;;
RISC*:Mach:*:*)
echo mips-dec-mach_bsd4.3
exit ;;
RISC*:ULTRIX:*:*)
echo mips-dec-ultrix${UNAME_RELEASE}
exit ;;
VAX*:ULTRIX*:*:*)
echo vax-dec-ultrix${UNAME_RELEASE}
exit ;;
2020:CLIX:*:* | 2430:CLIX:*:*)
echo clipper-intergraph-clix${UNAME_RELEASE}
exit ;;
mips:*:*:UMIPS | mips:*:*:RISCos)
eval $set_cc_for_build
sed 's/^ //' << EOF >$dummy.c
#ifdef __cplusplus
#include /* for printf() prototype */
int main (int argc, char *argv[]) {
#else
int main (argc, argv) int argc; char *argv[]; {
#endif
#if defined (host_mips) && defined (MIPSEB)
#if defined (SYSTYPE_SYSV)
printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
#endif
#if defined (SYSTYPE_SVR4)
printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
#endif
#if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
#endif
#endif
exit (-1);
}
EOF
$CC_FOR_BUILD -o $dummy $dummy.c &&
dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
SYSTEM_NAME=`$dummy $dummyarg` &&
{ echo "$SYSTEM_NAME"; exit; }
echo mips-mips-riscos${UNAME_RELEASE}
exit ;;
Motorola:PowerMAX_OS:*:*)
echo powerpc-motorola-powermax
exit ;;
Motorola:*:4.3:PL8-*)
echo powerpc-harris-powermax
exit ;;
Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
echo powerpc-harris-powermax
exit ;;
Night_Hawk:Power_UNIX:*:*)
echo powerpc-harris-powerunix
exit ;;
m88k:CX/UX:7*:*)
echo m88k-harris-cxux7
exit ;;
m88k:*:4*:R4*)
echo m88k-motorola-sysv4
exit ;;
m88k:*:3*:R3*)
echo m88k-motorola-sysv3
exit ;;
AViiON:dgux:*:*)
# DG/UX returns AViiON for all architectures
UNAME_PROCESSOR=`/usr/bin/uname -p`
if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
then
if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
[ ${TARGET_BINARY_INTERFACE}x = x ]
then
echo m88k-dg-dgux${UNAME_RELEASE}
else
echo m88k-dg-dguxbcs${UNAME_RELEASE}
fi
else
echo i586-dg-dgux${UNAME_RELEASE}
fi
exit ;;
M88*:DolphinOS:*:*) # DolphinOS (SVR3)
echo m88k-dolphin-sysv3
exit ;;
M88*:*:R3*:*)
# Delta 88k system running SVR3
echo m88k-motorola-sysv3
exit ;;
XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
echo m88k-tektronix-sysv3
exit ;;
Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
echo m68k-tektronix-bsd
exit ;;
*:IRIX*:*:*)
echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
exit ;;
????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
exit ;; # Note that: echo "'`uname -s`'" gives 'AIX '
i*86:AIX:*:*)
echo i386-ibm-aix
exit ;;
ia64:AIX:*:*)
if [ -x /usr/bin/oslevel ] ; then
IBM_REV=`/usr/bin/oslevel`
else
IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
fi
echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
exit ;;
*:AIX:2:3)
if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
eval $set_cc_for_build
sed 's/^ //' << EOF >$dummy.c
#include
main()
{
if (!__power_pc())
exit(1);
puts("powerpc-ibm-aix3.2.5");
exit(0);
}
EOF
if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
then
echo "$SYSTEM_NAME"
else
echo rs6000-ibm-aix3.2.5
fi
elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
echo rs6000-ibm-aix3.2.4
else
echo rs6000-ibm-aix3.2
fi
exit ;;
*:AIX:*:[4567])
IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
IBM_ARCH=rs6000
else
IBM_ARCH=powerpc
fi
if [ -x /usr/bin/oslevel ] ; then
IBM_REV=`/usr/bin/oslevel`
else
IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
fi
echo ${IBM_ARCH}-ibm-aix${IBM_REV}
exit ;;
*:AIX:*:*)
echo rs6000-ibm-aix
exit ;;
ibmrt:4.4BSD:*|romp-ibm:BSD:*)
echo romp-ibm-bsd4.4
exit ;;
ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
exit ;; # report: romp-ibm BSD 4.3
*:BOSX:*:*)
echo rs6000-bull-bosx
exit ;;
DPX/2?00:B.O.S.:*:*)
echo m68k-bull-sysv3
exit ;;
9000/[34]??:4.3bsd:1.*:*)
echo m68k-hp-bsd
exit ;;
hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
echo m68k-hp-bsd4.4
exit ;;
9000/[34678]??:HP-UX:*:*)
HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
case "${UNAME_MACHINE}" in
9000/31? ) HP_ARCH=m68000 ;;
9000/[34]?? ) HP_ARCH=m68k ;;
9000/[678][0-9][0-9])
if [ -x /usr/bin/getconf ]; then
sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
case "${sc_cpu_version}" in
523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
532) # CPU_PA_RISC2_0
case "${sc_kernel_bits}" in
32) HP_ARCH="hppa2.0n" ;;
64) HP_ARCH="hppa2.0w" ;;
'') HP_ARCH="hppa2.0" ;; # HP-UX 10.20
esac ;;
esac
fi
if [ "${HP_ARCH}" = "" ]; then
eval $set_cc_for_build
sed 's/^ //' << EOF >$dummy.c
#define _HPUX_SOURCE
#include
#include
int main ()
{
#if defined(_SC_KERNEL_BITS)
long bits = sysconf(_SC_KERNEL_BITS);
#endif
long cpu = sysconf (_SC_CPU_VERSION);
switch (cpu)
{
case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
case CPU_PA_RISC2_0:
#if defined(_SC_KERNEL_BITS)
switch (bits)
{
case 64: puts ("hppa2.0w"); break;
case 32: puts ("hppa2.0n"); break;
default: puts ("hppa2.0"); break;
} break;
#else /* !defined(_SC_KERNEL_BITS) */
puts ("hppa2.0"); break;
#endif
default: puts ("hppa1.0"); break;
}
exit (0);
}
EOF
(CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
test -z "$HP_ARCH" && HP_ARCH=hppa
fi ;;
esac
if [ ${HP_ARCH} = "hppa2.0w" ]
then
eval $set_cc_for_build
# hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
# 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler
# generating 64-bit code. GNU and HP use different nomenclature:
#
# $ CC_FOR_BUILD=cc ./config.guess
# => hppa2.0w-hp-hpux11.23
# $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
# => hppa64-hp-hpux11.23
if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
grep -q __LP64__
then
HP_ARCH="hppa2.0w"
else
HP_ARCH="hppa64"
fi
fi
echo ${HP_ARCH}-hp-hpux${HPUX_REV}
exit ;;
ia64:HP-UX:*:*)
HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
echo ia64-hp-hpux${HPUX_REV}
exit ;;
3050*:HI-UX:*:*)
eval $set_cc_for_build
sed 's/^ //' << EOF >$dummy.c
#include
int
main ()
{
long cpu = sysconf (_SC_CPU_VERSION);
/* The order matters, because CPU_IS_HP_MC68K erroneously returns
true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
results, however. */
if (CPU_IS_PA_RISC (cpu))
{
switch (cpu)
{
case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
default: puts ("hppa-hitachi-hiuxwe2"); break;
}
}
else if (CPU_IS_HP_MC68K (cpu))
puts ("m68k-hitachi-hiuxwe2");
else puts ("unknown-hitachi-hiuxwe2");
exit (0);
}
EOF
$CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
{ echo "$SYSTEM_NAME"; exit; }
echo unknown-hitachi-hiuxwe2
exit ;;
9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
echo hppa1.1-hp-bsd
exit ;;
9000/8??:4.3bsd:*:*)
echo hppa1.0-hp-bsd
exit ;;
*9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
echo hppa1.0-hp-mpeix
exit ;;
hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
echo hppa1.1-hp-osf
exit ;;
hp8??:OSF1:*:*)
echo hppa1.0-hp-osf
exit ;;
i*86:OSF1:*:*)
if [ -x /usr/sbin/sysversion ] ; then
echo ${UNAME_MACHINE}-unknown-osf1mk
else
echo ${UNAME_MACHINE}-unknown-osf1
fi
exit ;;
parisc*:Lites*:*:*)
echo hppa1.1-hp-lites
exit ;;
C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
echo c1-convex-bsd
exit ;;
C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
if getsysinfo -f scalar_acc
then echo c32-convex-bsd
else echo c2-convex-bsd
fi
exit ;;
C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
echo c34-convex-bsd
exit ;;
C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
echo c38-convex-bsd
exit ;;
C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
echo c4-convex-bsd
exit ;;
CRAY*Y-MP:*:*:*)
echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
exit ;;
CRAY*[A-Z]90:*:*:*)
echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
| sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
-e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
-e 's/\.[^.]*$/.X/'
exit ;;
CRAY*TS:*:*:*)
echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
exit ;;
CRAY*T3E:*:*:*)
echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
exit ;;
CRAY*SV1:*:*:*)
echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
exit ;;
*:UNICOS/mp:*:*)
echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
exit ;;
F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
exit ;;
5000:UNIX_System_V:4.*:*)
FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
exit ;;
i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
exit ;;
sparc*:BSD/OS:*:*)
echo sparc-unknown-bsdi${UNAME_RELEASE}
exit ;;
*:BSD/OS:*:*)
echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
exit ;;
*:FreeBSD:*:*)
UNAME_PROCESSOR=`/usr/bin/uname -p`
case ${UNAME_PROCESSOR} in
amd64)
echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
*)
echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
esac
exit ;;
i*:CYGWIN*:*)
echo ${UNAME_MACHINE}-pc-cygwin
exit ;;
*:MINGW64*:*)
echo ${UNAME_MACHINE}-pc-mingw64
exit ;;
*:MINGW*:*)
echo ${UNAME_MACHINE}-pc-mingw32
exit ;;
i*:MSYS*:*)
echo ${UNAME_MACHINE}-pc-msys
exit ;;
i*:windows32*:*)
# uname -m includes "-pc" on this system.
echo ${UNAME_MACHINE}-mingw32
exit ;;
i*:PW*:*)
echo ${UNAME_MACHINE}-pc-pw32
exit ;;
*:Interix*:*)
case ${UNAME_MACHINE} in
x86)
echo i586-pc-interix${UNAME_RELEASE}
exit ;;
authenticamd | genuineintel | EM64T)
echo x86_64-unknown-interix${UNAME_RELEASE}
exit ;;
IA64)
echo ia64-unknown-interix${UNAME_RELEASE}
exit ;;
esac ;;
[345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
echo i${UNAME_MACHINE}-pc-mks
exit ;;
8664:Windows_NT:*)
echo x86_64-pc-mks
exit ;;
i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
# How do we know it's Interix rather than the generic POSIX subsystem?
# It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
# UNAME_MACHINE based on the output of uname instead of i386?
echo i586-pc-interix
exit ;;
i*:UWIN*:*)
echo ${UNAME_MACHINE}-pc-uwin
exit ;;
amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
echo x86_64-unknown-cygwin
exit ;;
p*:CYGWIN*:*)
echo powerpcle-unknown-cygwin
exit ;;
prep*:SunOS:5.*:*)
echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit ;;
*:GNU:*:*)
# the GNU system
echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
exit ;;
*:GNU/*:*:*)
# other systems with GNU libc and userland
echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC}
exit ;;
i*86:Minix:*:*)
echo ${UNAME_MACHINE}-pc-minix
exit ;;
aarch64:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
aarch64_be:Linux:*:*)
UNAME_MACHINE=aarch64_be
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
alpha:Linux:*:*)
case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
EV5) UNAME_MACHINE=alphaev5 ;;
EV56) UNAME_MACHINE=alphaev56 ;;
PCA56) UNAME_MACHINE=alphapca56 ;;
PCA57) UNAME_MACHINE=alphapca56 ;;
EV6) UNAME_MACHINE=alphaev6 ;;
EV67) UNAME_MACHINE=alphaev67 ;;
EV68*) UNAME_MACHINE=alphaev68 ;;
esac
objdump --private-headers /bin/sh | grep -q ld.so.1
if test "$?" = 0 ; then LIBC="gnulibc1" ; fi
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
arc:Linux:*:* | arceb:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
arm*:Linux:*:*)
eval $set_cc_for_build
if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
| grep -q __ARM_EABI__
then
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
else
if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
| grep -q __ARM_PCS_VFP
then
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi
else
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf
fi
fi
exit ;;
avr32*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
cris:Linux:*:*)
echo ${UNAME_MACHINE}-axis-linux-${LIBC}
exit ;;
crisv32:Linux:*:*)
echo ${UNAME_MACHINE}-axis-linux-${LIBC}
exit ;;
frv:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
hexagon:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
i*86:Linux:*:*)
echo ${UNAME_MACHINE}-pc-linux-${LIBC}
exit ;;
ia64:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
m32r*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
m68*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
mips:Linux:*:* | mips64:Linux:*:*)
eval $set_cc_for_build
sed 's/^ //' << EOF >$dummy.c
#undef CPU
#undef ${UNAME_MACHINE}
#undef ${UNAME_MACHINE}el
#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
CPU=${UNAME_MACHINE}el
#else
#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
CPU=${UNAME_MACHINE}
#else
CPU=
#endif
#endif
EOF
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; }
;;
or1k:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
or32:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
padre:Linux:*:*)
echo sparc-unknown-linux-${LIBC}
exit ;;
parisc64:Linux:*:* | hppa64:Linux:*:*)
echo hppa64-unknown-linux-${LIBC}
exit ;;
parisc:Linux:*:* | hppa:Linux:*:*)
# Look for CPU level
case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
PA7*) echo hppa1.1-unknown-linux-${LIBC} ;;
PA8*) echo hppa2.0-unknown-linux-${LIBC} ;;
*) echo hppa-unknown-linux-${LIBC} ;;
esac
exit ;;
ppc64:Linux:*:*)
echo powerpc64-unknown-linux-${LIBC}
exit ;;
ppc:Linux:*:*)
echo powerpc-unknown-linux-${LIBC}
exit ;;
s390:Linux:*:* | s390x:Linux:*:*)
echo ${UNAME_MACHINE}-ibm-linux-${LIBC}
exit ;;
sh64*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
sh*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
sparc:Linux:*:* | sparc64:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
tile*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
vax:Linux:*:*)
echo ${UNAME_MACHINE}-dec-linux-${LIBC}
exit ;;
x86_64:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
xtensa*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
i*86:DYNIX/ptx:4*:*)
# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
# earlier versions are messed up and put the nodename in both
# sysname and nodename.
echo i386-sequent-sysv4
exit ;;
i*86:UNIX_SV:4.2MP:2.*)
# Unixware is an offshoot of SVR4, but it has its own version
# number series starting with 2...
# I am not positive that other SVR4 systems won't match this,
# I just have to hope. -- rms.
# Use sysv4.2uw... so that sysv4* matches it.
echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
exit ;;
i*86:OS/2:*:*)
# If we were able to find `uname', then EMX Unix compatibility
# is probably installed.
echo ${UNAME_MACHINE}-pc-os2-emx
exit ;;
i*86:XTS-300:*:STOP)
echo ${UNAME_MACHINE}-unknown-stop
exit ;;
i*86:atheos:*:*)
echo ${UNAME_MACHINE}-unknown-atheos
exit ;;
i*86:syllable:*:*)
echo ${UNAME_MACHINE}-pc-syllable
exit ;;
i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
echo i386-unknown-lynxos${UNAME_RELEASE}
exit ;;
i*86:*DOS:*:*)
echo ${UNAME_MACHINE}-pc-msdosdjgpp
exit ;;
i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
else
echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
fi
exit ;;
i*86:*:5:[678]*)
# UnixWare 7.x, OpenUNIX and OpenServer 6.
case `/bin/uname -X | grep "^Machine"` in
*486*) UNAME_MACHINE=i486 ;;
*Pentium) UNAME_MACHINE=i586 ;;
*Pent*|*Celeron) UNAME_MACHINE=i686 ;;
esac
echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
exit ;;
i*86:*:3.2:*)
if test -f /usr/options/cb.name; then
UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then
UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
(/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
(/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
&& UNAME_MACHINE=i586
(/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
&& UNAME_MACHINE=i686
(/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
&& UNAME_MACHINE=i686
echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
else
echo ${UNAME_MACHINE}-pc-sysv32
fi
exit ;;
pc:*:*:*)
# Left here for compatibility:
# uname -m prints for DJGPP always 'pc', but it prints nothing about
# the processor, so we play safe by assuming i586.
# Note: whatever this is, it MUST be the same as what config.sub
# prints for the "djgpp" host, or else GDB configury will decide that
# this is a cross-build.
echo i586-pc-msdosdjgpp
exit ;;
Intel:Mach:3*:*)
echo i386-pc-mach3
exit ;;
paragon:*:*:*)
echo i860-intel-osf1
exit ;;
i860:*:4.*:*) # i860-SVR4
if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
else # Add other i860-SVR4 vendors below as they are discovered.
echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
fi
exit ;;
mini*:CTIX:SYS*5:*)
# "miniframe"
echo m68010-convergent-sysv
exit ;;
mc68k:UNIX:SYSTEM5:3.51m)
echo m68k-convergent-sysv
exit ;;
M680?0:D-NIX:5.3:*)
echo m68k-diab-dnix
exit ;;
M68*:*:R3V[5678]*:*)
test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
OS_REL=''
test -r /etc/.relid \
&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
&& { echo i486-ncr-sysv4.3${OS_REL}; exit; }
/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
&& { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
&& { echo i486-ncr-sysv4; exit; } ;;
NCR*:*:4.2:* | MPRAS*:*:4.2:*)
OS_REL='.3'
test -r /etc/.relid \
&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
&& { echo i486-ncr-sysv4.3${OS_REL}; exit; }
/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
&& { echo i586-ncr-sysv4.3${OS_REL}; exit; }
/bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
&& { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
echo m68k-unknown-lynxos${UNAME_RELEASE}
exit ;;
mc68030:UNIX_System_V:4.*:*)
echo m68k-atari-sysv4
exit ;;
TSUNAMI:LynxOS:2.*:*)
echo sparc-unknown-lynxos${UNAME_RELEASE}
exit ;;
rs6000:LynxOS:2.*:*)
echo rs6000-unknown-lynxos${UNAME_RELEASE}
exit ;;
PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
echo powerpc-unknown-lynxos${UNAME_RELEASE}
exit ;;
SM[BE]S:UNIX_SV:*:*)
echo mips-dde-sysv${UNAME_RELEASE}
exit ;;
RM*:ReliantUNIX-*:*:*)
echo mips-sni-sysv4
exit ;;
RM*:SINIX-*:*:*)
echo mips-sni-sysv4
exit ;;
*:SINIX-*:*:*)
if uname -p 2>/dev/null >/dev/null ; then
UNAME_MACHINE=`(uname -p) 2>/dev/null`
echo ${UNAME_MACHINE}-sni-sysv4
else
echo ns32k-sni-sysv
fi
exit ;;
PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
# says
echo i586-unisys-sysv4
exit ;;
*:UNIX_System_V:4*:FTX*)
# From Gerald Hewes .
# How about differentiating between stratus architectures? -djm
echo hppa1.1-stratus-sysv4
exit ;;
*:*:*:FTX*)
# From seanf@swdc.stratus.com.
echo i860-stratus-sysv4
exit ;;
i*86:VOS:*:*)
# From Paul.Green@stratus.com.
echo ${UNAME_MACHINE}-stratus-vos
exit ;;
*:VOS:*:*)
# From Paul.Green@stratus.com.
echo hppa1.1-stratus-vos
exit ;;
mc68*:A/UX:*:*)
echo m68k-apple-aux${UNAME_RELEASE}
exit ;;
news*:NEWS-OS:6*:*)
echo mips-sony-newsos6
exit ;;
R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
if [ -d /usr/nec ]; then
echo mips-nec-sysv${UNAME_RELEASE}
else
echo mips-unknown-sysv${UNAME_RELEASE}
fi
exit ;;
BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
echo powerpc-be-beos
exit ;;
BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
echo powerpc-apple-beos
exit ;;
BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
echo i586-pc-beos
exit ;;
BePC:Haiku:*:*) # Haiku running on Intel PC compatible.
echo i586-pc-haiku
exit ;;
x86_64:Haiku:*:*)
echo x86_64-unknown-haiku
exit ;;
SX-4:SUPER-UX:*:*)
echo sx4-nec-superux${UNAME_RELEASE}
exit ;;
SX-5:SUPER-UX:*:*)
echo sx5-nec-superux${UNAME_RELEASE}
exit ;;
SX-6:SUPER-UX:*:*)
echo sx6-nec-superux${UNAME_RELEASE}
exit ;;
SX-7:SUPER-UX:*:*)
echo sx7-nec-superux${UNAME_RELEASE}
exit ;;
SX-8:SUPER-UX:*:*)
echo sx8-nec-superux${UNAME_RELEASE}
exit ;;
SX-8R:SUPER-UX:*:*)
echo sx8r-nec-superux${UNAME_RELEASE}
exit ;;
Power*:Rhapsody:*:*)
echo powerpc-apple-rhapsody${UNAME_RELEASE}
exit ;;
*:Rhapsody:*:*)
echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
exit ;;
*:Darwin:*:*)
UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
eval $set_cc_for_build
if test "$UNAME_PROCESSOR" = unknown ; then
UNAME_PROCESSOR=powerpc
fi
if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
(CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
grep IS_64BIT_ARCH >/dev/null
then
case $UNAME_PROCESSOR in
i386) UNAME_PROCESSOR=x86_64 ;;
powerpc) UNAME_PROCESSOR=powerpc64 ;;
esac
fi
fi
echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
exit ;;
*:procnto*:*:* | *:QNX:[0123456789]*:*)
UNAME_PROCESSOR=`uname -p`
if test "$UNAME_PROCESSOR" = "x86"; then
UNAME_PROCESSOR=i386
UNAME_MACHINE=pc
fi
echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
exit ;;
*:QNX:*:4*)
echo i386-pc-qnx
exit ;;
NEO-?:NONSTOP_KERNEL:*:*)
echo neo-tandem-nsk${UNAME_RELEASE}
exit ;;
NSE-*:NONSTOP_KERNEL:*:*)
echo nse-tandem-nsk${UNAME_RELEASE}
exit ;;
NSR-?:NONSTOP_KERNEL:*:*)
echo nsr-tandem-nsk${UNAME_RELEASE}
exit ;;
*:NonStop-UX:*:*)
echo mips-compaq-nonstopux
exit ;;
BS2000:POSIX*:*:*)
echo bs2000-siemens-sysv
exit ;;
DS/*:UNIX_System_V:*:*)
echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
exit ;;
*:Plan9:*:*)
# "uname -m" is not consistent, so use $cputype instead. 386
# is converted to i386 for consistency with other x86
# operating systems.
if test "$cputype" = "386"; then
UNAME_MACHINE=i386
else
UNAME_MACHINE="$cputype"
fi
echo ${UNAME_MACHINE}-unknown-plan9
exit ;;
*:TOPS-10:*:*)
echo pdp10-unknown-tops10
exit ;;
*:TENEX:*:*)
echo pdp10-unknown-tenex
exit ;;
KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
echo pdp10-dec-tops20
exit ;;
XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
echo pdp10-xkl-tops20
exit ;;
*:TOPS-20:*:*)
echo pdp10-unknown-tops20
exit ;;
*:ITS:*:*)
echo pdp10-unknown-its
exit ;;
SEI:*:*:SEIUX)
echo mips-sei-seiux${UNAME_RELEASE}
exit ;;
*:DragonFly:*:*)
echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
exit ;;
*:*VMS:*:*)
UNAME_MACHINE=`(uname -p) 2>/dev/null`
case "${UNAME_MACHINE}" in
A*) echo alpha-dec-vms ; exit ;;
I*) echo ia64-dec-vms ; exit ;;
V*) echo vax-dec-vms ; exit ;;
esac ;;
*:XENIX:*:SysV)
echo i386-pc-xenix
exit ;;
i*86:skyos:*:*)
echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
exit ;;
i*86:rdos:*:*)
echo ${UNAME_MACHINE}-pc-rdos
exit ;;
i*86:AROS:*:*)
echo ${UNAME_MACHINE}-pc-aros
exit ;;
x86_64:VMkernel:*:*)
echo ${UNAME_MACHINE}-unknown-esx
exit ;;
esac
eval $set_cc_for_build
cat >$dummy.c <
# include
#endif
main ()
{
#if defined (sony)
#if defined (MIPSEB)
/* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
I don't know.... */
printf ("mips-sony-bsd\n"); exit (0);
#else
#include
printf ("m68k-sony-newsos%s\n",
#ifdef NEWSOS4
"4"
#else
""
#endif
); exit (0);
#endif
#endif
#if defined (__arm) && defined (__acorn) && defined (__unix)
printf ("arm-acorn-riscix\n"); exit (0);
#endif
#if defined (hp300) && !defined (hpux)
printf ("m68k-hp-bsd\n"); exit (0);
#endif
#if defined (NeXT)
#if !defined (__ARCHITECTURE__)
#define __ARCHITECTURE__ "m68k"
#endif
int version;
version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
if (version < 4)
printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
else
printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
exit (0);
#endif
#if defined (MULTIMAX) || defined (n16)
#if defined (UMAXV)
printf ("ns32k-encore-sysv\n"); exit (0);
#else
#if defined (CMU)
printf ("ns32k-encore-mach\n"); exit (0);
#else
printf ("ns32k-encore-bsd\n"); exit (0);
#endif
#endif
#endif
#if defined (__386BSD__)
printf ("i386-pc-bsd\n"); exit (0);
#endif
#if defined (sequent)
#if defined (i386)
printf ("i386-sequent-dynix\n"); exit (0);
#endif
#if defined (ns32000)
printf ("ns32k-sequent-dynix\n"); exit (0);
#endif
#endif
#if defined (_SEQUENT_)
struct utsname un;
uname(&un);
if (strncmp(un.version, "V2", 2) == 0) {
printf ("i386-sequent-ptx2\n"); exit (0);
}
if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
printf ("i386-sequent-ptx1\n"); exit (0);
}
printf ("i386-sequent-ptx\n"); exit (0);
#endif
#if defined (vax)
# if !defined (ultrix)
# include
# if defined (BSD)
# if BSD == 43
printf ("vax-dec-bsd4.3\n"); exit (0);
# else
# if BSD == 199006
printf ("vax-dec-bsd4.3reno\n"); exit (0);
# else
printf ("vax-dec-bsd\n"); exit (0);
# endif
# endif
# else
printf ("vax-dec-bsd\n"); exit (0);
# endif
# else
printf ("vax-dec-ultrix\n"); exit (0);
# endif
#endif
#if defined (alliant) && defined (i860)
printf ("i860-alliant-bsd\n"); exit (0);
#endif
exit (1);
}
EOF
$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
{ echo "$SYSTEM_NAME"; exit; }
# Apollos put the system type in the environment.
test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
# Convex versions that predate uname can use getsysinfo(1)
if [ -x /usr/convex/getsysinfo ]
then
case `getsysinfo -f cpu_type` in
c1*)
echo c1-convex-bsd
exit ;;
c2*)
if getsysinfo -f scalar_acc
then echo c32-convex-bsd
else echo c2-convex-bsd
fi
exit ;;
c34*)
echo c34-convex-bsd
exit ;;
c38*)
echo c38-convex-bsd
exit ;;
c4*)
echo c4-convex-bsd
exit ;;
esac
fi
cat >&2 < in order to provide the needed
information to handle your system.
config.guess timestamp = $timestamp
uname -m = `(uname -m) 2>/dev/null || echo unknown`
uname -r = `(uname -r) 2>/dev/null || echo unknown`
uname -s = `(uname -s) 2>/dev/null || echo unknown`
uname -v = `(uname -v) 2>/dev/null || echo unknown`
/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
/bin/uname -X = `(/bin/uname -X) 2>/dev/null`
hostinfo = `(hostinfo) 2>/dev/null`
/bin/universe = `(/bin/universe) 2>/dev/null`
/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null`
/bin/arch = `(/bin/arch) 2>/dev/null`
/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null`
/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
UNAME_MACHINE = ${UNAME_MACHINE}
UNAME_RELEASE = ${UNAME_RELEASE}
UNAME_SYSTEM = ${UNAME_SYSTEM}
UNAME_VERSION = ${UNAME_VERSION}
EOF
exit 1
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "timestamp='"
# time-stamp-format: "%:y-%02m-%02d"
# time-stamp-end: "'"
# End:
rsync-bpc-3.1.3.0/config.h.in 0000664 0000000 0000000 00000050620 13737671777 0015633 0 ustar 00root root 0000000 0000000 /* config.h.in. Generated from configure.ac by autoheader. */
/* Define if building universal (internal helper macro) */
#undef AC_APPLE_UNIVERSAL_BUILD
/* Define to 1 if link() can hard-link special files. */
#undef CAN_HARDLINK_SPECIAL
/* Define to 1 if link() can hard-link symlinks. */
#undef CAN_HARDLINK_SYMLINK
/* Define to 1 if chown modifies symlinks. */
#undef CHOWN_MODIFIES_SYMLINK
/* Undefine if you do not want locale features. By default this is defined. */
#undef CONFIG_LOCALE
/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
systems. This function is required for `alloca.c' support on those systems.
*/
#undef CRAY_STACKSEG_END
/* Define to 1 if using `alloca.c'. */
#undef C_ALLOCA
/* Define to 1 if using external zlib */
#undef EXTERNAL_ZLIB
/* Used to make "checker" understand that FD_ZERO() clears memory. */
#undef FORCE_FD_ZERO_MEMSET
/* Define to the type of elements in the array set by `getgroups'. Usually
this is either `int' or `gid_t'. */
#undef GETGROUPS_T
/* Define to 1 if the `getpgrp' function requires zero arguments. */
#undef GETPGRP_VOID
/* Define to 1 if you have the `aclsort' function. */
#undef HAVE_ACLSORT
/* true if you have acl_get_perm_np */
#undef HAVE_ACL_GET_PERM_NP
/* Define to 1 if you have the header file. */
#undef HAVE_ACL_LIBACL_H
/* true if you have AIX ACLs */
#undef HAVE_AIX_ACLS
/* Define to 1 if you have `alloca', as a function or macro. */
#undef HAVE_ALLOCA
/* Define to 1 if you have and it should be used (not on Ultrix).
*/
#undef HAVE_ALLOCA_H
/* Define to 1 if you have the header file. */
#undef HAVE_ARPA_INET_H
/* Define to 1 if you have the header file. */
#undef HAVE_ARPA_NAMESER_H
/* Define to 1 if you have the `asprintf' function. */
#undef HAVE_ASPRINTF
/* Define to 1 if you have the `attropen' function. */
#undef HAVE_ATTROPEN
/* Define to 1 if you have the header file. */
#undef HAVE_ATTR_XATTR_H
/* Define to 1 if readdir() is broken */
#undef HAVE_BROKEN_READDIR
/* Define to 1 if vsprintf has a C99-compatible return value */
#undef HAVE_C99_VSNPRINTF
/* Define to 1 if you have the `chmod' function. */
#undef HAVE_CHMOD
/* Define to 1 if you have the `chown' function. */
#undef HAVE_CHOWN
/* Define to 1 if you have the header file. */
#undef HAVE_COMPAT_H
/* Define to 1 if you have the "connect" function */
#undef HAVE_CONNECT
/* Define to 1 if you have the header file. */
#undef HAVE_CTYPE_H
/* Define to 1 if you have the header file, and it defines `DIR'.
*/
#undef HAVE_DIRENT_H
/* Define if posix_fallocate is efficient (Cygwin) */
#undef HAVE_EFFICIENT_POSIX_FALLOCATE
/* Define to 1 if errno is declared in errno.h */
#undef HAVE_ERRNO_DECL
/* Define to 1 if you have the `extattr_get_link' function. */
#undef HAVE_EXTATTR_GET_LINK
/* Define to 1 if you have the fallocate function and it compiles and links
without error */
#undef HAVE_FALLOCATE
/* Define if FALLOC_FL_PUNCH_HOLE is available. */
#undef HAVE_FALLOC_FL_PUNCH_HOLE
/* Define if FALLOC_FL_ZERO_RANGE is available. */
#undef HAVE_FALLOC_FL_ZERO_RANGE
/* Define to 1 if you have the `fchmod' function. */
#undef HAVE_FCHMOD
/* Define to 1 if you have the header file. */
#undef HAVE_FCNTL_H
/* Define to 1 if you have the header file. */
#undef HAVE_FLOAT_H
/* True if you have FreeBSD xattrs */
#undef HAVE_FREEBSD_XATTRS
/* Define to 1 if you have the `fstat' function. */
#undef HAVE_FSTAT
/* Define to 1 if you have the `ftruncate' function. */
#undef HAVE_FTRUNCATE
/* Define to 1 if you have the "getaddrinfo" function and required types. */
#undef HAVE_GETADDRINFO
/* Define to 1 if you have the `getcwd' function. */
#undef HAVE_GETCWD
/* Define to 1 if you have the `getegid' function. */
#undef HAVE_GETEGID
/* Define to 1 if you have the `geteuid' function. */
#undef HAVE_GETEUID
/* Define to 1 if you have the `getgrouplist' function. */
#undef HAVE_GETGROUPLIST
/* Define to 1 if you have the `getgroups' function. */
#undef HAVE_GETGROUPS
/* Define to 1 if you have the `getpass' function. */
#undef HAVE_GETPASS
/* Define to 1 if you have the `getpgrp' function. */
#undef HAVE_GETPGRP
/* Define to 1 if gettimeofday() takes a time-zone arg */
#undef HAVE_GETTIMEOFDAY_TZ
/* Define to 1 if you have the `getxattr' function. */
#undef HAVE_GETXATTR
/* Define to 1 if you have the header file. */
#undef HAVE_GRP_H
/* true if you have HPUX ACLs */
#undef HAVE_HPUX_ACLS
/* Define to 1 if you have the header file. */
#undef HAVE_ICONV_H
/* Define to 1 if you have the `iconv_open' function. */
#undef HAVE_ICONV_OPEN
/* Define to 1 if the system has the type `id_t'. */
#undef HAVE_ID_T
/* Define to 1 if you have the `inet_ntop' function. */
#undef HAVE_INET_NTOP
/* Define to 1 if you have the `inet_pton' function. */
#undef HAVE_INET_PTON
/* Define to 1 if you have the `initgroups' function. */
#undef HAVE_INITGROUPS
/* Define to 1 if you have the header file. */
#undef HAVE_INTTYPES_H
/* true if you have IRIX ACLs */
#undef HAVE_IRIX_ACLS
/* Define to 1 if you have the header file. */
#undef HAVE_LANGINFO_H
/* Define to 1 if you have the `lchmod' function. */
#undef HAVE_LCHMOD
/* Define to 1 if you have the `lchown' function. */
#undef HAVE_LCHOWN
/* Define to 1 if you have the `acl' library (-lacl). */
#undef HAVE_LIBACL
/* Define to 1 if you have the `attr' library (-lattr). */
#undef HAVE_LIBATTR
/* Define to 1 if you have the header file. */
#undef HAVE_LIBCHARSET_H
/* Define to 1 if you have the `inet' library (-linet). */
#undef HAVE_LIBINET
/* Define to 1 if you have the `nsl' library (-lnsl). */
#undef HAVE_LIBNSL
/* Define to 1 if you have the `nsl_s' library (-lnsl_s). */
#undef HAVE_LIBNSL_S
/* Define to 1 if you have the `popt' library (-lpopt). */
#undef HAVE_LIBPOPT
/* Define to 1 if you have the `resolv' library (-lresolv). */
#undef HAVE_LIBRESOLV
/* Define to 1 if you have the `sec' library (-lsec). */
#undef HAVE_LIBSEC
/* Define to 1 if you have the `socket' library (-lsocket). */
#undef HAVE_LIBSOCKET
/* Define to 1 if you have the `z' library (-lz). */
#undef HAVE_LIBZ
/* Define to 1 if you have the header file. */
#undef HAVE_LIMITS_H
/* Define to 1 if you have the `link' function. */
#undef HAVE_LINK
/* Define to 1 if you have the header file. */
#undef HAVE_LINUX_FALLOC_H
/* True if you have Linux xattrs (or equivalent) */
#undef HAVE_LINUX_XATTRS
/* Define to 1 if you have the `locale_charset' function. */
#undef HAVE_LOCALE_CHARSET
/* Define to 1 if you have the header file. */
#undef HAVE_LOCALE_H
/* Define to 1 if the type `long double' works and has more range or precision
than `double'. */
#undef HAVE_LONG_DOUBLE
/* Define to 1 if the type `long double' works and has more range or precision
than `double'. */
#undef HAVE_LONG_DOUBLE_WIDER
/* Define to 1 if you have the `lseek64' function. */
#undef HAVE_LSEEK64
/* Define to 1 if you have the `lutimes' function. */
#undef HAVE_LUTIMES
/* Define to 1 if you have the `mallinfo' function. */
#undef HAVE_MALLINFO
/* Define to 1 if you have the header file. */
#undef HAVE_MALLOC_H
/* Define to 1 if you have the header file. */
#undef HAVE_MCHECK_H
/* Define to 1 if you have the `memmove' function. */
#undef HAVE_MEMMOVE
/* Define to 1 if you have the header file. */
#undef HAVE_MEMORY_H
/* Define to 1 if you have the `mkfifo' function. */
#undef HAVE_MKFIFO
/* Define to 1 if you have the `mknod' function. */
#undef HAVE_MKNOD
/* Define to 1 if you have the `mkstemp64' function. */
#undef HAVE_MKSTEMP64
/* Define to 1 if the system has the type `mode_t'. */
#undef HAVE_MODE_T
/* Define to 1 if you have the `mtrace' function. */
#undef HAVE_MTRACE
/* Define to 1 if you have the header file, and it defines `DIR'. */
#undef HAVE_NDIR_H
/* Define to 1 if you have the header file. */
#undef HAVE_NETDB_H
/* Define to 1 if you have the header file. */
#undef HAVE_NETINET_IN_SYSTM_H
/* Define to 1 if you have the header file. */
#undef HAVE_NETINET_IP_H
/* Define to 1 if you have the `nl_langinfo' function. */
#undef HAVE_NL_LANGINFO
/* Define to 1 if the system has the type `off_t'. */
#undef HAVE_OFF_T
/* Define to 1 if you have the `open64' function. */
#undef HAVE_OPEN64
/* true if you have Mac OS X ACLs */
#undef HAVE_OSX_ACLS
/* True if you have Mac OS X xattrs */
#undef HAVE_OSX_XATTRS
/* Define to 1 if the system has the type `pid_t'. */
#undef HAVE_PID_T
/* Define to 1 if you have the header file. */
#undef HAVE_POPT_H
/* Define to 1 if you have the header file. */
#undef HAVE_POPT_POPT_H
/* true if you have posix ACLs */
#undef HAVE_POSIX_ACLS
/* Define to 1 if you have the `posix_fallocate' function. */
#undef HAVE_POSIX_FALLOCATE
/* Define to 1 if you have the `putenv' function. */
#undef HAVE_PUTENV
/* Define to 1 if you have the `readlink' function. */
#undef HAVE_READLINK
/* Define to 1 if remote shell is remsh, not rsh */
#undef HAVE_REMSH
/* Define to 1 if mkstemp() is available and works right */
#undef HAVE_SECURE_MKSTEMP
/* Define to 1 if you have the `setattrlist' function. */
#undef HAVE_SETATTRLIST
/* Define to 1 if you have the `seteuid' function. */
#undef HAVE_SETEUID
/* Define to 1 if you have the `setgroups' function. */
#undef HAVE_SETGROUPS
/* Define to 1 if you have the `setlocale' function. */
#undef HAVE_SETLOCALE
/* Define to 1 if you have the `setmode' function. */
#undef HAVE_SETMODE
/* Define to 1 if you have the `setsid' function. */
#undef HAVE_SETSID
/* Define to 1 if you have the `setvbuf' function. */
#undef HAVE_SETVBUF
/* Define to 1 if you have the `sigaction' function. */
#undef HAVE_SIGACTION
/* Define to 1 if you have the `sigprocmask' function. */
#undef HAVE_SIGPROCMASK
/* Define to 1 if the system has the type `size_t'. */
#undef HAVE_SIZE_T
/* Define to 1 if you have the `snprintf' function. */
#undef HAVE_SNPRINTF
/* Do we have sockaddr_in6.sin6_scope_id? */
#undef HAVE_SOCKADDR_IN6_SCOPE_ID
/* Do we have sockaddr_in.sin_len? */
#undef HAVE_SOCKADDR_IN_LEN
/* Do we have sockaddr.sa_len? */
#undef HAVE_SOCKADDR_LEN
/* Do we have sockaddr_un.sun_len? */
#undef HAVE_SOCKADDR_UN_LEN
/* Define to 1 if you have the "socketpair" function */
#undef HAVE_SOCKETPAIR
/* true if you have solaris ACLs */
#undef HAVE_SOLARIS_ACLS
/* True if you have Solaris xattrs */
#undef HAVE_SOLARIS_XATTRS
/* Define to 1 if you have the header file. */
#undef HAVE_STDINT_H
/* Define to 1 if you have the header file. */
#undef HAVE_STDLIB_H
/* Define to 1 if you have the `strcasecmp' function. */
#undef HAVE_STRCASECMP
/* Define to 1 if you have the `strchr' function. */
#undef HAVE_STRCHR
/* Define to 1 if you have the `strdup' function. */
#undef HAVE_STRDUP
/* Define to 1 if you have the `strerror' function. */
#undef HAVE_STRERROR
/* Define to 1 if you have the `strftime' function. */
#undef HAVE_STRFTIME
/* Define to 1 if you have the header file. */
#undef HAVE_STRINGS_H
/* Define to 1 if you have the header file. */
#undef HAVE_STRING_H
/* Define to 1 if you have the `strlcat' function. */
#undef HAVE_STRLCAT
/* Define to 1 if you have the `strlcpy' function. */
#undef HAVE_STRLCPY
/* Define to 1 if you have the `strpbrk' function. */
#undef HAVE_STRPBRK
/* Define to 1 if you have the `strtol' function. */
#undef HAVE_STRTOL
/* Define to 1 if the system has the type `struct addrinfo'. */
#undef HAVE_STRUCT_ADDRINFO
/* Define to 1 if the system has the type `struct sockaddr_storage'. */
#undef HAVE_STRUCT_SOCKADDR_STORAGE
/* Define to 1 if the system has the type `struct stat64'. */
#undef HAVE_STRUCT_STAT64
/* Define to 1 if `st_mtimensec' is a member of `struct stat'. */
#undef HAVE_STRUCT_STAT_ST_MTIMENSEC
/* Define to 1 if `st_mtimespec.tv_nsec' is a member of `struct stat'. */
#undef HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC
/* Define to 1 if `st_mtim.tv_nsec' is a member of `struct stat'. */
#undef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
/* Define to 1 if `st_rdev' is a member of `struct stat'. */
#undef HAVE_STRUCT_STAT_ST_RDEV
/* Define to 1 if you have the "struct utimbuf" type */
#undef HAVE_STRUCT_UTIMBUF
/* Define to 1 if you have the header file. */
#undef HAVE_SYS_ACL_H
/* Define to 1 if you have the header file. */
#undef HAVE_SYS_ATTR_H
/* Define to 1 if you have the header file, and it defines `DIR'.
*/
#undef HAVE_SYS_DIR_H
/* Define to 1 if you have the header file. */
#undef HAVE_SYS_EXTATTR_H
/* Define to 1 if you have the SYS_fallocate syscall number */
#undef HAVE_SYS_FALLOCATE
/* Define to 1 if you have the header file. */
#undef HAVE_SYS_FCNTL_H
/* Define to 1 if you have the header file. */
#undef HAVE_SYS_FILIO_H
/* Define to 1 if you have the header file. */
#undef HAVE_SYS_IOCTL_H
/* Define to 1 if you have the header file. */
#undef HAVE_SYS_MODE_H
/* Define to 1 if you have the header file, and it defines `DIR'.
*/
#undef HAVE_SYS_NDIR_H
/* Define to 1 if you have the header file. */
#undef HAVE_SYS_PARAM_H
/* Define to 1 if you have the header file. */
#undef HAVE_SYS_SELECT_H
/* Define to 1 if you have the header file. */
#undef HAVE_SYS_SOCKET_H
/* Define to 1 if you have the header file. */
#undef HAVE_SYS_STAT_H
/* Define to 1 if you have the header file. */
#undef HAVE_SYS_TIME_H
/* Define to 1 if you have the header file. */
#undef HAVE_SYS_TYPES_H
/* Define to 1 if you have the header file. */
#undef HAVE_SYS_UNISTD_H
/* Define to 1 if you have the header file. */
#undef HAVE_SYS_UN_H
/* Define to 1 if you have the header file. */
#undef HAVE_SYS_WAIT_H
/* Define to 1 if you have the header file. */
#undef HAVE_SYS_XATTR_H
/* Define to 1 if you have the `tcgetpgrp' function. */
#undef HAVE_TCGETPGRP
/* true if you have Tru64 ACLs */
#undef HAVE_TRU64_ACLS
/* Define to 1 if you have the header file. */
#undef HAVE_UNISTD_H
/* true if you have UnixWare ACLs */
#undef HAVE_UNIXWARE_ACLS
/* Define to 1 if you have the `usleep' function. */
#undef HAVE_USLEEP
/* Define to 1 if you have the `utime' function. */
#undef HAVE_UTIME
/* Define to 1 if you have the `utimensat' function. */
#undef HAVE_UTIMENSAT
/* Define to 1 if you have the `utimes' function. */
#undef HAVE_UTIMES
/* Define to 1 if you have the header file. */
#undef HAVE_UTIME_H
/* Define to 1 if `utime(file, NULL)' sets file's timestamp to the present. */
#undef HAVE_UTIME_NULL
/* Define to 1 if you have the `vasprintf' function. */
#undef HAVE_VASPRINTF
/* Define to 1 if you have the `va_copy' function. */
#undef HAVE_VA_COPY
/* Define to 1 if you have the `vsnprintf' function. */
#undef HAVE_VSNPRINTF
/* Define to 1 if you have the `wait4' function. */
#undef HAVE_WAIT4
/* Define to 1 if you have the `waitpid' function. */
#undef HAVE_WAITPID
/* Define to 1 if you have the header file. */
#undef HAVE_ZLIB_H
/* Define to 1 if you have the `_acl' function. */
#undef HAVE__ACL
/* Define to 1 if you have the `_facl' function. */
#undef HAVE__FACL
/* Define to 1 if you have the `__acl' function. */
#undef HAVE___ACL
/* Define to 1 if you have the `__facl' function. */
#undef HAVE___FACL
/* Define to 1 if you have the `__va_copy' function. */
#undef HAVE___VA_COPY
/* Define as const if the declaration of iconv() needs const. */
#undef ICONV_CONST
/* Define if you want the --iconv option. Specifing a value will set the
default iconv setting (a NULL means no --iconv processing by default). */
#undef ICONV_OPTION
/* true if you have IPv6 */
#undef INET6
/* Define to 1 if `major', `minor', and `makedev' are declared in .
*/
#undef MAJOR_IN_MKDEV
/* Define to 1 if `major', `minor', and `makedev' are declared in
. */
#undef MAJOR_IN_SYSMACROS
/* Define to 1 if makedev() takes 3 args */
#undef MAKEDEV_TAKES_3_ARGS
/* Define to 1 if mknod() can create FIFOs. */
#undef MKNOD_CREATES_FIFOS
/* Define to 1 if mknod() can create sockets. */
#undef MKNOD_CREATES_SOCKETS
/* unprivileged group for unprivileged user */
#undef NOBODY_GROUP
/* unprivileged user--e.g. nobody */
#undef NOBODY_USER
/* True if device files do not support xattrs */
#undef NO_DEVICE_XATTRS
/* True if special files do not support xattrs */
#undef NO_SPECIAL_XATTRS
/* True if symlinks do not support user xattrs */
#undef NO_SYMLINK_USER_XATTRS
/* True if symlinks do not support xattrs */
#undef NO_SYMLINK_XATTRS
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
/* Define to the full name of this package. */
#undef PACKAGE_NAME
/* Define to the full name and version of this package. */
#undef PACKAGE_STRING
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Define to the home page for this package. */
#undef PACKAGE_URL
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* location of configuration file for rsync server */
#undef RSYNCD_SYSCONF
/* location of rsync on remote machine */
#undef RSYNC_PATH
/* default -e command */
#undef RSYNC_RSH
/* Define to 1 if --protected-args should be the default */
#undef RSYNC_USE_PROTECTED_ARGS
/* rsync release version */
#undef RSYNC_VERSION
/* Define to 1 if sockets need to be shutdown */
#undef SHUTDOWN_ALL_SOCKETS
/* Define to 1 if "signed char" is a valid type */
#undef SIGNED_CHAR_OK
/* The size of `int', as computed by sizeof. */
#undef SIZEOF_INT
/* The size of `int16_t', as computed by sizeof. */
#undef SIZEOF_INT16_T
/* The size of `int32_t', as computed by sizeof. */
#undef SIZEOF_INT32_T
/* The size of `int64_t', as computed by sizeof. */
#undef SIZEOF_INT64_T
/* The size of `long', as computed by sizeof. */
#undef SIZEOF_LONG
/* The size of `long long', as computed by sizeof. */
#undef SIZEOF_LONG_LONG
/* The size of `off64_t', as computed by sizeof. */
#undef SIZEOF_OFF64_T
/* The size of `off_t', as computed by sizeof. */
#undef SIZEOF_OFF_T
/* The size of `short', as computed by sizeof. */
#undef SIZEOF_SHORT
/* The size of `time_t', as computed by sizeof. */
#undef SIZEOF_TIME_T
/* The size of `uint16_t', as computed by sizeof. */
#undef SIZEOF_UINT16_T
/* The size of `uint32_t', as computed by sizeof. */
#undef SIZEOF_UINT32_T
/* If using the C implementation of alloca, define if you know the
direction of stack growth for your system; otherwise it will be
automatically deduced at runtime.
STACK_DIRECTION > 0 => grows toward higher addresses
STACK_DIRECTION < 0 => grows toward lower addresses
STACK_DIRECTION = 0 => direction of growth unknown */
#undef STACK_DIRECTION
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Define to 1 to add support for ACLs */
#undef SUPPORT_ACLS
/* Define to 1 to add support for extended attributes */
#undef SUPPORT_XATTRS
/* Define to 1 if you can safely include both and . */
#undef TIME_WITH_SYS_TIME
/* Define to 1 if you want rsync to make use of iconv_open() */
#undef USE_ICONV_OPEN
/* String to pass to iconv() for the UTF-8 charset. */
#undef UTF8_CHARSET
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
significant byte first (like Motorola and SPARC, unlike Intel). */
#if defined AC_APPLE_UNIVERSAL_BUILD
# if defined __BIG_ENDIAN__
# define WORDS_BIGENDIAN 1
# endif
#else
# ifndef WORDS_BIGENDIAN
# undef WORDS_BIGENDIAN
# endif
#endif
/* Enable large inode numbers on Mac OS X 10.5. */
#ifndef _DARWIN_USE_64_BIT_INODE
# define _DARWIN_USE_64_BIT_INODE 1
#endif
/* Number of bits in a file offset, on hosts where this is settable. */
#undef _FILE_OFFSET_BITS
/* Define _GNU_SOURCE so that we get all necessary prototypes */
#undef _GNU_SOURCE
/* Define for large files, on AIX-style hosts. */
#undef _LARGE_FILES
/* Define to `int' if doesn't define. */
#undef gid_t
/* Define to `__inline__' or `__inline' if that's what the C compiler
calls it, or to nothing if 'inline' is not supported under any name. */
#ifndef __cplusplus
#undef inline
#endif
/* Define to `unsigned int' if does not define. */
#undef size_t
/* type to use in place of socklen_t if not defined */
#undef socklen_t
/* Define to `int' if doesn't define. */
#undef uid_t
rsync-bpc-3.1.3.0/config.sub 0000664 0000000 0000000 00000105301 13737671777 0015565 0 ustar 00root root 0000000 0000000 #! /bin/sh
# Configuration validation subroutine script.
# Copyright 1992-2013 Free Software Foundation, Inc.
timestamp='2013-04-24'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# 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, see .
#
# 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. This Exception is an additional permission under section 7
# of the GNU General Public License, version 3 ("GPLv3").
# Please send patches with a ChangeLog entry to config-patches@gnu.org.
#
# Configuration subroutine to validate and canonicalize a configuration type.
# Supply the specified configuration type as an argument.
# If it is invalid, we print an error message on stderr and exit with code 1.
# Otherwise, we print the canonical config type on stdout and succeed.
# You can get the latest version of this script from:
# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
# This file is supposed to be the same for all GNU packages
# and recognize all the CPU types, system types and aliases
# that are meaningful with *any* GNU software.
# Each package is responsible for reporting which valid configurations
# it does not support. The user should be able to distinguish
# a failure to support a valid configuration from a meaningless
# configuration.
# The goal of this file is to map all the various variations of a given
# machine specification into a single specification in the form:
# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
# or in some cases, the newer four-part form:
# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
# It is wrong to echo any other type of specification.
me=`echo "$0" | sed -e 's,.*/,,'`
usage="\
Usage: $0 [OPTION] CPU-MFR-OPSYS
$0 [OPTION] ALIAS
Canonicalize a configuration name.
Operation modes:
-h, --help print this help, then exit
-t, --time-stamp print date of last modification, then exit
-v, --version print version number, then exit
Report bugs and patches to ."
version="\
GNU config.sub ($timestamp)
Copyright 1992-2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
help="
Try \`$me --help' for more information."
# Parse command line
while test $# -gt 0 ; do
case $1 in
--time-stamp | --time* | -t )
echo "$timestamp" ; exit ;;
--version | -v )
echo "$version" ; exit ;;
--help | --h* | -h )
echo "$usage"; exit ;;
-- ) # Stop option processing
shift; break ;;
- ) # Use stdin as input.
break ;;
-* )
echo "$me: invalid option $1$help"
exit 1 ;;
*local*)
# First pass through any local machine types.
echo $1
exit ;;
* )
break ;;
esac
done
case $# in
0) echo "$me: missing argument$help" >&2
exit 1;;
1) ;;
*) echo "$me: too many arguments$help" >&2
exit 1;;
esac
# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
# 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-android* | linux-dietlibc | linux-newlib* | \
linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
knetbsd*-gnu* | netbsd*-gnu* | \
kopensolaris*-gnu* | \
storm-chaos* | os2-emx* | rtmk-nova*)
os=-$maybe_os
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
;;
android-linux)
os=-linux-android
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown
;;
*)
basic_machine=`echo $1 | sed 's/-[^-]*$//'`
if [ $basic_machine != $1 ]
then os=`echo $1 | sed 's/.*-/-/'`
else os=; fi
;;
esac
### Let's recognize common machines as not being operating systems so
### that things like config.sub decstation-3100 work. We also
### recognize some manufacturers as not being operating systems, so we
### can provide default operating systems below.
case $os in
-sun*os*)
# Prevent following clause from handling this invalid input.
;;
-dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
-att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
-unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
-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 | -knuth | -cray | -microblaze*)
os=
basic_machine=$1
;;
-bluegene*)
os=-cnk
;;
-sim | -cisco | -oki | -wec | -winbond)
os=
basic_machine=$1
;;
-scout)
;;
-wrs)
os=-vxworks
basic_machine=$1
;;
-chorusos*)
os=-chorusos
basic_machine=$1
;;
-chorusrdb)
os=-chorusrdb
basic_machine=$1
;;
-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/'`
;;
-sco4)
os=-sco3.2v4
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-sco3.2.[4-9]*)
os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-sco3.2v[4-9]*)
# 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/'`
;;
-udk*)
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-isc)
os=-isc2.2
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-clix*)
basic_machine=clipper-intergraph
;;
-isc*)
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-lynx*178)
os=-lynxos178
;;
-lynx*5)
os=-lynxos5
;;
-lynx*)
os=-lynxos
;;
-ptx*)
basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
;;
-windowsnt*)
os=`echo $os | sed -e 's/windowsnt/winnt/'`
;;
-psos*)
os=-psos
;;
-mint | -mint[0-9]*)
basic_machine=m68k-atari
os=-mint
;;
esac
# Decode aliases for certain CPU-COMPANY combinations.
case $basic_machine in
# Recognize the basic CPU types without company name.
# Some are omitted here because they have special meanings below.
1750a | 580 \
| a29k \
| aarch64 | aarch64_be \
| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
| am33_2.0 \
| arc | arceb \
| arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \
| avr | avr32 \
| be32 | be64 \
| bfin \
| c4x | clipper \
| d10v | d30v | dlx | dsp16xx \
| epiphany \
| fido | fr30 | frv \
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
| hexagon \
| i370 | i860 | i960 | ia64 \
| ip2k | iq2000 \
| le32 | le64 \
| lm32 \
| m32c | m32r | m32rle | m68000 | m68k | m88k \
| maxq | mb | microblaze | microblazeel | mcore | mep | metag \
| mips | mipsbe | mipseb | mipsel | mipsle \
| mips16 \
| mips64 | mips64el \
| mips64octeon | mips64octeonel \
| mips64orion | mips64orionel \
| mips64r5900 | mips64r5900el \
| mips64vr | mips64vrel \
| mips64vr4100 | mips64vr4100el \
| mips64vr4300 | mips64vr4300el \
| mips64vr5000 | mips64vr5000el \
| mips64vr5900 | mips64vr5900el \
| mipsisa32 | mipsisa32el \
| mipsisa32r2 | mipsisa32r2el \
| mipsisa64 | mipsisa64el \
| mipsisa64r2 | mipsisa64r2el \
| mipsisa64sb1 | mipsisa64sb1el \
| mipsisa64sr71k | mipsisa64sr71kel \
| mipsr5900 | mipsr5900el \
| mipstx39 | mipstx39el \
| mn10200 | mn10300 \
| moxie \
| mt \
| msp430 \
| nds32 | nds32le | nds32be \
| nios | nios2 | nios2eb | nios2el \
| ns16k | ns32k \
| open8 \
| or1k | or32 \
| pdp10 | pdp11 | pj | pjl \
| powerpc | powerpc64 | powerpc64le | powerpcle \
| pyramid \
| rl78 | rx \
| score \
| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
| sh64 | sh64le \
| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
| spu \
| tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
| ubicom32 \
| v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
| we32k \
| x86 | xc16x | xstormy16 | xtensa \
| z8k | z80)
basic_machine=$basic_machine-unknown
;;
c54x)
basic_machine=tic54x-unknown
;;
c55x)
basic_machine=tic55x-unknown
;;
c6x)
basic_machine=tic6x-unknown
;;
m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip)
basic_machine=$basic_machine-unknown
os=-none
;;
m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
;;
ms1)
basic_machine=mt-unknown
;;
strongarm | thumb | xscale)
basic_machine=arm-unknown
;;
xgate)
basic_machine=$basic_machine-unknown
os=-none
;;
xscaleeb)
basic_machine=armeb-unknown
;;
xscaleel)
basic_machine=armel-unknown
;;
# We use `pc' rather than `unknown'
# because (1) that's what they normally are, and
# (2) the word "unknown" tends to confuse beginning users.
i*86 | x86_64)
basic_machine=$basic_machine-pc
;;
# Object if more than one company name word.
*-*-*)
echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
exit 1
;;
# Recognize the basic CPU types with company name.
580-* \
| a29k-* \
| aarch64-* | aarch64_be-* \
| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
| alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \
| arm-* | armbe-* | armle-* | armeb-* | armv*-* \
| avr-* | avr32-* \
| be32-* | be64-* \
| bfin-* | bs2000-* \
| c[123]* | c30-* | [cjt]90-* | c4x-* \
| clipper-* | craynv-* | cydra-* \
| d10v-* | d30v-* | dlx-* \
| elxsi-* \
| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
| h8300-* | h8500-* \
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
| hexagon-* \
| i*86-* | i860-* | i960-* | ia64-* \
| ip2k-* | iq2000-* \
| le32-* | le64-* \
| lm32-* \
| m32c-* | m32r-* | m32rle-* \
| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
| m88110-* | m88k-* | maxq-* | mcore-* | metag-* \
| microblaze-* | microblazeel-* \
| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
| mips16-* \
| mips64-* | mips64el-* \
| mips64octeon-* | mips64octeonel-* \
| mips64orion-* | mips64orionel-* \
| mips64r5900-* | mips64r5900el-* \
| mips64vr-* | mips64vrel-* \
| mips64vr4100-* | mips64vr4100el-* \
| mips64vr4300-* | mips64vr4300el-* \
| mips64vr5000-* | mips64vr5000el-* \
| mips64vr5900-* | mips64vr5900el-* \
| mipsisa32-* | mipsisa32el-* \
| mipsisa32r2-* | mipsisa32r2el-* \
| mipsisa64-* | mipsisa64el-* \
| mipsisa64r2-* | mipsisa64r2el-* \
| mipsisa64sb1-* | mipsisa64sb1el-* \
| mipsisa64sr71k-* | mipsisa64sr71kel-* \
| mipsr5900-* | mipsr5900el-* \
| mipstx39-* | mipstx39el-* \
| mmix-* \
| mt-* \
| msp430-* \
| nds32-* | nds32le-* | nds32be-* \
| nios-* | nios2-* | nios2eb-* | nios2el-* \
| none-* | np1-* | ns16k-* | ns32k-* \
| open8-* \
| orion-* \
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
| pyramid-* \
| rl78-* | romp-* | rs6000-* | rx-* \
| sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
| sparclite-* \
| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \
| tahoe-* \
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
| tile*-* \
| tron-* \
| ubicom32-* \
| v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
| vax-* \
| we32k-* \
| x86-* | x86_64-* | xc16x-* | xps100-* \
| xstormy16-* | xtensa*-* \
| ymp-* \
| z8k-* | z80-*)
;;
# Recognize the basic CPU types without company name, with glob match.
xtensa*)
basic_machine=$basic_machine-unknown
;;
# Recognize the various machine names and aliases which stand
# for a CPU type and a company and sometimes even an OS.
386bsd)
basic_machine=i386-unknown
os=-bsd
;;
3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
basic_machine=m68000-att
;;
3b*)
basic_machine=we32k-att
;;
a29khif)
basic_machine=a29k-amd
os=-udi
;;
abacus)
basic_machine=abacus-unknown
;;
adobe68k)
basic_machine=m68010-adobe
os=-scout
;;
alliant | fx80)
basic_machine=fx80-alliant
;;
altos | altos3068)
basic_machine=m68k-altos
;;
am29k)
basic_machine=a29k-none
os=-bsd
;;
amd64)
basic_machine=x86_64-pc
;;
amd64-*)
basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
amdahl)
basic_machine=580-amdahl
os=-sysv
;;
amiga | amiga-*)
basic_machine=m68k-unknown
;;
amigaos | amigados)
basic_machine=m68k-unknown
os=-amigaos
;;
amigaunix | amix)
basic_machine=m68k-unknown
os=-sysv4
;;
apollo68)
basic_machine=m68k-apollo
os=-sysv
;;
apollo68bsd)
basic_machine=m68k-apollo
os=-bsd
;;
aros)
basic_machine=i386-pc
os=-aros
;;
aux)
basic_machine=m68k-apple
os=-aux
;;
balance)
basic_machine=ns32k-sequent
os=-dynix
;;
blackfin)
basic_machine=bfin-unknown
os=-linux
;;
blackfin-*)
basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
os=-linux
;;
bluegene*)
basic_machine=powerpc-ibm
os=-cnk
;;
c54x-*)
basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
c55x-*)
basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
c6x-*)
basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
c90)
basic_machine=c90-cray
os=-unicos
;;
cegcc)
basic_machine=arm-unknown
os=-cegcc
;;
convex-c1)
basic_machine=c1-convex
os=-bsd
;;
convex-c2)
basic_machine=c2-convex
os=-bsd
;;
convex-c32)
basic_machine=c32-convex
os=-bsd
;;
convex-c34)
basic_machine=c34-convex
os=-bsd
;;
convex-c38)
basic_machine=c38-convex
os=-bsd
;;
cray | j90)
basic_machine=j90-cray
os=-unicos
;;
craynv)
basic_machine=craynv-cray
os=-unicosmp
;;
cr16 | cr16-*)
basic_machine=cr16-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
;;
decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
basic_machine=mips-dec
;;
decsystem10* | dec10*)
basic_machine=pdp10-dec
os=-tops10
;;
decsystem20* | dec20*)
basic_machine=pdp10-dec
os=-tops20
;;
delta | 3300 | motorola-3300 | motorola-delta \
| 3300-motorola | delta-motorola)
basic_machine=m68k-motorola
;;
delta88)
basic_machine=m88k-motorola
os=-sysv3
;;
dicos)
basic_machine=i686-pc
os=-dicos
;;
djgpp)
basic_machine=i586-pc
os=-msdosdjgpp
;;
dpx20 | dpx20-*)
basic_machine=rs6000-bull
os=-bosx
;;
dpx2* | dpx2*-bull)
basic_machine=m68k-bull
os=-sysv3
;;
ebmon29k)
basic_machine=a29k-amd
os=-ebmon
;;
elxsi)
basic_machine=elxsi-elxsi
os=-bsd
;;
encore | umax | mmax)
basic_machine=ns32k-encore
;;
es1800 | OSE68k | ose68k | ose | OSE)
basic_machine=m68k-ericsson
os=-ose
;;
fx2800)
basic_machine=i860-alliant
;;
genix)
basic_machine=ns32k-ns
;;
gmicro)
basic_machine=tron-gmicro
os=-sysv
;;
go32)
basic_machine=i386-pc
os=-go32
;;
h3050r* | hiux*)
basic_machine=hppa1.1-hitachi
os=-hiuxwe2
;;
h8300hms)
basic_machine=h8300-hitachi
os=-hms
;;
h8300xray)
basic_machine=h8300-hitachi
os=-xray
;;
h8500hms)
basic_machine=h8500-hitachi
os=-hms
;;
harris)
basic_machine=m88k-harris
os=-sysv3
;;
hp300-*)
basic_machine=m68k-hp
;;
hp300bsd)
basic_machine=m68k-hp
os=-bsd
;;
hp300hpux)
basic_machine=m68k-hp
os=-hpux
;;
hp3k9[0-9][0-9] | hp9[0-9][0-9])
basic_machine=hppa1.0-hp
;;
hp9k2[0-9][0-9] | hp9k31[0-9])
basic_machine=m68000-hp
;;
hp9k3[2-9][0-9])
basic_machine=m68k-hp
;;
hp9k6[0-9][0-9] | hp6[0-9][0-9])
basic_machine=hppa1.0-hp
;;
hp9k7[0-79][0-9] | hp7[0-79][0-9])
basic_machine=hppa1.1-hp
;;
hp9k78[0-9] | hp78[0-9])
# FIXME: really hppa2.0-hp
basic_machine=hppa1.1-hp
;;
hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
# FIXME: really hppa2.0-hp
basic_machine=hppa1.1-hp
;;
hp9k8[0-9][13679] | hp8[0-9][13679])
basic_machine=hppa1.1-hp
;;
hp9k8[0-9][0-9] | hp8[0-9][0-9])
basic_machine=hppa1.0-hp
;;
hppa-next)
os=-nextstep3
;;
hppaosf)
basic_machine=hppa1.1-hp
os=-osf
;;
hppro)
basic_machine=hppa1.1-hp
os=-proelf
;;
i370-ibm* | ibm*)
basic_machine=i370-ibm
;;
i*86v32)
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
os=-sysv32
;;
i*86v4*)
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
os=-sysv4
;;
i*86v)
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
os=-sysv
;;
i*86sol2)
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
os=-solaris2
;;
i386mach)
basic_machine=i386-mach
os=-mach
;;
i386-vsta | vsta)
basic_machine=i386-unknown
os=-vsta
;;
iris | iris4d)
basic_machine=mips-sgi
case $os in
-irix*)
;;
*)
os=-irix4
;;
esac
;;
isi68 | isi)
basic_machine=m68k-isi
os=-sysv
;;
m68knommu)
basic_machine=m68k-unknown
os=-linux
;;
m68knommu-*)
basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
os=-linux
;;
m88k-omron*)
basic_machine=m88k-omron
;;
magnum | m3230)
basic_machine=mips-mips
os=-sysv
;;
merlin)
basic_machine=ns32k-utek
os=-sysv
;;
microblaze*)
basic_machine=microblaze-xilinx
;;
mingw64)
basic_machine=x86_64-pc
os=-mingw64
;;
mingw32)
basic_machine=i386-pc
os=-mingw32
;;
mingw32ce)
basic_machine=arm-unknown
os=-mingw32ce
;;
miniframe)
basic_machine=m68000-convergent
;;
*mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
basic_machine=m68k-atari
os=-mint
;;
mips3*-*)
basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
;;
mips3*)
basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
;;
monitor)
basic_machine=m68k-rom68k
os=-coff
;;
morphos)
basic_machine=powerpc-unknown
os=-morphos
;;
msdos)
basic_machine=i386-pc
os=-msdos
;;
ms1-*)
basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
;;
msys)
basic_machine=i386-pc
os=-msys
;;
mvs)
basic_machine=i370-ibm
os=-mvs
;;
nacl)
basic_machine=le32-unknown
os=-nacl
;;
ncr3000)
basic_machine=i486-ncr
os=-sysv4
;;
netbsd386)
basic_machine=i386-unknown
os=-netbsd
;;
netwinder)
basic_machine=armv4l-rebel
os=-linux
;;
news | news700 | news800 | news900)
basic_machine=m68k-sony
os=-newsos
;;
news1000)
basic_machine=m68030-sony
os=-newsos
;;
news-3600 | risc-news)
basic_machine=mips-sony
os=-newsos
;;
necv70)
basic_machine=v70-nec
os=-sysv
;;
next | m*-next )
basic_machine=m68k-next
case $os in
-nextstep* )
;;
-ns2*)
os=-nextstep2
;;
*)
os=-nextstep3
;;
esac
;;
nh3000)
basic_machine=m68k-harris
os=-cxux
;;
nh[45]000)
basic_machine=m88k-harris
os=-cxux
;;
nindy960)
basic_machine=i960-intel
os=-nindy
;;
mon960)
basic_machine=i960-intel
os=-mon960
;;
nonstopux)
basic_machine=mips-compaq
os=-nonstopux
;;
np1)
basic_machine=np1-gould
;;
neo-tandem)
basic_machine=neo-tandem
;;
nse-tandem)
basic_machine=nse-tandem
;;
nsr-tandem)
basic_machine=nsr-tandem
;;
op50n-* | op60c-*)
basic_machine=hppa1.1-oki
os=-proelf
;;
openrisc | openrisc-*)
basic_machine=or32-unknown
;;
os400)
basic_machine=powerpc-ibm
os=-os400
;;
OSE68000 | ose68000)
basic_machine=m68000-ericsson
os=-ose
;;
os68k)
basic_machine=m68k-none
os=-os68k
;;
pa-hitachi)
basic_machine=hppa1.1-hitachi
os=-hiuxwe2
;;
paragon)
basic_machine=i860-intel
os=-osf
;;
parisc)
basic_machine=hppa-unknown
os=-linux
;;
parisc-*)
basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`
os=-linux
;;
pbd)
basic_machine=sparc-tti
;;
pbb)
basic_machine=m68k-tti
;;
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
;;
pentiumpro | p6 | 6x86 | athlon | athlon_*)
basic_machine=i686-pc
;;
pentiumii | pentium2 | pentiumiii | pentium3)
basic_machine=i686-pc
;;
pentium4)
basic_machine=i786-pc
;;
pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
pentiumpro-* | p6-* | 6x86-* | athlon-*)
basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
pentium4-*)
basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
pn)
basic_machine=pn-gould
;;
power) basic_machine=power-ibm
;;
ppc | ppcbe) basic_machine=powerpc-unknown
;;
ppc-* | ppcbe-*)
basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
ppcle | powerpclittle | ppc-le | powerpc-little)
basic_machine=powerpcle-unknown
;;
ppcle-* | powerpclittle-*)
basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
ppc64) basic_machine=powerpc64-unknown
;;
ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
ppc64le | powerpc64little | ppc64-le | powerpc64-little)
basic_machine=powerpc64le-unknown
;;
ppc64le-* | powerpc64little-*)
basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
ps2)
basic_machine=i386-ibm
;;
pw32)
basic_machine=i586-unknown
os=-pw32
;;
rdos | rdos64)
basic_machine=x86_64-pc
os=-rdos
;;
rdos32)
basic_machine=i386-pc
os=-rdos
;;
rom68k)
basic_machine=m68k-rom68k
os=-coff
;;
rm[46]00)
basic_machine=mips-siemens
;;
rtpc | rtpc-*)
basic_machine=romp-ibm
;;
s390 | s390-*)
basic_machine=s390-ibm
;;
s390x | s390x-*)
basic_machine=s390x-ibm
;;
sa29200)
basic_machine=a29k-amd
os=-udi
;;
sb1)
basic_machine=mipsisa64sb1-unknown
;;
sb1el)
basic_machine=mipsisa64sb1el-unknown
;;
sde)
basic_machine=mipsisa32-sde
os=-elf
;;
sei)
basic_machine=mips-sei
os=-seiux
;;
sequent)
basic_machine=i386-sequent
;;
sh)
basic_machine=sh-hitachi
os=-hms
;;
sh5el)
basic_machine=sh5le-unknown
;;
sh64)
basic_machine=sh64-unknown
;;
sparclite-wrs | simso-wrs)
basic_machine=sparclite-wrs
os=-vxworks
;;
sps7)
basic_machine=m68k-bull
os=-sysv2
;;
spur)
basic_machine=spur-unknown
;;
st2000)
basic_machine=m68k-tandem
;;
stratus)
basic_machine=i860-stratus
os=-sysv4
;;
strongarm-* | thumb-*)
basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
sun2)
basic_machine=m68000-sun
;;
sun2os3)
basic_machine=m68000-sun
os=-sunos3
;;
sun2os4)
basic_machine=m68000-sun
os=-sunos4
;;
sun3os3)
basic_machine=m68k-sun
os=-sunos3
;;
sun3os4)
basic_machine=m68k-sun
os=-sunos4
;;
sun4os3)
basic_machine=sparc-sun
os=-sunos3
;;
sun4os4)
basic_machine=sparc-sun
os=-sunos4
;;
sun4sol2)
basic_machine=sparc-sun
os=-solaris2
;;
sun3 | sun3-*)
basic_machine=m68k-sun
;;
sun4)
basic_machine=sparc-sun
;;
sun386 | sun386i | roadrunner)
basic_machine=i386-sun
;;
sv1)
basic_machine=sv1-cray
os=-unicos
;;
symmetry)
basic_machine=i386-sequent
os=-dynix
;;
t3e)
basic_machine=alphaev5-cray
os=-unicos
;;
t90)
basic_machine=t90-cray
os=-unicos
;;
tile*)
basic_machine=$basic_machine-unknown
os=-linux-gnu
;;
tx39)
basic_machine=mipstx39-unknown
;;
tx39el)
basic_machine=mipstx39el-unknown
;;
toad1)
basic_machine=pdp10-xkl
os=-tops20
;;
tower | tower-32)
basic_machine=m68k-ncr
;;
tpf)
basic_machine=s390x-ibm
os=-tpf
;;
udi29k)
basic_machine=a29k-amd
os=-udi
;;
ultra3)
basic_machine=a29k-nyu
os=-sym1
;;
v810 | necv810)
basic_machine=v810-nec
os=-none
;;
vaxv)
basic_machine=vax-dec
os=-sysv
;;
vms)
basic_machine=vax-dec
os=-vms
;;
vpp*|vx|vx-*)
basic_machine=f301-fujitsu
;;
vxworks960)
basic_machine=i960-wrs
os=-vxworks
;;
vxworks68)
basic_machine=m68k-wrs
os=-vxworks
;;
vxworks29k)
basic_machine=a29k-wrs
os=-vxworks
;;
w65*)
basic_machine=w65-wdc
os=-none
;;
w89k-*)
basic_machine=hppa1.1-winbond
os=-proelf
;;
xbox)
basic_machine=i686-pc
os=-mingw32
;;
xps | xps100)
basic_machine=xps100-honeywell
;;
xscale-* | xscalee[bl]-*)
basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'`
;;
ymp)
basic_machine=ymp-cray
os=-unicos
;;
z8k-*-coff)
basic_machine=z8k-unknown
os=-sim
;;
z80-*-coff)
basic_machine=z80-unknown
os=-sim
;;
none)
basic_machine=none-none
os=-none
;;
# Here we handle the default manufacturer of certain CPU types. It is in
# some cases the only manufacturer, in others, it is the most popular.
w89k)
basic_machine=hppa1.1-winbond
;;
op50n)
basic_machine=hppa1.1-oki
;;
op60c)
basic_machine=hppa1.1-oki
;;
romp)
basic_machine=romp-ibm
;;
mmix)
basic_machine=mmix-knuth
;;
rs6000)
basic_machine=rs6000-ibm
;;
vax)
basic_machine=vax-dec
;;
pdp10)
# there are many clones, so DEC is not a safe bet
basic_machine=pdp10-unknown
;;
pdp11)
basic_machine=pdp11-dec
;;
we32k)
basic_machine=we32k-att
;;
sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele)
basic_machine=sh-unknown
;;
sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
basic_machine=sparc-sun
;;
cydra)
basic_machine=cydra-cydrome
;;
orion)
basic_machine=orion-highlevel
;;
orion105)
basic_machine=clipper-highlevel
;;
mac | mpw | mac-mpw)
basic_machine=m68k-apple
;;
pmac | pmac-mpw)
basic_machine=powerpc-apple
;;
*-unknown)
# Make sure to match an already-canonicalized machine name.
;;
*)
echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
exit 1
;;
esac
# Here we canonicalize certain aliases for manufacturers.
case $basic_machine in
*-digital*)
basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
;;
*-commodore*)
basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
;;
*)
;;
esac
# Decode manufacturer-specific aliases for certain operating systems.
if [ x"$os" != x"" ]
then
case $os in
# First match some system type aliases
# that might get confused with valid system types.
# -solaris* is a basic system type, with this one exception.
-auroraux)
os=-auroraux
;;
-solaris1 | -solaris1.*)
os=`echo $os | sed -e 's|solaris1|sunos4|'`
;;
-solaris)
os=-solaris2
;;
-svr4*)
os=-sysv4
;;
-unixware*)
os=-sysv4.2uw
;;
-gnu/linux*)
os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
;;
# First accept the basic system types.
# The portable systems comes first.
# Each alternative MUST END IN A *, to match a version number.
# -sysv* is not here because it comes later, after sysvr4.
-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
| -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
| -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
| -sym* | -kopensolaris* | -plan9* \
| -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
| -aos* | -aros* \
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
| -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
| -bitrig* | -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* | -cegcc* \
| -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
| -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
| -linux-newlib* | -linux-musl* | -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* | -dragonfly* \
| -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*)
# Remember, each alternative MUST END IN *, to match a version number.
;;
-qnx*)
case $basic_machine in
x86-* | i*86-*)
;;
*)
os=-nto$os
;;
esac
;;
-nto-qnx*)
;;
-nto*)
os=`echo $os | sed -e 's|nto|nto-qnx|'`
;;
-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
| -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
| -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
;;
-mac*)
os=`echo $os | sed -e 's|mac|macos|'`
;;
-linux-dietlibc)
os=-linux-dietlibc
;;
-linux*)
os=`echo $os | sed -e 's|linux|linux-gnu|'`
;;
-sunos5*)
os=`echo $os | sed -e 's|sunos5|solaris2|'`
;;
-sunos6*)
os=`echo $os | sed -e 's|sunos6|solaris3|'`
;;
-opened*)
os=-openedition
;;
-os400*)
os=-os400
;;
-wince*)
os=-wince
;;
-osfrose*)
os=-osfrose
;;
-osf*)
os=-osf
;;
-utek*)
os=-bsd
;;
-dynix*)
os=-bsd
;;
-acis*)
os=-aos
;;
-atheos*)
os=-atheos
;;
-syllable*)
os=-syllable
;;
-386bsd)
os=-bsd
;;
-ctix* | -uts*)
os=-sysv
;;
-nova*)
os=-rtmk-nova
;;
-ns2 )
os=-nextstep2
;;
-nsk*)
os=-nsk
;;
# Preserve the version number of sinix5.
-sinix5.*)
os=`echo $os | sed -e 's|sinix|sysv|'`
;;
-sinix*)
os=-sysv4
;;
-tpf*)
os=-tpf
;;
-triton*)
os=-sysv3
;;
-oss*)
os=-sysv3
;;
-svr4)
os=-sysv4
;;
-svr3)
os=-sysv3
;;
-sysvr4)
os=-sysv4
;;
# This must come after -sysvr4.
-sysv*)
;;
-ose*)
os=-ose
;;
-es1800*)
os=-ose
;;
-xenix)
os=-xenix
;;
-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
os=-mint
;;
-aros*)
os=-aros
;;
-zvmoe)
os=-zvmoe
;;
-dicos*)
os=-dicos
;;
-nacl*)
;;
-none)
;;
*)
# Get rid of the `-' at the beginning of $os.
os=`echo $os | sed 's/[^-]*-//'`
echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
exit 1
;;
esac
else
# Here we handle the default operating systems that come with various machines.
# The value should be what the vendor currently ships out the door with their
# machine or put another way, the most popular os provided with the machine.
# Note that if you're going to try to match "-MANUFACTURER" here (say,
# "-sun"), then you have to tell the case statement up towards the top
# that MANUFACTURER isn't an operating system. Otherwise, code above
# will signal an error saying that MANUFACTURER isn't an operating
# system, and we'll never get to this point.
case $basic_machine in
score-*)
os=-elf
;;
spu-*)
os=-elf
;;
*-acorn)
os=-riscix1.2
;;
arm*-rebel)
os=-linux
;;
arm*-semi)
os=-aout
;;
c4x-* | tic4x-*)
os=-coff
;;
hexagon-*)
os=-elf
;;
tic54x-*)
os=-coff
;;
tic55x-*)
os=-coff
;;
tic6x-*)
os=-coff
;;
# This must come before the *-dec entry.
pdp10-*)
os=-tops20
;;
pdp11-*)
os=-none
;;
*-dec | vax-*)
os=-ultrix4.2
;;
m68*-apollo)
os=-domain
;;
i386-sun)
os=-sunos4.0.2
;;
m68000-sun)
os=-sunos3
;;
m68*-cisco)
os=-aout
;;
mep-*)
os=-elf
;;
mips*-cisco)
os=-elf
;;
mips*-*)
os=-elf
;;
or1k-*)
os=-elf
;;
or32-*)
os=-coff
;;
*-tti) # must be before sparc entry or we get the wrong os.
os=-sysv3
;;
sparc-* | *-sun)
os=-sunos4.1.1
;;
*-be)
os=-beos
;;
*-haiku)
os=-haiku
;;
*-ibm)
os=-aix
;;
*-knuth)
os=-mmixware
;;
*-wec)
os=-proelf
;;
*-winbond)
os=-proelf
;;
*-oki)
os=-proelf
;;
*-hp)
os=-hpux
;;
*-hitachi)
os=-hiux
;;
i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
os=-sysv
;;
*-cbm)
os=-amigaos
;;
*-dg)
os=-dgux
;;
*-dolphin)
os=-sysv3
;;
m68k-ccur)
os=-rtu
;;
m88k-omron*)
os=-luna
;;
*-next )
os=-nextstep
;;
*-sequent)
os=-ptx
;;
*-crds)
os=-unos
;;
*-ns)
os=-genix
;;
i370-*)
os=-mvs
;;
*-next)
os=-nextstep3
;;
*-gould)
os=-sysv
;;
*-highlevel)
os=-bsd
;;
*-encore)
os=-bsd
;;
*-sgi)
os=-irix
;;
*-siemens)
os=-sysv4
;;
*-masscomp)
os=-rtu
;;
f30[01]-fujitsu | f700-fujitsu)
os=-uxpv
;;
*-rom68k)
os=-coff
;;
*-*bug)
os=-coff
;;
*-apple)
os=-macos
;;
*-atari*)
os=-mint
;;
*)
os=-none
;;
esac
fi
# Here we handle the case where we know the os, and the CPU type, but not the
# manufacturer. We pick the logical manufacturer.
vendor=unknown
case $basic_machine in
*-unknown)
case $os in
-riscix*)
vendor=acorn
;;
-sunos*)
vendor=sun
;;
-cnk*|-aix*)
vendor=ibm
;;
-beos*)
vendor=be
;;
-hpux*)
vendor=hp
;;
-mpeix*)
vendor=hp
;;
-hiux*)
vendor=hitachi
;;
-unos*)
vendor=crds
;;
-dgux*)
vendor=dg
;;
-luna*)
vendor=omron
;;
-genix*)
vendor=ns
;;
-mvs* | -opened*)
vendor=ibm
;;
-os400*)
vendor=ibm
;;
-ptx*)
vendor=sequent
;;
-tpf*)
vendor=ibm
;;
-vxsim* | -vxworks* | -windiss*)
vendor=wrs
;;
-aux*)
vendor=apple
;;
-hms*)
vendor=hitachi
;;
-mpw* | -macos*)
vendor=apple
;;
-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
vendor=atari
;;
-vos*)
vendor=stratus
;;
esac
basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
;;
esac
echo $basic_machine$os
exit
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "timestamp='"
# time-stamp-format: "%:y-%02m-%02d"
# time-stamp-end: "'"
# End:
rsync-bpc-3.1.3.0/configure 0000775 0000000 0000000 00000001355 13737671777 0015520 0 ustar 00root root 0000000 0000000 #!/bin/sh -e
# This configure script ensures that the configure.sh script exists, and
# if not, it tries to fetch rsync's generated files or build them. We
# then transfer control to the configure.sh script to do the real work.
dir=`dirname $0`
realconfigure="$dir/configure.sh"
if test ! -f "$realconfigure"; then
if test -f "$HOME/build_farm/build_test.fns"; then
# Test the included popt
set -- --with-included-popt "${@}"
# Allow the build farm to grab latest files via rsync.
actions='build fetch'
else
actions='build'
fi
if "$dir/prepare-source" $actions; then
:
else
echo 'Failed to build configure.sh and/or config.h.in -- giving up.' >&2
rm -f "$realconfigure"
exit 1
fi
fi
exec "$realconfigure" "${@}"
rsync-bpc-3.1.3.0/configure.ac 0000664 0000000 0000000 00000110064 13737671777 0016075 0 ustar 00root root 0000000 0000000 dnl Process this file with autoconf to produce a configure script.
AC_INIT([rsync-bpc],[3.1.3.0],[https://github.com/backuppc/rsync-bpc/issues])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_SRCDIR([byteorder.h])
AC_CONFIG_HEADER(config.h)
AC_PREREQ([2.69])
AC_SUBST(RSYNC_VERSION, $PACKAGE_VERSION)
AC_MSG_NOTICE([Configuring rsync_bpc $PACKAGE_VERSION])
AC_DEFINE_UNQUOTED(RSYNC_VERSION, ["$PACKAGE_VERSION"], [rsync_bpc release version])
LDFLAGS=${LDFLAGS-""}
AC_CANONICAL_HOST
dnl define the directory for replacement function since AC_LIBOBJ does not
dnl officially support subdirs and fails with automake
AC_CONFIG_LIBOBJ_DIR([lib])
# We must decide this before testing the compiler.
# Please allow this to default to yes, so that your users have more
# chance of getting a useful stack trace if problems occur.
AC_MSG_CHECKING([whether to include debugging symbols])
AC_ARG_ENABLE(debug,
AS_HELP_STRING([--disable-debug],[disable debugging symbols and features]))
if test x"$enable_debug" = x"no"; then
AC_MSG_RESULT(no)
ac_cv_prog_cc_g=no
else
AC_MSG_RESULT([yes])
dnl AC_DEFINE(DEBUG, 1, [Define to turn on debugging code that may slow normal operation])
# leave ac_cv_prog_cc_g alone; AC_PROG_CC will try to include -g if it can
fi
dnl Checks for programs.
AC_PROG_CC
AC_PROG_CPP
AC_PROG_EGREP
AC_PROG_INSTALL
AC_PROG_MKDIR_P
AC_PROG_CC_STDC
AC_SUBST(SHELL)
AC_PATH_PROG([PERL], [perl])
AC_DEFINE([_GNU_SOURCE], 1,
[Define _GNU_SOURCE so that we get all necessary prototypes])
if test x"$ac_cv_prog_cc_stdc" = x"no"; then
AC_MSG_WARN([rsync requires an ANSI C compiler and you do not seem to have one])
fi
AC_ARG_ENABLE(profile,
AS_HELP_STRING([--enable-profile],[turn on CPU profiling]))
if test x"$enable_profile" = x"yes"; then
CFLAGS="$CFLAGS -pg"
fi
# Specifically, this turns on panic_action handling.
AC_ARG_ENABLE(maintainer-mode,
AS_HELP_STRING([--enable-maintainer-mode],[turn on extra debug features]))
if test x"$enable_maintainer_mode" = x"yes"; then
CFLAGS="$CFLAGS -DMAINTAINER_MODE"
fi
# This is needed for our included version of popt. Kind of silly, but
# I don't want our version too far out of sync.
CFLAGS="$CFLAGS -DHAVE_CONFIG_H"
# If GCC, turn on warnings.
if test x"$GCC" = x"yes"; then
CFLAGS="$CFLAGS -Wall -W"
fi
AC_ARG_WITH(included-popt,
AS_HELP_STRING([--with-included-popt],[use bundled popt library, not from system]))
AC_ARG_WITH(included-zlib,
AS_HELP_STRING([--with-included-zlib],[use bundled zlib library, not from system]))
AC_ARG_WITH(protected-args,
AS_HELP_STRING([--with-protected-args],[make --protected-args option the default]))
if test x"$with_protected_args" = x"yes"; then
AC_DEFINE_UNQUOTED(RSYNC_USE_PROTECTED_ARGS, 1, [Define to 1 if --protected-args should be the default])
fi
AC_ARG_WITH(rsync-path,
AS_HELP_STRING([--with-rsync-path=PATH],[set default --rsync-path to PATH (default: rsync)]),
[ RSYNC_PATH="$with_rsync_path" ],
[ RSYNC_PATH="rsync" ])
AC_DEFINE_UNQUOTED(RSYNC_PATH, "$RSYNC_PATH", [location of rsync on remote machine])
AC_ARG_WITH(rsyncd-conf,
AS_HELP_STRING([--with-rsyncd-conf=PATH],[set configuration file for rsync server to PATH (default: /etc/rsyncd.conf)]),
[ if test ! -z "$with_rsyncd_conf" ; then
case $with_rsyncd_conf in
yes|no)
RSYNCD_SYSCONF="/etc/rsyncd.conf"
;;
/*)
RSYNCD_SYSCONF="$with_rsyncd_conf"
;;
*)
AC_MSG_ERROR(You must specify an absolute path to --with-rsyncd-conf=PATH)
;;
esac
else
RSYNCD_SYSCONF="/etc/rsyncd.conf"
fi ],
[ RSYNCD_SYSCONF="/etc/rsyncd.conf" ])
AC_DEFINE_UNQUOTED(RSYNCD_SYSCONF, "$RSYNCD_SYSCONF", [location of configuration file for rsync server])
AC_ARG_WITH(rsh,
AS_HELP_STRING([--with-rsh=CMD],[set remote shell command to CMD (default: ssh)]))
AC_CHECK_PROG(HAVE_REMSH, remsh, 1, 0)
if test x$HAVE_REMSH = x1; then
AC_DEFINE(HAVE_REMSH, 1, [Define to 1 if remote shell is remsh, not rsh])
fi
if test x"$with_rsh" != x; then
RSYNC_RSH="$with_rsh"
else
RSYNC_RSH="ssh"
fi
AC_DEFINE_UNQUOTED(RSYNC_RSH, "$RSYNC_RSH", [default -e command])
AC_CHECK_PROG(HAVE_YODL2MAN, yodl2man, 1, 0)
if test x$HAVE_YODL2MAN = x1; then
MAKE_MAN=man
else
MAKE_MAN=man-copy
fi
# Some programs on solaris are only found in /usr/xpg4/bin (or work better than others versions).
AC_PATH_PROG(SHELL_PATH, sh, /bin/sh, [/usr/xpg4/bin$PATH_SEPARATOR$PATH])
AC_PATH_PROG(FAKEROOT_PATH, fakeroot, /usr/bin/fakeroot, [/usr/xpg4/bin$PATH_SEPARATOR$PATH])
AC_ARG_WITH(nobody-group,
AS_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_DEFINE_UNQUOTED(NOBODY_USER, "nobody", [unprivileged user--e.g. nobody])
AC_DEFINE_UNQUOTED(NOBODY_GROUP, "$NOBODY_GROUP", [unprivileged group for unprivileged user])
# arrgh. libc in some old debian version screwed up the largefile
# stuff, getting byte range locking wrong
AC_CACHE_CHECK([for broken largefile support],rsync_cv_HAVE_BROKEN_LARGEFILE,[
AC_RUN_IFELSE([AC_LANG_SOURCE([[
#define _FILE_OFFSET_BITS 64
#include
#include
#include
#include
int main(void)
{
struct flock lock;
int status;
char tpl[32] = "/tmp/locktest.XXXXXX";
int fd = mkstemp(tpl);
if (fd < 0) {
strcpy(tpl, "conftest.dat");
fd = open(tpl, O_CREAT|O_RDWR, 0600);
}
lock.l_type = F_WRLCK;
lock.l_whence = SEEK_SET;
lock.l_start = 0;
lock.l_len = 1;
lock.l_pid = 0;
fcntl(fd,F_SETLK,&lock);
if (fork() == 0) {
lock.l_start = 1;
_exit(fcntl(fd,F_SETLK,&lock) == 0);
}
wait(&status);
unlink(tpl);
exit(WEXITSTATUS(status));
}
]])],[rsync_cv_HAVE_BROKEN_LARGEFILE=yes],[rsync_cv_HAVE_BROKEN_LARGEFILE=no],[rsync_cv_HAVE_BROKEN_LARGEFILE=cross])])
if test x"$rsync_cv_HAVE_BROKEN_LARGEFILE" != x"yes"; then
AC_SYS_LARGEFILE
fi
ipv6type=unknown
ipv6lib=none
ipv6trylibc=yes
AC_ARG_ENABLE(ipv6,
AS_HELP_STRING([--disable-ipv6],[do not even try to use IPv6]))
if test x"$enable_ipv6" != x"no"; then
AC_MSG_CHECKING([ipv6 stack type])
for i in inria kame linux-glibc linux-inet6 solaris toshiba v6d zeta cygwin; do
case $i in
inria)
# http://www.kame.net/
AC_EGREP_CPP(yes, [
#include
#ifdef IPV6_INRIA_VERSION
yes
#endif],
[ipv6type=$i;
AC_DEFINE(INET6, 1, [true if you have IPv6])
])
;;
kame)
# http://www.kame.net/
AC_EGREP_CPP(yes, [
#include
#ifdef __KAME__
yes
#endif],
[ipv6type=$i;
AC_DEFINE(INET6, 1, [true if you have IPv6])])
;;
linux-glibc)
# http://www.v6.linux.or.jp/
AC_EGREP_CPP(yes, [
#include
#if defined(__GLIBC__) && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1
yes
#endif],
[ipv6type=$i;
AC_DEFINE(INET6, 1, [true if you have IPv6])])
;;
linux-inet6)
# http://www.v6.linux.or.jp/
if test -d /usr/inet6 -o -f /usr/inet6/lib/libinet6.a; then
ipv6type=$i
ipv6lib=inet6
ipv6libdir=/usr/inet6/lib
ipv6trylibc=yes;
AC_DEFINE(INET6, 1, [true if you have IPv6])
CFLAGS="-I/usr/inet6/include $CFLAGS"
fi
;;
solaris)
# http://www.sun.com
AC_EGREP_CPP(yes, [
#include
#ifdef __sun
yes
#endif],
[ipv6type=$i;
AC_DEFINE(INET6, 1, [true if you have IPv6])])
;;
toshiba)
AC_EGREP_CPP(yes, [
#include
#ifdef _TOSHIBA_INET6
yes
#endif],
[ipv6type=$i;
ipv6lib=inet6;
ipv6libdir=/usr/local/v6/lib;
AC_DEFINE(INET6, 1, [true if you have IPv6])])
;;
v6d)
AC_EGREP_CPP(yes, [
#include
#ifdef __V6D__
yes
#endif],
[ipv6type=$i;
ipv6lib=v6;
ipv6libdir=/usr/local/v6/lib;
AC_DEFINE(INET6, 1, [true if you have IPv6])])
;;
zeta)
AC_EGREP_CPP(yes, [
#include
#ifdef _ZETA_MINAMI_INET6
yes
#endif],
[ipv6type=$i;
ipv6lib=inet6;
ipv6libdir=/usr/local/v6/lib;
AC_DEFINE(INET6, 1, [true if you have IPv6])])
;;
cygwin)
AC_EGREP_CPP(yes, [
#include
#ifdef _CYGWIN_IN6_H
yes
#endif],
[ipv6type=$i;
AC_DEFINE(INET6, 1, [true if you have IPv6])])
;;
esac
if test "$ipv6type" != "unknown"; then
break
fi
done
AC_MSG_RESULT($ipv6type)
AC_SEARCH_LIBS(getaddrinfo, inet6)
fi
dnl Do you want to disable use of locale functions
AC_ARG_ENABLE([locale],
AS_HELP_STRING([--disable-locale],[disable locale features]))
AH_TEMPLATE([CONFIG_LOCALE],
[Undefine if you do not want locale features. By default this is defined.])
if test x"$enable_locale" != x"no"; then
AC_DEFINE(CONFIG_LOCALE)
fi
AC_MSG_CHECKING([whether to call shutdown on all sockets])
case $host_os in
*cygwin* ) AC_MSG_RESULT(yes)
AC_DEFINE(SHUTDOWN_ALL_SOCKETS, 1,
[Define to 1 if sockets need to be shutdown])
;;
* ) AC_MSG_RESULT(no);;
esac
AC_C_BIGENDIAN
AC_HEADER_DIRENT
AC_HEADER_TIME
AC_HEADER_SYS_WAIT
AC_CHECK_HEADERS(sys/fcntl.h sys/select.h fcntl.h sys/time.h sys/unistd.h \
unistd.h utime.h grp.h compat.h sys/param.h ctype.h sys/wait.h \
sys/ioctl.h sys/filio.h string.h stdlib.h sys/socket.h sys/mode.h \
sys/un.h sys/attr.h mcheck.h arpa/inet.h arpa/nameser.h locale.h \
netdb.h malloc.h float.h limits.h iconv.h libcharset.h langinfo.h \
sys/acl.h acl/libacl.h attr/xattr.h sys/xattr.h sys/extattr.h \
popt.h popt/popt.h linux/falloc.h netinet/in_systm.h netinet/ip.h \
zlib.h)
AC_CHECK_HEADERS_ONCE([sys/types.h])
AC_CHECK_HEADER(sys/mkdev.h,
[AC_DEFINE(MAJOR_IN_MKDEV, 1,
[Define to 1 if `major', `minor', and `makedev' are
declared in .])])
if test $ac_cv_header_sys_mkdev_h = no; then
AC_CHECK_HEADER(sys/sysmacros.h,
[AC_DEFINE(MAJOR_IN_SYSMACROS, 1,
[Define to 1 if `major', `minor', and `makedev'
are declared in .])])
fi
AC_CACHE_CHECK([if makedev takes 3 args],rsync_cv_MAKEDEV_TAKES_3_ARGS,[
AC_RUN_IFELSE([AC_LANG_SOURCE([[
#include
#ifdef MAJOR_IN_MKDEV
#include
# if !defined makedev && (defined mkdev || defined _WIN32 || defined __WIN32__)
# define makedev mkdev
# endif
#elif defined MAJOR_IN_SYSMACROS
#include
#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_TYPE_LONG_DOUBLE_WIDER
ac_cv_c_long_double=$ac_cv_type_long_double_wider
if test $ac_cv_c_long_double = yes; then
AC_DEFINE([HAVE_LONG_DOUBLE],[1],[Define to 1 if the type `long double' works and has more range or precision than `double'.])
fi
AC_TYPE_UID_T
AC_CHECK_TYPES([mode_t,off_t,size_t,pid_t,id_t])
AC_TYPE_GETGROUPS
AC_CHECK_MEMBERS([struct stat.st_rdev,
struct stat.st_mtimensec,
struct stat.st_mtimespec.tv_nsec,
struct stat.st_mtim.tv_nsec],,,[
#ifdef HAVE_SYS_TYPES_H
#include
#endif
#ifdef HAVE_SYS_STAT_H
#include
#endif
#ifdef HAVE_UNISTD_H
#include
#endif])
TYPE_SOCKLEN_T
AC_CACHE_CHECK([for errno in errno.h],rsync_cv_errno, [
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[int i = errno]])],[rsync_cv_errno=yes],[rsync_cv_have_errno_decl=no])])
if test x"$rsync_cv_errno" = x"yes"; then
AC_DEFINE(HAVE_ERRNO_DECL, 1, [Define to 1 if errno is declared in errno.h])
fi
# The following test taken from the cvs sources
# If we can't find connect, try looking in -lsocket, -lnsl, and -linet.
# These need checks to be before checks for any other functions that
# might be in the same libraries.
# The Irix 5 libc.so has connect and gethostbyname, but Irix 5 also has
# libsocket.so which has a bad implementation of gethostbyname (it
# only looks in /etc/hosts), so we only look for -lsocket if we need
# it.
AC_CHECK_FUNCS(connect)
if test x"$ac_cv_func_connect" = x"no"; then
case "$LIBS" in
*-lnsl*) ;;
*) AC_CHECK_LIB(nsl_s, printf) ;;
esac
case "$LIBS" in
*-lnsl*) ;;
*) AC_CHECK_LIB(nsl, printf) ;;
esac
case "$LIBS" in
*-lsocket*) ;;
*) AC_CHECK_LIB(socket, connect) ;;
esac
case "$LIBS" in
*-linet*) ;;
*) AC_CHECK_LIB(inet, connect) ;;
esac
dnl We can't just call AC_CHECK_FUNCS(connect) here, because the value
dnl has been cached.
if test x"$ac_cv_lib_socket_connect" = x"yes" ||
test x"$ac_cv_lib_inet_connect" = x"yes"; then
# ac_cv_func_connect=yes
# don't! it would cause AC_CHECK_FUNC to succeed next time configure is run
AC_DEFINE(HAVE_CONNECT, 1, [Define to 1 if you have the "connect" function])
fi
fi
AC_SEARCH_LIBS(inet_ntop, resolv)
# For OS X, Solaris, HP-UX, etc.: figure out if -liconv is needed. We'll
# accept either iconv_open or libiconv_open, since some include files map
# the former to the latter.
AC_SEARCH_LIBS(iconv_open, iconv)
AC_SEARCH_LIBS(libiconv_open, iconv)
AC_MSG_CHECKING([for iconv declaration])
AC_CACHE_VAL(am_cv_proto_iconv, [
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include
#include
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_REPLACE_FUNCS([inet_ntop inet_pton])
AC_HAVE_TYPE([struct addrinfo], [#include ])
AC_HAVE_TYPE([struct sockaddr_storage], [#include
#include ])
# Irix 6.5 has getaddrinfo but not the corresponding defines, so use
# builtin getaddrinfo if one of the defines don't exist
AC_CACHE_CHECK([whether defines needed by getaddrinfo exist],
rsync_cv_HAVE_GETADDR_DEFINES,[
AC_EGREP_CPP(yes, [
#include
#include
#include
#ifdef AI_PASSIVE
yes
#endif],
rsync_cv_HAVE_GETADDR_DEFINES=yes,
rsync_cv_HAVE_GETADDR_DEFINES=no)])
AS_IF([test x"$rsync_cv_HAVE_GETADDR_DEFINES" = x"yes" -a x"$ac_cv_type_struct_addrinfo" = x"yes"],[
# Tru64 UNIX has getaddrinfo() but has it renamed in libc as
# something else so we must include to get the
# redefinition.
AC_CHECK_FUNCS(getaddrinfo, ,
[AC_MSG_CHECKING([for getaddrinfo by including ])
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include
#include
#include ]], [[getaddrinfo(NULL, NULL, NULL, NULL);]])],[AC_MSG_RESULT([yes])
AC_DEFINE(HAVE_GETADDRINFO, 1,
[Define to 1 if you have the "getaddrinfo" function and required types.])],[AC_MSG_RESULT([no])
AC_LIBOBJ([getaddrinfo])])])
],[AC_LIBOBJ([getaddrinfo])])
AC_CHECK_MEMBER([struct sockaddr.sa_len],
[ AC_DEFINE(HAVE_SOCKADDR_LEN, 1, [Do we have sockaddr.sa_len?]) ],
[],
[
#include
#include
])
AC_CHECK_MEMBER([struct sockaddr_in.sin_len],
[ AC_DEFINE(HAVE_SOCKADDR_IN_LEN, 1, [Do we have sockaddr_in.sin_len?]) ],
[],
[
#include
#include
#include
])
AC_CHECK_MEMBER([struct sockaddr_un.sun_len],
[ AC_DEFINE(HAVE_SOCKADDR_UN_LEN, 1, [Do we have sockaddr_un.sun_len?]) ],
[],
[
#include
#include
#include
])
AC_CHECK_MEMBER([struct sockaddr_in6.sin6_scope_id],
[ AC_DEFINE(HAVE_SOCKADDR_IN6_SCOPE_ID, 1, [Do we have sockaddr_in6.sin6_scope_id?]) ],
[],
[
#include
#include
#include
])
AC_HAVE_TYPE([struct stat64], [#include
#if HAVE_SYS_TYPES_H
# include
#endif
#if HAVE_SYS_STAT_H
# include
#endif
#if STDC_HEADERS
# include
# include
#else
# if HAVE_STDLIB_H
# include
# endif
#endif
])
# if we can't find strcasecmp, look in -lresolv (for Unixware at least)
#
AC_CHECK_FUNCS(strcasecmp)
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.
dnl AC_FUNC_MEMCMP
AC_FUNC_UTIME_NULL
AC_FUNC_ALLOCA
AC_CHECK_FUNCS(waitpid wait4 getcwd strdup chown chmod lchmod mknod mkfifo \
fchmod fstat ftruncate strchr readlink link utime utimes lutimes strftime \
memmove lchown vsnprintf snprintf vasprintf asprintf setsid strpbrk \
strlcat strlcpy strtol mallinfo getgroups setgroups geteuid getegid \
setlocale setmode open64 lseek64 mkstemp64 mtrace va_copy __va_copy \
seteuid strerror putenv iconv_open locale_charset nl_langinfo getxattr \
extattr_get_link sigaction sigprocmask setattrlist getgrouplist \
initgroups utimensat posix_fallocate attropen setvbuf usleep)
dnl cygwin iconv.h defines iconv_open as libiconv_open
if test x"$ac_cv_func_iconv_open" != x"yes"; then
AC_CHECK_FUNC(libiconv_open, [ac_cv_func_iconv_open=yes; AC_DEFINE(HAVE_ICONV_OPEN, 1)])
fi
dnl Preallocation stuff (also fallocate, posix_fallocate function tests above):
AC_CACHE_CHECK([for useable fallocate],rsync_cv_have_fallocate,[
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include
#include ]], [[fallocate(0, 0, 0, 0);]])],[rsync_cv_have_fallocate=yes],[rsync_cv_have_fallocate=no])])
if test x"$rsync_cv_have_fallocate" = x"yes"; then
AC_DEFINE(HAVE_FALLOCATE, 1, [Define to 1 if you have the fallocate function and it compiles and links without error])
fi
AC_MSG_CHECKING([for FALLOC_FL_PUNCH_HOLE])
AC_PREPROC_IFELSE([AC_LANG_SOURCE([[
#define _GNU_SOURCE 1
#include
#ifndef FALLOC_FL_PUNCH_HOLE
#error FALLOC_FL_PUNCH_HOLE is missing
#endif
]])], [
AC_MSG_RESULT([yes])
AC_DEFINE([HAVE_FALLOC_FL_PUNCH_HOLE], [1], [Define if FALLOC_FL_PUNCH_HOLE is available.])
], [
AC_MSG_RESULT([no])
]
)
AC_MSG_CHECKING([for FALLOC_FL_ZERO_RANGE])
AC_PREPROC_IFELSE([AC_LANG_SOURCE([[
#define _GNU_SOURCE 1
#include
#ifndef FALLOC_FL_ZERO_RANGE
#error FALLOC_FL_ZERO_RANGE is missing
#endif
]])], [
AC_MSG_RESULT([yes])
AC_DEFINE([HAVE_FALLOC_FL_ZERO_RANGE], [1], [Define if FALLOC_FL_ZERO_RANGE is available.])
], [
AC_MSG_RESULT([no])
]
)
AC_CACHE_CHECK([for SYS_fallocate],rsync_cv_have_sys_fallocate,[
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include
#include ]], [[syscall(SYS_fallocate, 0, 0, (loff_t)0, (loff_t)0);]])],[rsync_cv_have_sys_fallocate=yes],[rsync_cv_have_sys_fallocate=no])])
if test x"$rsync_cv_have_sys_fallocate" = x"yes"; then
AC_DEFINE(HAVE_SYS_FALLOCATE, 1, [Define to 1 if you have the SYS_fallocate syscall number])
fi
if test x"$ac_cv_func_posix_fallocate" = x"yes"; then
AC_MSG_CHECKING([whether posix_fallocate is efficient])
case $host_os in
*cygwin*)
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_EFFICIENT_POSIX_FALLOCATE, 1,
[Define if posix_fallocate is efficient (Cygwin)])
;;
*)
AC_MSG_RESULT(no)
;;
esac
fi
dnl End of preallocation stuff
AC_CHECK_FUNCS(getpgrp tcgetpgrp)
if test $ac_cv_func_getpgrp = yes; then
AC_FUNC_GETPGRP
fi
AC_ARG_ENABLE(iconv-open,
AS_HELP_STRING([--disable-iconv-open],[disable all use of iconv_open() function]),
[], [enable_iconv_open=$ac_cv_func_iconv_open])
if test x"$enable_iconv_open" != x"no"; then
AC_DEFINE(USE_ICONV_OPEN, 1, [Define to 1 if you want rsync to make use of iconv_open()])
fi
AC_ARG_ENABLE(iconv,
AS_HELP_STRING([--disable-iconv],[disable rsync's --iconv option]),
[], [enable_iconv=$enable_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_RUN_IFELSE([AC_LANG_SOURCE([[
#if HAVE_UNISTD_H
# include
#endif
#include
#include
main() {
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(1);
exit(0);
}]])],[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_RUN_IFELSE([AC_LANG_SOURCE([[
#if HAVE_UNISTD_H
# include
#endif
#include
#include
#define FILENAME "conftest.dangle"
main() {
unlink(FILENAME);
if (symlink("conftest.no-such", FILENAME) < 0) abort();
unlink(FILENAME "2");
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_RUN_IFELSE([AC_LANG_SOURCE([[
#if HAVE_UNISTD_H
# include
#endif
#include
#include
#define FILENAME "conftest.fifi"
main() {
unlink(FILENAME);
if (mkfifo(FILENAME, 0777) < 0) abort();
unlink(FILENAME "2");
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_RUN_IFELSE([AC_LANG_SOURCE([[
#include
#include
main() {
int fd[2];
exit((socketpair(AF_UNIX, SOCK_STREAM, 0, fd) != -1) ? 0 : 1);
}]])],[rsync_cv_HAVE_SOCKETPAIR=yes],[rsync_cv_HAVE_SOCKETPAIR=no],[rsync_cv_HAVE_SOCKETPAIR=cross])])
if test x"$rsync_cv_HAVE_SOCKETPAIR" = x"yes"; then
AC_DEFINE(HAVE_SOCKETPAIR, 1, [Define to 1 if you have the "socketpair" function])
fi
AC_REPLACE_FUNCS([getpass])
if test x"$with_included_popt" != x"yes"; then
AC_CHECK_LIB(popt, poptGetContext, , [with_included_popt=yes])
fi
if test x"$ac_cv_header_popt_popt_h" = x"yes"; then
# If the system has /usr/include/popt/popt.h, we enable the
# included popt because an attempt to "#include "
# would use our included header file anyway (due to -I.), and
# might conflict with the system popt.
with_included_popt=yes
elif test x"$ac_cv_header_popt_h" != x"yes"; then
with_included_popt=yes
fi
AC_MSG_CHECKING([whether to use included libpopt])
if test x"$with_included_popt" = x"yes"; then
AC_MSG_RESULT($srcdir/popt)
BUILD_POPT='$(popt_OBJS)'
CFLAGS="-I$srcdir/popt $CFLAGS"
if test x"$ALLOCA" != x
then
# this can be removed when/if we add an included alloca.c;
# see autoconf documentation on AC_FUNC_ALLOCA
AC_MSG_WARN([included libpopt will use malloc, not alloca (which wastes a small amount of memory)])
fi
else
AC_MSG_RESULT(no)
fi
# We default to not using our zlib unless --with-included-zlib=yes is given.
if test x"$with_included_zlib" != x"yes"; then
with_included_zlib=no
fi
if test x"$ac_cv_header_zlib_h" != x"yes"; then
with_included_zlib=yes
fi
if test x"$with_included_zlib" != x"yes"; then
AC_CHECK_LIB(z, deflateParams, , [with_included_zlib=yes])
fi
AC_MSG_CHECKING([whether to use included zlib])
if test x"$with_included_zlib" = x"yes"; then
AC_MSG_RESULT($srcdir/zlib)
BUILD_ZLIB='$(zlib_OBJS)'
CFLAGS="-I$srcdir/zlib $CFLAGS"
else
AC_DEFINE(EXTERNAL_ZLIB, 1, [Define to 1 if using external zlib])
AC_MSG_RESULT(no)
fi
AC_CACHE_CHECK([for unsigned char],rsync_cv_SIGNED_CHAR_OK,[
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[signed char *s = ""]])],[rsync_cv_SIGNED_CHAR_OK=yes],[rsync_cv_SIGNED_CHAR_OK=no])])
if test x"$rsync_cv_SIGNED_CHAR_OK" = x"yes"; then
AC_DEFINE(SIGNED_CHAR_OK, 1, [Define to 1 if "signed char" is a valid type])
fi
AC_CACHE_CHECK([for broken readdir],rsync_cv_HAVE_BROKEN_READDIR,[
AC_RUN_IFELSE([AC_LANG_SOURCE([[#include
#include
main() { struct dirent *di; DIR *d = opendir("."); di = readdir(d);
if (di && di->d_name[-2] == '.' && di->d_name[-1] == 0 &&
di->d_name[0] == 0) exit(0); exit(1);} ]])],[rsync_cv_HAVE_BROKEN_READDIR=yes],[rsync_cv_HAVE_BROKEN_READDIR=no],[rsync_cv_HAVE_BROKEN_READDIR=cross])])
if test x"$rsync_cv_HAVE_BROKEN_READDIR" = x"yes"; then
AC_DEFINE(HAVE_BROKEN_READDIR, 1, [Define to 1 if readdir() is broken])
fi
AC_CACHE_CHECK([for utimbuf],rsync_cv_HAVE_STRUCT_UTIMBUF,[
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include
#include ]], [[struct utimbuf tbuf; tbuf.actime = 0; tbuf.modtime = 1; exit(utime("foo.c",&tbuf));]])],[rsync_cv_HAVE_STRUCT_UTIMBUF=yes],[rsync_cv_HAVE_STRUCT_UTIMBUF=no])])
if test x"$rsync_cv_HAVE_STRUCT_UTIMBUF" = x"yes"; then
AC_DEFINE(HAVE_STRUCT_UTIMBUF, 1, [Define to 1 if you have the "struct utimbuf" type])
fi
AC_CACHE_CHECK([if gettimeofday takes tz argument],rsync_cv_HAVE_GETTIMEOFDAY_TZ,[
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include
#include ]], [[struct timeval tv; exit(gettimeofday(&tv, NULL));]])],[rsync_cv_HAVE_GETTIMEOFDAY_TZ=yes],[rsync_cv_HAVE_GETTIMEOFDAY_TZ=no])])
if test x"$rsync_cv_HAVE_GETTIMEOFDAY_TZ" != x"no"; then
AC_DEFINE(HAVE_GETTIMEOFDAY_TZ, 1, [Define to 1 if gettimeofday() takes a time-zone arg])
fi
AC_CACHE_CHECK([for C99 vsnprintf],rsync_cv_HAVE_C99_VSNPRINTF,[
AC_RUN_IFELSE([AC_LANG_SOURCE([[
#include
#include
void foo(const char *format, ...) {
va_list ap;
int len;
char buf[5];
va_start(ap, format);
len = vsnprintf(0, 0, format, ap);
va_end(ap);
if (len != 5) exit(1);
if (snprintf(buf, 3, "hello") != 5 || strcmp(buf, "he") != 0) exit(1);
exit(0);
}
main() { foo("hello"); }
]])],[rsync_cv_HAVE_C99_VSNPRINTF=yes],[rsync_cv_HAVE_C99_VSNPRINTF=no],[rsync_cv_HAVE_C99_VSNPRINTF=cross])])
if test x"$rsync_cv_HAVE_C99_VSNPRINTF" = x"yes"; then
AC_DEFINE(HAVE_C99_VSNPRINTF, 1, [Define to 1 if vsprintf has a C99-compatible return value])
fi
AC_CACHE_CHECK([for secure mkstemp],rsync_cv_HAVE_SECURE_MKSTEMP,[
AC_RUN_IFELSE([AC_LANG_SOURCE([[#include
#include
#include
#include
main() {
struct stat st;
char tpl[20]="/tmp/test.XXXXXX";
int fd = mkstemp(tpl);
if (fd == -1) exit(1);
unlink(tpl);
if (fstat(fd, &st) != 0) exit(1);
if ((st.st_mode & 0777) != 0600) exit(1);
exit(0);
}]])],[rsync_cv_HAVE_SECURE_MKSTEMP=yes],[rsync_cv_HAVE_SECURE_MKSTEMP=no],[rsync_cv_HAVE_SECURE_MKSTEMP=cross])])
if test x"$rsync_cv_HAVE_SECURE_MKSTEMP" = x"yes"; then
case $host_os in
hpux*)
dnl HP-UX has a broken mkstemp() implementation they refuse to fix,
dnl so we noisily skip using it. See HP change request JAGaf34426
dnl for details. (sbonds)
AC_MSG_WARN(Skipping broken HP-UX mkstemp() -- using mktemp() instead)
;;
*)
AC_DEFINE(HAVE_SECURE_MKSTEMP, 1, [Define to 1 if mkstemp() is available and works right])
;;
esac
fi
AC_CACHE_CHECK([if mknod creates FIFOs],rsync_cv_MKNOD_CREATES_FIFOS,[
AC_RUN_IFELSE([AC_LANG_SOURCE([[
#include
#include
#include
main() { int rc, ec; char *fn = "fifo-test";
unlink(fn); rc = mknod(fn,S_IFIFO,0600); ec = errno; unlink(fn);
if (rc) {printf("(%d %d) ",rc,ec); return ec;}
return 0;}]])],[rsync_cv_MKNOD_CREATES_FIFOS=yes],[rsync_cv_MKNOD_CREATES_FIFOS=no],[rsync_cv_MKNOD_CREATES_FIFOS=cross])])
if test x"$rsync_cv_MKNOD_CREATES_FIFOS" = x"yes"; then
AC_DEFINE(MKNOD_CREATES_FIFOS, 1, [Define to 1 if mknod() can create FIFOs.])
fi
AC_CACHE_CHECK([if mknod creates sockets],rsync_cv_MKNOD_CREATES_SOCKETS,[
AC_RUN_IFELSE([AC_LANG_SOURCE([[
#include
#include
#include
main() { int rc, ec; char *fn = "sock-test";
unlink(fn); rc = mknod(fn,S_IFSOCK,0600); ec = errno; unlink(fn);
if (rc) {printf("(%d %d) ",rc,ec); return ec;}
return 0;}]])],[rsync_cv_MKNOD_CREATES_SOCKETS=yes],[rsync_cv_MKNOD_CREATES_SOCKETS=no],[rsync_cv_MKNOD_CREATES_SOCKETS=cross])])
if test x"$rsync_cv_MKNOD_CREATES_SOCKETS" = x"yes"; then
AC_DEFINE(MKNOD_CREATES_SOCKETS, 1, [Define to 1 if mknod() can create sockets.])
fi
#
# The following test was mostly taken from the tcl/tk plus patches
#
AC_CACHE_CHECK([whether -c -o works],rsync_cv_DASHC_WORKS_WITH_DASHO,[
rm -rf conftest*
cat > conftest.$ac_ext <
#include ]], [[ 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_LINK_IFELSE([AC_LANG_PROGRAM([[#include
#include ]], [[ 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
#################################################
# check for extended attribute support
AC_MSG_CHECKING(whether to support extended attributes)
AC_ARG_ENABLE(xattr-support,
AS_HELP_STRING([--disable-xattr-support],[disable extended attributes]),
[], [case "$ac_cv_func_getxattr$ac_cv_func_extattr_get_link$ac_cv_func_attropen" 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*|*netbsd*)
AC_MSG_RESULT(Using Linux xattrs)
AC_DEFINE(HAVE_LINUX_XATTRS, 1, [True if you have Linux xattrs (or equivalent)])
AC_DEFINE(SUPPORT_XATTRS, 1)
AC_DEFINE(NO_SYMLINK_USER_XATTRS, 1, [True if symlinks do not support user xattrs])
AC_CHECK_LIB(attr,getxattr)
;;
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)
AC_DEFINE(NO_DEVICE_XATTRS, 1, [True if device files do not support xattrs])
AC_DEFINE(NO_SPECIAL_XATTRS, 1, [True if special files do not support xattrs])
;;
freebsd*)
AC_MSG_RESULT(Using FreeBSD extattrs)
AC_DEFINE(HAVE_FREEBSD_XATTRS, 1, [True if you have FreeBSD xattrs])
AC_DEFINE(SUPPORT_XATTRS, 1)
;;
solaris*)
AC_MSG_RESULT(Using Solaris xattrs)
AC_DEFINE(HAVE_SOLARIS_XATTRS, 1, [True if you have Solaris xattrs])
AC_DEFINE(SUPPORT_XATTRS, 1)
AC_DEFINE(NO_SYMLINK_XATTRS, 1, [True if symlinks do not support xattrs])
;;
*)
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
if test x"$enable_acl_support" = x"no" -o x"$enable_xattr_support" = x"no" -o x"$enable_iconv" = x"no"; then
AC_MSG_CHECKING([whether $CC supports -Wno-unused-parameter])
OLD_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -Wno-unused-parameter"
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], [[printf("hello\n");]])],[rsync_warn_flag=yes],[rsync_warn_flag=no])
AC_MSG_RESULT([$rsync_warn_flag])
if test x"$rsync_warn_flag" = x"no"; then
CFLAGS="$OLD_CFLAGS"
fi
fi
case "$CC" in
' checker'*|checker*)
AC_DEFINE(FORCE_FD_ZERO_MEMSET, 1, [Used to make "checker" understand that FD_ZERO() clears memory.])
;;
esac
AC_CONFIG_FILES([Makefile lib/dummy zlib/dummy popt/dummy shconfig])
AC_OUTPUT
AC_MSG_RESULT()
AC_MSG_RESULT([ rsync_bpc ${RSYNC_VERSION} configuration successful])
AC_MSG_RESULT()
rsync-bpc-3.1.3.0/configure.sh 0000775 0000000 0000000 00001056721 13737671777 0016141 0 ustar 00root root 0000000 0000000 #! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for rsync-bpc 3.1.3.0.
#
# Report bugs to .
#
#
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
#
#
# This configure script is free software; the Free Software Foundation
# gives unlimited permission to copy, distribute and modify it.
## -------------------- ##
## M4sh Initialization. ##
## -------------------- ##
# Be more Bourne compatible
DUALCASE=1; export DUALCASE # for MKS sh
if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
emulate sh
NULLCMD=:
# Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
# is contrary to our usage. Disable this feature.
alias -g '${1+"$@"}'='"$@"'
setopt NO_GLOB_SUBST
else
case `(set -o) 2>/dev/null` in #(
*posix*) :
set -o posix ;; #(
*) :
;;
esac
fi
as_nl='
'
export as_nl
# Printing a long string crashes Solaris 7 /usr/bin/printf.
as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
# Prefer a ksh shell builtin over an external printf program on Solaris,
# but without wasting forks for bash or zsh.
if test -z "$BASH_VERSION$ZSH_VERSION" \
&& (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
as_echo='print -r --'
as_echo_n='print -rn --'
elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
as_echo='printf %s\n'
as_echo_n='printf %s'
else
if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
as_echo_n='/usr/ucb/echo -n'
else
as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
as_echo_n_body='eval
arg=$1;
case $arg in #(
*"$as_nl"*)
expr "X$arg" : "X\\(.*\\)$as_nl";
arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
esac;
expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
'
export as_echo_n_body
as_echo_n='sh -c $as_echo_n_body as_echo'
fi
export as_echo_body
as_echo='sh -c $as_echo_body as_echo'
fi
# The user is always right.
if test "${PATH_SEPARATOR+set}" != set; then
PATH_SEPARATOR=:
(PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
(PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
PATH_SEPARATOR=';'
}
fi
# IFS
# We need space, tab and new line, in precisely that order. Quoting is
# there to prevent editors from complaining about space-tab.
# (If _AS_PATH_WALK were called with IFS unset, it would disable word
# splitting by setting IFS to empty value.)
IFS=" "" $as_nl"
# Find who we are. Look in the path if we contain no directory separator.
as_myself=
case $0 in #((
*[\\/]* ) as_myself=$0 ;;
*) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
done
IFS=$as_save_IFS
;;
esac
# We did not find ourselves, most probably we were run as `sh COMMAND'
# in which case we are not to be found in the path.
if test "x$as_myself" = x; then
as_myself=$0
fi
if test ! -f "$as_myself"; then
$as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
exit 1
fi
# Unset variables that we do not need and which cause bugs (e.g. in
# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
# suppresses any "Segmentation fault" message there. '((' could
# trigger a bug in pdksh 5.2.14.
for as_var in BASH_ENV ENV MAIL MAILPATH
do eval test x\${$as_var+set} = xset \
&& ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
done
PS1='$ '
PS2='> '
PS4='+ '
# NLS nuisances.
LC_ALL=C
export LC_ALL
LANGUAGE=C
export LANGUAGE
# CDPATH.
(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
# Use a proper internal environment variable to ensure we don't fall
# into an infinite loop, continuously re-executing ourselves.
if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
_as_can_reexec=no; export _as_can_reexec;
# We cannot yet assume a decent shell, so we have to provide a
# neutralization value for shells without unset; and this also
# works around shells that cannot unset nonexistent variables.
# Preserve -v and -x to the replacement shell.
BASH_ENV=/dev/null
ENV=/dev/null
(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
case $- in # ((((
*v*x* | *x*v* ) as_opts=-vx ;;
*v* ) as_opts=-v ;;
*x* ) as_opts=-x ;;
* ) as_opts= ;;
esac
exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
# Admittedly, this is quite paranoid, since all the known shells bail
# out after a failed `exec'.
$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
as_fn_exit 255
fi
# We don't want this to propagate to other subprocesses.
{ _as_can_reexec=; unset _as_can_reexec;}
if test "x$CONFIG_SHELL" = x; then
as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
emulate sh
NULLCMD=:
# Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
# is contrary to our usage. Disable this feature.
alias -g '\${1+\"\$@\"}'='\"\$@\"'
setopt NO_GLOB_SUBST
else
case \`(set -o) 2>/dev/null\` in #(
*posix*) :
set -o posix ;; #(
*) :
;;
esac
fi
"
as_required="as_fn_return () { (exit \$1); }
as_fn_success () { as_fn_return 0; }
as_fn_failure () { as_fn_return 1; }
as_fn_ret_success () { return 0; }
as_fn_ret_failure () { return 1; }
exitcode=0
as_fn_success || { exitcode=1; echo as_fn_success failed.; }
as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
else
exitcode=1; echo positional parameters were not saved.
fi
test x\$exitcode = x0 || exit 1
test -x / || exit 1"
as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
test \$(( 1 + 1 )) = 2 || exit 1"
if (eval "$as_required") 2>/dev/null; then :
as_have_required=yes
else
as_have_required=no
fi
if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
as_found=false
for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
as_found=:
case $as_dir in #(
/*)
for as_base in sh bash ksh sh5; do
# Try only shells that exist, to save several forks.
as_shell=$as_dir/$as_base
if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
{ $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
CONFIG_SHELL=$as_shell as_have_required=yes
if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
break 2
fi
fi
done;;
esac
as_found=false
done
$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
{ $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
CONFIG_SHELL=$SHELL as_have_required=yes
fi; }
IFS=$as_save_IFS
if test "x$CONFIG_SHELL" != x; then :
export CONFIG_SHELL
# We cannot yet assume a decent shell, so we have to provide a
# neutralization value for shells without unset; and this also
# works around shells that cannot unset nonexistent variables.
# Preserve -v and -x to the replacement shell.
BASH_ENV=/dev/null
ENV=/dev/null
(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
case $- in # ((((
*v*x* | *x*v* ) as_opts=-vx ;;
*v* ) as_opts=-v ;;
*x* ) as_opts=-x ;;
* ) as_opts= ;;
esac
exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
# Admittedly, this is quite paranoid, since all the known shells bail
# out after a failed `exec'.
$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
exit 255
fi
if test x$as_have_required = xno; then :
$as_echo "$0: This script requires a shell more modern than all"
$as_echo "$0: the shells that I found on your system."
if test x${ZSH_VERSION+set} = xset ; then
$as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
$as_echo "$0: be upgraded to zsh 4.3.4 or later."
else
$as_echo "$0: Please tell bug-autoconf@gnu.org and
$0: https://github.com/backuppc/rsync-bpc/issues about your
$0: system, including any error possibly output before this
$0: message. Then install a modern shell, or manually run
$0: the script under such a shell if you do have one."
fi
exit 1
fi
fi
fi
SHELL=${CONFIG_SHELL-/bin/sh}
export SHELL
# Unset more variables known to interfere with behavior of common tools.
CLICOLOR_FORCE= GREP_OPTIONS=
unset CLICOLOR_FORCE GREP_OPTIONS
## --------------------- ##
## M4sh Shell Functions. ##
## --------------------- ##
# as_fn_unset VAR
# ---------------
# Portably unset VAR.
as_fn_unset ()
{
{ eval $1=; unset $1;}
}
as_unset=as_fn_unset
# as_fn_set_status STATUS
# -----------------------
# Set $? to STATUS, without forking.
as_fn_set_status ()
{
return $1
} # as_fn_set_status
# as_fn_exit STATUS
# -----------------
# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
as_fn_exit ()
{
set +e
as_fn_set_status $1
exit $1
} # as_fn_exit
# as_fn_mkdir_p
# -------------
# Create "$as_dir" as a directory, including parents if necessary.
as_fn_mkdir_p ()
{
case $as_dir in #(
-*) as_dir=./$as_dir;;
esac
test -d "$as_dir" || eval $as_mkdir_p || {
as_dirs=
while :; do
case $as_dir in #(
*\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
*) as_qdir=$as_dir;;
esac
as_dirs="'$as_qdir' $as_dirs"
as_dir=`$as_dirname -- "$as_dir" ||
$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$as_dir" : 'X\(//\)[^/]' \| \
X"$as_dir" : 'X\(//\)$' \| \
X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
$as_echo X"$as_dir" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
}
/^X\(\/\/\)[^/].*/{
s//\1/
q
}
/^X\(\/\/\)$/{
s//\1/
q
}
/^X\(\/\).*/{
s//\1/
q
}
s/.*/./; q'`
test -d "$as_dir" && break
done
test -z "$as_dirs" || eval "mkdir $as_dirs"
} || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
} # as_fn_mkdir_p
# as_fn_executable_p FILE
# -----------------------
# Test if FILE is an executable regular file.
as_fn_executable_p ()
{
test -f "$1" && test -x "$1"
} # as_fn_executable_p
# as_fn_append VAR VALUE
# ----------------------
# Append the text in VALUE to the end of the definition contained in VAR. Take
# advantage of any shell optimizations that allow amortized linear growth over
# repeated appends, instead of the typical quadratic growth present in naive
# implementations.
if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
eval 'as_fn_append ()
{
eval $1+=\$2
}'
else
as_fn_append ()
{
eval $1=\$$1\$2
}
fi # as_fn_append
# as_fn_arith ARG...
# ------------------
# Perform arithmetic evaluation on the ARGs, and store the result in the
# global $as_val. Take advantage of shells that can avoid forks. The arguments
# must be portable across $(()) and expr.
if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
eval 'as_fn_arith ()
{
as_val=$(( $* ))
}'
else
as_fn_arith ()
{
as_val=`expr "$@" || test $? -eq 1`
}
fi # as_fn_arith
# as_fn_error STATUS ERROR [LINENO LOG_FD]
# ----------------------------------------
# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
# script with STATUS, using 1 if that was 0.
as_fn_error ()
{
as_status=$1; test $as_status -eq 0 && as_status=1
if test "$4"; then
as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
$as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
fi
$as_echo "$as_me: error: $2" >&2
as_fn_exit $as_status
} # as_fn_error
if expr a : '\(a\)' >/dev/null 2>&1 &&
test "X`expr 00001 : '.*\(...\)'`" = X001; then
as_expr=expr
else
as_expr=false
fi
if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
as_basename=basename
else
as_basename=false
fi
if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
as_dirname=dirname
else
as_dirname=false
fi
as_me=`$as_basename -- "$0" ||
$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
X"$0" : 'X\(//\)$' \| \
X"$0" : 'X\(/\)' \| . 2>/dev/null ||
$as_echo X/"$0" |
sed '/^.*\/\([^/][^/]*\)\/*$/{
s//\1/
q
}
/^X\/\(\/\/\)$/{
s//\1/
q
}
/^X\/\(\/\).*/{
s//\1/
q
}
s/.*/./; q'`
# Avoid depending upon Character Ranges.
as_cr_letters='abcdefghijklmnopqrstuvwxyz'
as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
as_cr_Letters=$as_cr_letters$as_cr_LETTERS
as_cr_digits='0123456789'
as_cr_alnum=$as_cr_Letters$as_cr_digits
as_lineno_1=$LINENO as_lineno_1a=$LINENO
as_lineno_2=$LINENO as_lineno_2a=$LINENO
eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
# Blame Lee E. McMahon (1931-1989) for sed's syntax. :-)
sed -n '
p
/[$]LINENO/=
' <$as_myself |
sed '
s/[$]LINENO.*/&-/
t lineno
b
:lineno
N
:loop
s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
t loop
s/-\n.*//
' >$as_me.lineno &&
chmod +x "$as_me.lineno" ||
{ $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
# If we had to re-execute with $CONFIG_SHELL, we're ensured to have
# already done that, so ensure we don't try to do so again and fall
# in an infinite loop. This has already happened in practice.
_as_can_reexec=no; export _as_can_reexec
# Don't try to exec as it changes $[0], causing all sort of problems
# (the dirname of $[0] is not the place where we might find the
# original and so on. Autoconf is especially sensitive to this).
. "./$as_me.lineno"
# Exit status is that of the last command.
exit
}
ECHO_C= ECHO_N= ECHO_T=
case `echo -n x` in #(((((
-n*)
case `echo 'xy\c'` in
*c*) ECHO_T=' ';; # ECHO_T is single tab character.
xy) ECHO_C='\c';;
*) echo `echo ksh88 bug on AIX 6.1` > /dev/null
ECHO_T=' ';;
esac;;
*)
ECHO_N='-n';;
esac
rm -f conf$$ conf$$.exe conf$$.file
if test -d conf$$.dir; then
rm -f conf$$.dir/conf$$.file
else
rm -f conf$$.dir
mkdir conf$$.dir 2>/dev/null
fi
if (echo >conf$$.file) 2>/dev/null; then
if ln -s conf$$.file conf$$ 2>/dev/null; then
as_ln_s='ln -s'
# ... but there are two gotchas:
# 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
# 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
# In both cases, we have to default to `cp -pR'.
ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
as_ln_s='cp -pR'
elif ln conf$$.file conf$$ 2>/dev/null; then
as_ln_s=ln
else
as_ln_s='cp -pR'
fi
else
as_ln_s='cp -pR'
fi
rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
rmdir conf$$.dir 2>/dev/null
if mkdir -p . 2>/dev/null; then
as_mkdir_p='mkdir -p "$as_dir"'
else
test -d ./-p && rmdir ./-p
as_mkdir_p=false
fi
as_test_x='test -x'
as_executable_p=as_fn_executable_p
# Sed expression to map a string onto a valid CPP name.
as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
# Sed expression to map a string onto a valid variable name.
as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
test -n "$DJDIR" || exec 7<&0 &1
# Name of the host.
# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
# so uname gets run too.
ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
#
# Initializations.
#
ac_default_prefix=/usr/local
ac_clean_files=
ac_config_libobj_dir=.
LIBOBJS=
cross_compiling=no
subdirs=
MFLAGS=
MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='rsync-bpc'
PACKAGE_TARNAME='rsync-bpc'
PACKAGE_VERSION='3.1.3.0'
PACKAGE_STRING='rsync-bpc 3.1.3.0'
PACKAGE_BUGREPORT='https://github.com/backuppc/rsync-bpc/issues'
PACKAGE_URL=''
ac_unique_file="byteorder.h"
ac_config_libobj_dir=lib
# Factoring default headers for most tests.
ac_includes_default="\
#include
#ifdef HAVE_SYS_TYPES_H
# include
#endif
#ifdef HAVE_SYS_STAT_H
# include
#endif
#ifdef STDC_HEADERS
# include
# include
#else
# ifdef HAVE_STDLIB_H
# include
# endif
#endif
#ifdef HAVE_STRING_H
# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
# include
# endif
# include
#endif
#ifdef HAVE_STRINGS_H
# include
#endif
#ifdef HAVE_INTTYPES_H
# include
#endif
#ifdef HAVE_STDINT_H
# include
#endif
#ifdef HAVE_UNISTD_H
# include
#endif"
ac_header_list=
ac_subst_vars='LTLIBOBJS
STUNNEL4
STUNNEL
MAKE_MAN
BUILD_ZLIB
BUILD_POPT
CC_SHOBJ_FLAG
OBJ_RESTORE
OBJ_SAVE
ALLOCA
LIBOBJS
FAKEROOT_PATH
SHELL_PATH
HAVE_YODL2MAN
HAVE_REMSH
PERL
MKDIR_P
INSTALL_DATA
INSTALL_SCRIPT
INSTALL_PROGRAM
EGREP
GREP
CPP
OBJEXT
EXEEXT
ac_ct_CC
CPPFLAGS
LDFLAGS
CFLAGS
CC
host_os
host_vendor
host_cpu
host
build_os
build_vendor
build_cpu
build
RSYNC_VERSION
target_alias
host_alias
build_alias
LIBS
ECHO_T
ECHO_N
ECHO_C
DEFS
mandir
localedir
libdir
psdir
pdfdir
dvidir
htmldir
infodir
docdir
oldincludedir
includedir
runstatedir
localstatedir
sharedstatedir
sysconfdir
datadir
datarootdir
libexecdir
sbindir
bindir
program_transform_name
prefix
exec_prefix
PACKAGE_URL
PACKAGE_BUGREPORT
PACKAGE_STRING
PACKAGE_VERSION
PACKAGE_TARNAME
PACKAGE_NAME
PATH_SEPARATOR
SHELL'
ac_subst_files=''
ac_user_opts='
enable_option_checking
enable_debug
enable_profile
enable_maintainer_mode
with_included_popt
with_included_zlib
with_protected_args
with_rsync_path
with_rsyncd_conf
with_rsh
with_nobody_group
enable_largefile
enable_ipv6
enable_locale
enable_iconv_open
enable_iconv
enable_acl_support
enable_xattr_support
'
ac_precious_vars='build_alias
host_alias
target_alias
CC
CFLAGS
LDFLAGS
LIBS
CPPFLAGS
CPP'
# Initialize some variables set by options.
ac_init_help=
ac_init_version=false
ac_unrecognized_opts=
ac_unrecognized_sep=
# The variables have the same names as the options, with
# dashes changed to underlines.
cache_file=/dev/null
exec_prefix=NONE
no_create=
no_recursion=
prefix=NONE
program_prefix=NONE
program_suffix=NONE
program_transform_name=s,x,x,
silent=
site=
srcdir=
verbose=
x_includes=NONE
x_libraries=NONE
# Installation directory options.
# These are left unexpanded so users can "make install exec_prefix=/foo"
# and all the variables that are supposed to be based on exec_prefix
# by default will actually change.
# Use braces instead of parens because sh, perl, etc. also accept them.
# (The list follows the same order as the GNU Coding Standards.)
bindir='${exec_prefix}/bin'
sbindir='${exec_prefix}/sbin'
libexecdir='${exec_prefix}/libexec'
datarootdir='${prefix}/share'
datadir='${datarootdir}'
sysconfdir='${prefix}/etc'
sharedstatedir='${prefix}/com'
localstatedir='${prefix}/var'
runstatedir='${localstatedir}/run'
includedir='${prefix}/include'
oldincludedir='/usr/include'
docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
infodir='${datarootdir}/info'
htmldir='${docdir}'
dvidir='${docdir}'
pdfdir='${docdir}'
psdir='${docdir}'
libdir='${exec_prefix}/lib'
localedir='${datarootdir}/locale'
mandir='${datarootdir}/man'
ac_prev=
ac_dashdash=
for ac_option
do
# If the previous option needs an argument, assign it.
if test -n "$ac_prev"; then
eval $ac_prev=\$ac_option
ac_prev=
continue
fi
case $ac_option in
*=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
*=) ac_optarg= ;;
*) ac_optarg=yes ;;
esac
# Accept the important Cygnus configure options, so we can diagnose typos.
case $ac_dashdash$ac_option in
--)
ac_dashdash=yes ;;
-bindir | --bindir | --bindi | --bind | --bin | --bi)
ac_prev=bindir ;;
-bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
bindir=$ac_optarg ;;
-build | --build | --buil | --bui | --bu)
ac_prev=build_alias ;;
-build=* | --build=* | --buil=* | --bui=* | --bu=*)
build_alias=$ac_optarg ;;
-cache-file | --cache-file | --cache-fil | --cache-fi \
| --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
ac_prev=cache_file ;;
-cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
| --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
cache_file=$ac_optarg ;;
--config-cache | -C)
cache_file=config.cache ;;
-datadir | --datadir | --datadi | --datad)
ac_prev=datadir ;;
-datadir=* | --datadir=* | --datadi=* | --datad=*)
datadir=$ac_optarg ;;
-datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
| --dataroo | --dataro | --datar)
ac_prev=datarootdir ;;
-datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
| --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
datarootdir=$ac_optarg ;;
-disable-* | --disable-*)
ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
as_fn_error $? "invalid feature name: $ac_useropt"
ac_useropt_orig=$ac_useropt
ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
*"
"enable_$ac_useropt"
"*) ;;
*) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
ac_unrecognized_sep=', ';;
esac
eval enable_$ac_useropt=no ;;
-docdir | --docdir | --docdi | --doc | --do)
ac_prev=docdir ;;
-docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
docdir=$ac_optarg ;;
-dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
ac_prev=dvidir ;;
-dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
dvidir=$ac_optarg ;;
-enable-* | --enable-*)
ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
as_fn_error $? "invalid feature name: $ac_useropt"
ac_useropt_orig=$ac_useropt
ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
*"
"enable_$ac_useropt"
"*) ;;
*) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
ac_unrecognized_sep=', ';;
esac
eval enable_$ac_useropt=\$ac_optarg ;;
-exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
| --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
| --exec | --exe | --ex)
ac_prev=exec_prefix ;;
-exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
| --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
| --exec=* | --exe=* | --ex=*)
exec_prefix=$ac_optarg ;;
-gas | --gas | --ga | --g)
# Obsolete; use --with-gas.
with_gas=yes ;;
-help | --help | --hel | --he | -h)
ac_init_help=long ;;
-help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
ac_init_help=recursive ;;
-help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
ac_init_help=short ;;
-host | --host | --hos | --ho)
ac_prev=host_alias ;;
-host=* | --host=* | --hos=* | --ho=*)
host_alias=$ac_optarg ;;
-htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
ac_prev=htmldir ;;
-htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
| --ht=*)
htmldir=$ac_optarg ;;
-includedir | --includedir | --includedi | --included | --include \
| --includ | --inclu | --incl | --inc)
ac_prev=includedir ;;
-includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
| --includ=* | --inclu=* | --incl=* | --inc=*)
includedir=$ac_optarg ;;
-infodir | --infodir | --infodi | --infod | --info | --inf)
ac_prev=infodir ;;
-infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
infodir=$ac_optarg ;;
-libdir | --libdir | --libdi | --libd)
ac_prev=libdir ;;
-libdir=* | --libdir=* | --libdi=* | --libd=*)
libdir=$ac_optarg ;;
-libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
| --libexe | --libex | --libe)
ac_prev=libexecdir ;;
-libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
| --libexe=* | --libex=* | --libe=*)
libexecdir=$ac_optarg ;;
-localedir | --localedir | --localedi | --localed | --locale)
ac_prev=localedir ;;
-localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
localedir=$ac_optarg ;;
-localstatedir | --localstatedir | --localstatedi | --localstated \
| --localstate | --localstat | --localsta | --localst | --locals)
ac_prev=localstatedir ;;
-localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
| --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
localstatedir=$ac_optarg ;;
-mandir | --mandir | --mandi | --mand | --man | --ma | --m)
ac_prev=mandir ;;
-mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
mandir=$ac_optarg ;;
-nfp | --nfp | --nf)
# Obsolete; use --without-fp.
with_fp=no ;;
-no-create | --no-create | --no-creat | --no-crea | --no-cre \
| --no-cr | --no-c | -n)
no_create=yes ;;
-no-recursion | --no-recursion | --no-recursio | --no-recursi \
| --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
no_recursion=yes ;;
-oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
| --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
| --oldin | --oldi | --old | --ol | --o)
ac_prev=oldincludedir ;;
-oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
| --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
| --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
oldincludedir=$ac_optarg ;;
-prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
ac_prev=prefix ;;
-prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
prefix=$ac_optarg ;;
-program-prefix | --program-prefix | --program-prefi | --program-pref \
| --program-pre | --program-pr | --program-p)
ac_prev=program_prefix ;;
-program-prefix=* | --program-prefix=* | --program-prefi=* \
| --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
program_prefix=$ac_optarg ;;
-program-suffix | --program-suffix | --program-suffi | --program-suff \
| --program-suf | --program-su | --program-s)
ac_prev=program_suffix ;;
-program-suffix=* | --program-suffix=* | --program-suffi=* \
| --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
program_suffix=$ac_optarg ;;
-program-transform-name | --program-transform-name \
| --program-transform-nam | --program-transform-na \
| --program-transform-n | --program-transform- \
| --program-transform | --program-transfor \
| --program-transfo | --program-transf \
| --program-trans | --program-tran \
| --progr-tra | --program-tr | --program-t)
ac_prev=program_transform_name ;;
-program-transform-name=* | --program-transform-name=* \
| --program-transform-nam=* | --program-transform-na=* \
| --program-transform-n=* | --program-transform-=* \
| --program-transform=* | --program-transfor=* \
| --program-transfo=* | --program-transf=* \
| --program-trans=* | --program-tran=* \
| --progr-tra=* | --program-tr=* | --program-t=*)
program_transform_name=$ac_optarg ;;
-pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
ac_prev=pdfdir ;;
-pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
pdfdir=$ac_optarg ;;
-psdir | --psdir | --psdi | --psd | --ps)
ac_prev=psdir ;;
-psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
psdir=$ac_optarg ;;
-q | -quiet | --quiet | --quie | --qui | --qu | --q \
| -silent | --silent | --silen | --sile | --sil)
silent=yes ;;
-runstatedir | --runstatedir | --runstatedi | --runstated \
| --runstate | --runstat | --runsta | --runst | --runs \
| --run | --ru | --r)
ac_prev=runstatedir ;;
-runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
| --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
| --run=* | --ru=* | --r=*)
runstatedir=$ac_optarg ;;
-sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
ac_prev=sbindir ;;
-sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
| --sbi=* | --sb=*)
sbindir=$ac_optarg ;;
-sharedstatedir | --sharedstatedir | --sharedstatedi \
| --sharedstated | --sharedstate | --sharedstat | --sharedsta \
| --sharedst | --shareds | --shared | --share | --shar \
| --sha | --sh)
ac_prev=sharedstatedir ;;
-sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
| --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
| --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
| --sha=* | --sh=*)
sharedstatedir=$ac_optarg ;;
-site | --site | --sit)
ac_prev=site ;;
-site=* | --site=* | --sit=*)
site=$ac_optarg ;;
-srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
ac_prev=srcdir ;;
-srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
srcdir=$ac_optarg ;;
-sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
| --syscon | --sysco | --sysc | --sys | --sy)
ac_prev=sysconfdir ;;
-sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
| --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
sysconfdir=$ac_optarg ;;
-target | --target | --targe | --targ | --tar | --ta | --t)
ac_prev=target_alias ;;
-target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
target_alias=$ac_optarg ;;
-v | -verbose | --verbose | --verbos | --verbo | --verb)
verbose=yes ;;
-version | --version | --versio | --versi | --vers | -V)
ac_init_version=: ;;
-with-* | --with-*)
ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
as_fn_error $? "invalid package name: $ac_useropt"
ac_useropt_orig=$ac_useropt
ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
*"
"with_$ac_useropt"
"*) ;;
*) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
ac_unrecognized_sep=', ';;
esac
eval with_$ac_useropt=\$ac_optarg ;;
-without-* | --without-*)
ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
as_fn_error $? "invalid package name: $ac_useropt"
ac_useropt_orig=$ac_useropt
ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
*"
"with_$ac_useropt"
"*) ;;
*) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
ac_unrecognized_sep=', ';;
esac
eval with_$ac_useropt=no ;;
--x)
# Obsolete; use --with-x.
with_x=yes ;;
-x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
| --x-incl | --x-inc | --x-in | --x-i)
ac_prev=x_includes ;;
-x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
| --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
x_includes=$ac_optarg ;;
-x-libraries | --x-libraries | --x-librarie | --x-librari \
| --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
ac_prev=x_libraries ;;
-x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
| --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
x_libraries=$ac_optarg ;;
-*) as_fn_error $? "unrecognized option: \`$ac_option'
Try \`$0 --help' for more information"
;;
*=*)
ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
# Reject names that are not valid shell variable names.
case $ac_envvar in #(
'' | [0-9]* | *[!_$as_cr_alnum]* )
as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
esac
eval $ac_envvar=\$ac_optarg
export $ac_envvar ;;
*)
# FIXME: should be removed in autoconf 3.0.
$as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
$as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
: "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
;;
esac
done
if test -n "$ac_prev"; then
ac_option=--`echo $ac_prev | sed 's/_/-/g'`
as_fn_error $? "missing argument to $ac_option"
fi
if test -n "$ac_unrecognized_opts"; then
case $enable_option_checking in
no) ;;
fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
*) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
esac
fi
# Check all directory arguments for consistency.
for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
datadir sysconfdir sharedstatedir localstatedir includedir \
oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
libdir localedir mandir runstatedir
do
eval ac_val=\$$ac_var
# Remove trailing slashes.
case $ac_val in
*/ )
ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
eval $ac_var=\$ac_val;;
esac
# Be sure to have absolute directory names.
case $ac_val in
[\\/$]* | ?:[\\/]* ) continue;;
NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
esac
as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
done
# There might be people who depend on the old broken behavior: `$host'
# used to hold the argument of --host etc.
# FIXME: To remove some day.
build=$build_alias
host=$host_alias
target=$target_alias
# FIXME: To remove some day.
if test "x$host_alias" != x; then
if test "x$build_alias" = x; then
cross_compiling=maybe
elif test "x$build_alias" != "x$host_alias"; then
cross_compiling=yes
fi
fi
ac_tool_prefix=
test -n "$host_alias" && ac_tool_prefix=$host_alias-
test "$silent" = yes && exec 6>/dev/null
ac_pwd=`pwd` && test -n "$ac_pwd" &&
ac_ls_di=`ls -di .` &&
ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
as_fn_error $? "working directory cannot be determined"
test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
as_fn_error $? "pwd does not report name of working directory"
# Find the source files, if location was not specified.
if test -z "$srcdir"; then
ac_srcdir_defaulted=yes
# Try the directory containing this script, then the parent directory.
ac_confdir=`$as_dirname -- "$as_myself" ||
$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$as_myself" : 'X\(//\)[^/]' \| \
X"$as_myself" : 'X\(//\)$' \| \
X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
$as_echo X"$as_myself" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
}
/^X\(\/\/\)[^/].*/{
s//\1/
q
}
/^X\(\/\/\)$/{
s//\1/
q
}
/^X\(\/\).*/{
s//\1/
q
}
s/.*/./; q'`
srcdir=$ac_confdir
if test ! -r "$srcdir/$ac_unique_file"; then
srcdir=..
fi
else
ac_srcdir_defaulted=no
fi
if test ! -r "$srcdir/$ac_unique_file"; then
test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
fi
ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
ac_abs_confdir=`(
cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
pwd)`
# When building in place, set srcdir=.
if test "$ac_abs_confdir" = "$ac_pwd"; then
srcdir=.
fi
# Remove unnecessary trailing slashes from srcdir.
# Double slashes in file names in object file debugging info
# mess up M-x gdb in Emacs.
case $srcdir in
*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
esac
for ac_var in $ac_precious_vars; do
eval ac_env_${ac_var}_set=\${${ac_var}+set}
eval ac_env_${ac_var}_value=\$${ac_var}
eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
eval ac_cv_env_${ac_var}_value=\$${ac_var}
done
#
# Report the --help message.
#
if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures rsync-bpc 3.1.3.0 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
To assign environment variables (e.g., CC, CFLAGS...), specify them as
VAR=VALUE. See below for descriptions of some of the useful variables.
Defaults for the options are specified in brackets.
Configuration:
-h, --help display this help and exit
--help=short display options specific to this package
--help=recursive display the short help of all the included packages
-V, --version display version information and exit
-q, --quiet, --silent do not print \`checking ...' messages
--cache-file=FILE cache test results in FILE [disabled]
-C, --config-cache alias for \`--cache-file=config.cache'
-n, --no-create do not create output files
--srcdir=DIR find the sources in DIR [configure dir or \`..']
Installation directories:
--prefix=PREFIX install architecture-independent files in PREFIX
[$ac_default_prefix]
--exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
[PREFIX]
By default, \`make install' will install all the files in
\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
an installation prefix other than \`$ac_default_prefix' using \`--prefix',
for instance \`--prefix=\$HOME'.
For better control, use the options below.
Fine tuning of the installation directories:
--bindir=DIR user executables [EPREFIX/bin]
--sbindir=DIR system admin executables [EPREFIX/sbin]
--libexecdir=DIR program executables [EPREFIX/libexec]
--sysconfdir=DIR read-only single-machine data [PREFIX/etc]
--sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
--localstatedir=DIR modifiable single-machine data [PREFIX/var]
--runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run]
--libdir=DIR object code libraries [EPREFIX/lib]
--includedir=DIR C header files [PREFIX/include]
--oldincludedir=DIR C header files for non-gcc [/usr/include]
--datarootdir=DIR read-only arch.-independent data root [PREFIX/share]
--datadir=DIR read-only architecture-independent data [DATAROOTDIR]
--infodir=DIR info documentation [DATAROOTDIR/info]
--localedir=DIR locale-dependent data [DATAROOTDIR/locale]
--mandir=DIR man documentation [DATAROOTDIR/man]
--docdir=DIR documentation root [DATAROOTDIR/doc/rsync-bpc]
--htmldir=DIR html documentation [DOCDIR]
--dvidir=DIR dvi documentation [DOCDIR]
--pdfdir=DIR pdf documentation [DOCDIR]
--psdir=DIR ps documentation [DOCDIR]
_ACEOF
cat <<\_ACEOF
System types:
--build=BUILD configure for building on BUILD [guessed]
--host=HOST cross-compile to build programs to run on HOST [BUILD]
_ACEOF
fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of rsync-bpc 3.1.3.0:";;
esac
cat <<\_ACEOF
Optional Features:
--disable-option-checking ignore unrecognized --enable/--with options
--disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
--enable-FEATURE[=ARG] include FEATURE [ARG=yes]
--disable-debug disable debugging symbols and features
--enable-profile turn on CPU profiling
--enable-maintainer-mode
turn on extra debug features
--disable-largefile omit support for large files
--disable-ipv6 do not even try to use IPv6
--disable-locale disable locale features
--disable-iconv-open disable all use of iconv_open() function
--disable-iconv disable rsync's --iconv option
--disable-acl-support disable ACL support
--disable-xattr-support disable extended attributes
Optional Packages:
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
--without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
--with-included-popt use bundled popt library, not from system
--with-included-zlib use bundled zlib library, not from system
--with-protected-args make --protected-args option the default
--with-rsync-path=PATH set default --rsync-path to PATH (default: rsync)
--with-rsyncd-conf=PATH set configuration file for rsync server to PATH
(default: /etc/rsyncd.conf)
--with-rsh=CMD set remote shell command to CMD (default: ssh)
--with-nobody-group=GROUP
set the default unprivileged group (default nobody
or nogroup)
Some influential environment variables:
CC C compiler command
CFLAGS C compiler flags
LDFLAGS linker flags, e.g. -L if you have libraries in a
nonstandard directory
LIBS libraries to pass to the linker, e.g. -l
CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if
you have headers in a nonstandard directory
CPP C preprocessor
Use these variables to override the choices made by `configure' or to help
it to find libraries and programs with nonstandard names/locations.
Report bugs to .
_ACEOF
ac_status=$?
fi
if test "$ac_init_help" = "recursive"; then
# If there are subdirs, report their specific --help.
for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
test -d "$ac_dir" ||
{ cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
continue
ac_builddir=.
case "$ac_dir" in
.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
*)
ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
# A ".." for each directory in $ac_dir_suffix.
ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
case $ac_top_builddir_sub in
"") ac_top_builddir_sub=. ac_top_build_prefix= ;;
*) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
esac ;;
esac
ac_abs_top_builddir=$ac_pwd
ac_abs_builddir=$ac_pwd$ac_dir_suffix
# for backward compatibility:
ac_top_builddir=$ac_top_build_prefix
case $srcdir in
.) # We are building in place.
ac_srcdir=.
ac_top_srcdir=$ac_top_builddir_sub
ac_abs_top_srcdir=$ac_pwd ;;
[\\/]* | ?:[\\/]* ) # Absolute name.
ac_srcdir=$srcdir$ac_dir_suffix;
ac_top_srcdir=$srcdir
ac_abs_top_srcdir=$srcdir ;;
*) # Relative name.
ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
ac_top_srcdir=$ac_top_build_prefix$srcdir
ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
esac
ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
cd "$ac_dir" || { ac_status=$?; continue; }
# Check for guested configure.
if test -f "$ac_srcdir/configure.gnu"; then
echo &&
$SHELL "$ac_srcdir/configure.gnu" --help=recursive
elif test -f "$ac_srcdir/configure"; then
echo &&
$SHELL "$ac_srcdir/configure" --help=recursive
else
$as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
fi || ac_status=$?
cd "$ac_pwd" || { ac_status=$?; break; }
done
fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
rsync-bpc configure 3.1.3.0
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
This configure script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it.
_ACEOF
exit
fi
## ------------------------ ##
## Autoconf initialization. ##
## ------------------------ ##
# ac_fn_c_try_compile LINENO
# --------------------------
# Try to compile conftest.$ac_ext, and return whether this succeeded.
ac_fn_c_try_compile ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
rm -f conftest.$ac_objext
if { { ac_try="$ac_compile"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
$as_echo "$ac_try_echo"; } >&5
(eval "$ac_compile") 2>conftest.err
ac_status=$?
if test -s conftest.err; then
grep -v '^ *+' conftest.err >conftest.er1
cat conftest.er1 >&5
mv -f conftest.er1 conftest.err
fi
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; } && {
test -z "$ac_c_werror_flag" ||
test ! -s conftest.err
} && test -s conftest.$ac_objext; then :
ac_retval=0
else
$as_echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_retval=1
fi
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
as_fn_set_status $ac_retval
} # ac_fn_c_try_compile
# ac_fn_c_try_cpp LINENO
# ----------------------
# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
ac_fn_c_try_cpp ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
if { { ac_try="$ac_cpp conftest.$ac_ext"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
$as_echo "$ac_try_echo"; } >&5
(eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
ac_status=$?
if test -s conftest.err; then
grep -v '^ *+' conftest.err >conftest.er1
cat conftest.er1 >&5
mv -f conftest.er1 conftest.err
fi
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; } > conftest.i && {
test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
test ! -s conftest.err
}; then :
ac_retval=0
else
$as_echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_retval=1
fi
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
as_fn_set_status $ac_retval
} # ac_fn_c_try_cpp
# ac_fn_c_try_run LINENO
# ----------------------
# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
# that executables *can* be run.
ac_fn_c_try_run ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
if { { ac_try="$ac_link"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
$as_echo "$ac_try_echo"; } >&5
(eval "$ac_link") 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
{ { case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
$as_echo "$ac_try_echo"; } >&5
(eval "$ac_try") 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; }; then :
ac_retval=0
else
$as_echo "$as_me: program exited with status $ac_status" >&5
$as_echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_retval=$ac_status
fi
rm -rf conftest.dSYM conftest_ipa8_conftest.oo
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
as_fn_set_status $ac_retval
} # ac_fn_c_try_run
# ac_fn_c_try_link LINENO
# -----------------------
# Try to link conftest.$ac_ext, and return whether this succeeded.
ac_fn_c_try_link ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
rm -f conftest.$ac_objext conftest$ac_exeext
if { { ac_try="$ac_link"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
$as_echo "$ac_try_echo"; } >&5
(eval "$ac_link") 2>conftest.err
ac_status=$?
if test -s conftest.err; then
grep -v '^ *+' conftest.err >conftest.er1
cat conftest.er1 >&5
mv -f conftest.er1 conftest.err
fi
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; } && {
test -z "$ac_c_werror_flag" ||
test ! -s conftest.err
} && test -s conftest$ac_exeext && {
test "$cross_compiling" = yes ||
test -x conftest$ac_exeext
}; then :
ac_retval=0
else
$as_echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_retval=1
fi
# Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
# created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
# interfere with the next link command; also delete a directory that is
# left behind by Apple's compiler. We do this before executing the actions.
rm -rf conftest.dSYM conftest_ipa8_conftest.oo
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
as_fn_set_status $ac_retval
} # ac_fn_c_try_link
# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
# -------------------------------------------------------
# Tests whether HEADER exists and can be compiled using the include files in
# INCLUDES, setting the cache variable VAR accordingly.
ac_fn_c_check_header_compile ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
$as_echo_n "checking for $2... " >&6; }
if eval \${$3+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
#include <$2>
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
eval "$3=yes"
else
eval "$3=no"
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
eval ac_res=\$$3
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
$as_echo "$ac_res" >&6; }
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
} # ac_fn_c_check_header_compile
# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
# -------------------------------------------------------
# Tests whether HEADER exists, giving a warning if it cannot be compiled using
# the include files in INCLUDES and setting the cache variable VAR
# accordingly.
ac_fn_c_check_header_mongrel ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
if eval \${$3+:} false; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
$as_echo_n "checking for $2... " >&6; }
if eval \${$3+:} false; then :
$as_echo_n "(cached) " >&6
fi
eval ac_res=\$$3
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
$as_echo "$ac_res" >&6; }
else
# Is the header compilable?
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
$as_echo_n "checking $2 usability... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
#include <$2>
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
ac_header_compiler=yes
else
ac_header_compiler=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
$as_echo "$ac_header_compiler" >&6; }
# Is the header present?
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
$as_echo_n "checking $2 presence... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <$2>
_ACEOF
if ac_fn_c_try_cpp "$LINENO"; then :
ac_header_preproc=yes
else
ac_header_preproc=no
fi
rm -f conftest.err conftest.i conftest.$ac_ext
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
$as_echo "$ac_header_preproc" >&6; }
# So? What about this header?
case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((
yes:no: )
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
;;
no:yes:* )
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5
$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;}
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5
$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;}
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
( $as_echo "## ----------------------------------------------------------- ##
## Report this to https://github.com/backuppc/rsync-bpc/issues ##
## ----------------------------------------------------------- ##"
) | sed "s/^/$as_me: WARNING: /" >&2
;;
esac
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
$as_echo_n "checking for $2... " >&6; }
if eval \${$3+:} false; then :
$as_echo_n "(cached) " >&6
else
eval "$3=\$ac_header_compiler"
fi
eval ac_res=\$$3
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
$as_echo "$ac_res" >&6; }
fi
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
} # ac_fn_c_check_header_mongrel
# ac_fn_c_compute_int LINENO EXPR VAR INCLUDES
# --------------------------------------------
# Tries to find the compile-time value of EXPR in a program that includes
# INCLUDES, setting VAR accordingly. Returns whether the value could be
# computed
ac_fn_c_compute_int ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
if test "$cross_compiling" = yes; then
# Depending upon the size, compute the lo and hi bounds.
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
int
main ()
{
static int test_array [1 - 2 * !(($2) >= 0)];
test_array [0] = 0;
return test_array [0];
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
ac_lo=0 ac_mid=0
while :; do
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
int
main ()
{
static int test_array [1 - 2 * !(($2) <= $ac_mid)];
test_array [0] = 0;
return test_array [0];
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
ac_hi=$ac_mid; break
else
as_fn_arith $ac_mid + 1 && ac_lo=$as_val
if test $ac_lo -le $ac_mid; then
ac_lo= ac_hi=
break
fi
as_fn_arith 2 '*' $ac_mid + 1 && ac_mid=$as_val
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
done
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
int
main ()
{
static int test_array [1 - 2 * !(($2) < 0)];
test_array [0] = 0;
return test_array [0];
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
ac_hi=-1 ac_mid=-1
while :; do
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
int
main ()
{
static int test_array [1 - 2 * !(($2) >= $ac_mid)];
test_array [0] = 0;
return test_array [0];
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
ac_lo=$ac_mid; break
else
as_fn_arith '(' $ac_mid ')' - 1 && ac_hi=$as_val
if test $ac_mid -le $ac_hi; then
ac_lo= ac_hi=
break
fi
as_fn_arith 2 '*' $ac_mid && ac_mid=$as_val
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
done
else
ac_lo= ac_hi=
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
# Binary search between lo and hi bounds.
while test "x$ac_lo" != "x$ac_hi"; do
as_fn_arith '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo && ac_mid=$as_val
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
int
main ()
{
static int test_array [1 - 2 * !(($2) <= $ac_mid)];
test_array [0] = 0;
return test_array [0];
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
ac_hi=$ac_mid
else
as_fn_arith '(' $ac_mid ')' + 1 && ac_lo=$as_val
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
done
case $ac_lo in #((
?*) eval "$3=\$ac_lo"; ac_retval=0 ;;
'') ac_retval=1 ;;
esac
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
static long int longval () { return $2; }
static unsigned long int ulongval () { return $2; }
#include
#include
int
main ()
{
FILE *f = fopen ("conftest.val", "w");
if (! f)
return 1;
if (($2) < 0)
{
long int i = longval ();
if (i != ($2))
return 1;
fprintf (f, "%ld", i);
}
else
{
unsigned long int i = ulongval ();
if (i != ($2))
return 1;
fprintf (f, "%lu", i);
}
/* Do not output a trailing newline, as this causes \r\n confusion
on some platforms. */
return ferror (f) || fclose (f) != 0;
;
return 0;
}
_ACEOF
if ac_fn_c_try_run "$LINENO"; then :
echo >>conftest.val; read $3 &5
$as_echo_n "checking for $2... " >&6; }
if eval \${$3+:} false; then :
$as_echo_n "(cached) " >&6
else
eval "$3=no"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
int
main ()
{
if (sizeof ($2))
return 0;
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
int
main ()
{
if (sizeof (($2)))
return 0;
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
else
eval "$3=yes"
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
eval ac_res=\$$3
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
$as_echo "$ac_res" >&6; }
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
} # ac_fn_c_check_type
# ac_fn_c_check_member LINENO AGGR MEMBER VAR INCLUDES
# ----------------------------------------------------
# Tries to find if the field MEMBER exists in type AGGR, after including
# INCLUDES, setting cache variable VAR accordingly.
ac_fn_c_check_member ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5
$as_echo_n "checking for $2.$3... " >&6; }
if eval \${$4+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$5
int
main ()
{
static $2 ac_aggr;
if (ac_aggr.$3)
return 0;
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
eval "$4=yes"
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$5
int
main ()
{
static $2 ac_aggr;
if (sizeof ac_aggr.$3)
return 0;
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
eval "$4=yes"
else
eval "$4=no"
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
eval ac_res=\$$4
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
$as_echo "$ac_res" >&6; }
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
} # ac_fn_c_check_member
# ac_fn_c_check_func LINENO FUNC VAR
# ----------------------------------
# Tests whether FUNC exists, setting the cache variable VAR accordingly
ac_fn_c_check_func ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
$as_echo_n "checking for $2... " >&6; }
if eval \${$3+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Define $2 to an innocuous variant, in case declares $2.
For example, HP-UX 11i declares gettimeofday. */
#define $2 innocuous_$2
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $2 (); below.
Prefer to if __STDC__ is defined, since
exists even on freestanding compilers. */
#ifdef __STDC__
# include
#else
# include
#endif
#undef $2
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char $2 ();
/* The GNU C library defines this for functions which it implements
to always fail with ENOSYS. Some functions are actually named
something starting with __ and the normal name is an alias. */
#if defined __stub_$2 || defined __stub___$2
choke me
#endif
int
main ()
{
return $2 ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
eval "$3=yes"
else
eval "$3=no"
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
fi
eval ac_res=\$$3
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
$as_echo "$ac_res" >&6; }
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
} # ac_fn_c_check_func
cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by rsync-bpc $as_me 3.1.3.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
_ACEOF
exec 5>>config.log
{
cat <<_ASUNAME
## --------- ##
## Platform. ##
## --------- ##
hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
uname -m = `(uname -m) 2>/dev/null || echo unknown`
uname -r = `(uname -r) 2>/dev/null || echo unknown`
uname -s = `(uname -s) 2>/dev/null || echo unknown`
uname -v = `(uname -v) 2>/dev/null || echo unknown`
/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown`
/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
_ASUNAME
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
$as_echo "PATH: $as_dir"
done
IFS=$as_save_IFS
} >&5
cat >&5 <<_ACEOF
## ----------- ##
## Core tests. ##
## ----------- ##
_ACEOF
# Keep a trace of the command line.
# Strip out --no-create and --no-recursion so they do not pile up.
# Strip out --silent because we don't want to record it for future runs.
# Also quote any args containing shell meta-characters.
# Make two passes to allow for proper duplicate-argument suppression.
ac_configure_args=
ac_configure_args0=
ac_configure_args1=
ac_must_keep_next=false
for ac_pass in 1 2
do
for ac_arg
do
case $ac_arg in
-no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
-q | -quiet | --quiet | --quie | --qui | --qu | --q \
| -silent | --silent | --silen | --sile | --sil)
continue ;;
*\'*)
ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
esac
case $ac_pass in
1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
2)
as_fn_append ac_configure_args1 " '$ac_arg'"
if test $ac_must_keep_next = true; then
ac_must_keep_next=false # Got value, back to normal.
else
case $ac_arg in
*=* | --config-cache | -C | -disable-* | --disable-* \
| -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
| -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
| -with-* | --with-* | -without-* | --without-* | --x)
case "$ac_configure_args0 " in
"$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
esac
;;
-* ) ac_must_keep_next=true ;;
esac
fi
as_fn_append ac_configure_args " '$ac_arg'"
;;
esac
done
done
{ ac_configure_args0=; unset ac_configure_args0;}
{ ac_configure_args1=; unset ac_configure_args1;}
# When interrupted or exit'd, cleanup temporary files, and complete
# config.log. We remove comments because anyway the quotes in there
# would cause problems or look ugly.
# WARNING: Use '\'' to represent an apostrophe within the trap.
# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
trap 'exit_status=$?
# Save into config.log some information that might help in debugging.
{
echo
$as_echo "## ---------------- ##
## Cache variables. ##
## ---------------- ##"
echo
# The following way of writing the cache mishandles newlines in values,
(
for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
eval ac_val=\$$ac_var
case $ac_val in #(
*${as_nl}*)
case $ac_var in #(
*_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
esac
case $ac_var in #(
_ | IFS | as_nl) ;; #(
BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
*) { eval $ac_var=; unset $ac_var;} ;;
esac ;;
esac
done
(set) 2>&1 |
case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
*${as_nl}ac_space=\ *)
sed -n \
"s/'\''/'\''\\\\'\'''\''/g;
s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
;; #(
*)
sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
;;
esac |
sort
)
echo
$as_echo "## ----------------- ##
## Output variables. ##
## ----------------- ##"
echo
for ac_var in $ac_subst_vars
do
eval ac_val=\$$ac_var
case $ac_val in
*\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
esac
$as_echo "$ac_var='\''$ac_val'\''"
done | sort
echo
if test -n "$ac_subst_files"; then
$as_echo "## ------------------- ##
## File substitutions. ##
## ------------------- ##"
echo
for ac_var in $ac_subst_files
do
eval ac_val=\$$ac_var
case $ac_val in
*\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
esac
$as_echo "$ac_var='\''$ac_val'\''"
done | sort
echo
fi
if test -s confdefs.h; then
$as_echo "## ----------- ##
## confdefs.h. ##
## ----------- ##"
echo
cat confdefs.h
echo
fi
test "$ac_signal" != 0 &&
$as_echo "$as_me: caught signal $ac_signal"
$as_echo "$as_me: exit $exit_status"
} >&5
rm -f core *.core core.conftest.* &&
rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
exit $exit_status
' 0
for ac_signal in 1 2 13 15; do
trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
done
ac_signal=0
# confdefs.h avoids OS command line length limits that DEFS can exceed.
rm -f -r conftest* confdefs.h
$as_echo "/* confdefs.h */" > confdefs.h
# Predefined preprocessor variables.
cat >>confdefs.h <<_ACEOF
#define PACKAGE_NAME "$PACKAGE_NAME"
_ACEOF
cat >>confdefs.h <<_ACEOF
#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
_ACEOF
cat >>confdefs.h <<_ACEOF
#define PACKAGE_VERSION "$PACKAGE_VERSION"
_ACEOF
cat >>confdefs.h <<_ACEOF
#define PACKAGE_STRING "$PACKAGE_STRING"
_ACEOF
cat >>confdefs.h <<_ACEOF
#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
_ACEOF
cat >>confdefs.h <<_ACEOF
#define PACKAGE_URL "$PACKAGE_URL"
_ACEOF
# Let the site file select an alternate cache file if it wants to.
# Prefer an explicitly selected file to automatically selected ones.
ac_site_file1=NONE
ac_site_file2=NONE
if test -n "$CONFIG_SITE"; then
# We do not want a PATH search for config.site.
case $CONFIG_SITE in #((
-*) ac_site_file1=./$CONFIG_SITE;;
*/*) ac_site_file1=$CONFIG_SITE;;
*) ac_site_file1=./$CONFIG_SITE;;
esac
elif test "x$prefix" != xNONE; then
ac_site_file1=$prefix/share/config.site
ac_site_file2=$prefix/etc/config.site
else
ac_site_file1=$ac_default_prefix/share/config.site
ac_site_file2=$ac_default_prefix/etc/config.site
fi
for ac_site_file in "$ac_site_file1" "$ac_site_file2"
do
test "x$ac_site_file" = xNONE && continue
if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
$as_echo "$as_me: loading site script $ac_site_file" >&6;}
sed 's/^/| /' "$ac_site_file" >&5
. "$ac_site_file" \
|| { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "failed to load site script $ac_site_file
See \`config.log' for more details" "$LINENO" 5; }
fi
done
if test -r "$cache_file"; then
# Some versions of bash will fail to source /dev/null (special files
# actually), so we avoid doing that. DJGPP emulates it as a regular file.
if test /dev/null != "$cache_file" && test -f "$cache_file"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
$as_echo "$as_me: loading cache $cache_file" >&6;}
case $cache_file in
[\\/]* | ?:[\\/]* ) . "$cache_file";;
*) . "./$cache_file";;
esac
fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
$as_echo "$as_me: creating cache $cache_file" >&6;}
>$cache_file
fi
as_fn_append ac_header_list " sys/types.h"
as_fn_append ac_header_list " utime.h"
# Check that the precious variables saved in the cache have kept the same
# value.
ac_cache_corrupted=false
for ac_var in $ac_precious_vars; do
eval ac_old_set=\$ac_cv_env_${ac_var}_set
eval ac_new_set=\$ac_env_${ac_var}_set
eval ac_old_val=\$ac_cv_env_${ac_var}_value
eval ac_new_val=\$ac_env_${ac_var}_value
case $ac_old_set,$ac_new_set in
set,)
{ $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
ac_cache_corrupted=: ;;
,set)
{ $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
ac_cache_corrupted=: ;;
,);;
*)
if test "x$ac_old_val" != "x$ac_new_val"; then
# differences in whitespace do not lead to failure.
ac_old_val_w=`echo x $ac_old_val`
ac_new_val_w=`echo x $ac_new_val`
if test "$ac_old_val_w" != "$ac_new_val_w"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
ac_cache_corrupted=:
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
eval $ac_var=\$ac_old_val
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5
$as_echo "$as_me: former value: \`$ac_old_val'" >&2;}
{ $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5
$as_echo "$as_me: current value: \`$ac_new_val'" >&2;}
fi;;
esac
# Pass precious variables to config.status.
if test "$ac_new_set" = set; then
case $ac_new_val in
*\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
*) ac_arg=$ac_var=$ac_new_val ;;
esac
case " $ac_configure_args " in
*" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
*) as_fn_append ac_configure_args " '$ac_arg'" ;;
esac
fi
done
if $ac_cache_corrupted; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
{ $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
fi
## -------------------- ##
## Main body of script. ##
## -------------------- ##
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
ac_config_headers="$ac_config_headers config.h"
RSYNC_VERSION=$PACKAGE_VERSION
{ $as_echo "$as_me:${as_lineno-$LINENO}: Configuring rsync_bpc $PACKAGE_VERSION" >&5
$as_echo "$as_me: Configuring rsync_bpc $PACKAGE_VERSION" >&6;}
cat >>confdefs.h <<_ACEOF
#define RSYNC_VERSION "$PACKAGE_VERSION"
_ACEOF
LDFLAGS=${LDFLAGS-""}
ac_aux_dir=
for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
if test -f "$ac_dir/install-sh"; then
ac_aux_dir=$ac_dir
ac_install_sh="$ac_aux_dir/install-sh -c"
break
elif test -f "$ac_dir/install.sh"; then
ac_aux_dir=$ac_dir
ac_install_sh="$ac_aux_dir/install.sh -c"
break
elif test -f "$ac_dir/shtool"; then
ac_aux_dir=$ac_dir
ac_install_sh="$ac_aux_dir/shtool install -c"
break
fi
done
if test -z "$ac_aux_dir"; then
as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5
fi
# These three variables are undocumented and unsupported,
# and are intended to be withdrawn in a future Autoconf release.
# They can cause serious problems if a builder's source tree is in a directory
# whose full name contains unusual characters.
ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var.
ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var.
ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var.
# Make sure we can run config.sub.
$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
$as_echo_n "checking build system type... " >&6; }
if ${ac_cv_build+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_build_alias=$build_alias
test "x$ac_build_alias" = x &&
ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
test "x$ac_build_alias" = x &&
as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5
ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
$as_echo "$ac_cv_build" >&6; }
case $ac_cv_build in
*-*-*) ;;
*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;;
esac
build=$ac_cv_build
ac_save_IFS=$IFS; IFS='-'
set x $ac_cv_build
shift
build_cpu=$1
build_vendor=$2
shift; shift
# Remember, the first character of IFS is used to create $*,
# except with old shells:
build_os=$*
IFS=$ac_save_IFS
case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
$as_echo_n "checking host system type... " >&6; }
if ${ac_cv_host+:} false; then :
$as_echo_n "(cached) " >&6
else
if test "x$host_alias" = x; then
ac_cv_host=$ac_cv_build
else
ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
$as_echo "$ac_cv_host" >&6; }
case $ac_cv_host in
*-*-*) ;;
*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;;
esac
host=$ac_cv_host
ac_save_IFS=$IFS; IFS='-'
set x $ac_cv_host
shift
host_cpu=$1
host_vendor=$2
shift; shift
# Remember, the first character of IFS is used to create $*,
# except with old shells:
host_os=$*
IFS=$ac_save_IFS
case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
# We must decide this before testing the compiler.
# Please allow this to default to yes, so that your users have more
# chance of getting a useful stack trace if problems occur.
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to include debugging symbols" >&5
$as_echo_n "checking whether to include debugging symbols... " >&6; }
# Check whether --enable-debug was given.
if test "${enable_debug+set}" = set; then :
enableval=$enable_debug;
fi
if test x"$enable_debug" = x"no"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
ac_cv_prog_cc_g=no
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
# leave ac_cv_prog_cc_g alone; AC_PROG_CC will try to include -g if it can
fi
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
set dummy ${ac_tool_prefix}gcc; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_prog_CC+:} false; then :
$as_echo_n "(cached) " >&6
else
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_prog_CC="${ac_tool_prefix}gcc"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
$as_echo "$CC" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
fi
if test -z "$ac_cv_prog_CC"; then
ac_ct_CC=$CC
# Extract the first word of "gcc", so it can be a program name with args.
set dummy gcc; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_prog_ac_ct_CC+:} false; then :
$as_echo_n "(cached) " >&6
else
if test -n "$ac_ct_CC"; then
ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_CC="gcc"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi
fi
ac_ct_CC=$ac_cv_prog_ac_ct_CC
if test -n "$ac_ct_CC"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
$as_echo "$ac_ct_CC" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
if test "x$ac_ct_CC" = x; then
CC=""
else
case $cross_compiling:$ac_tool_warned in
yes:)
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
CC=$ac_ct_CC
fi
else
CC="$ac_cv_prog_CC"
fi
if test -z "$CC"; then
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
set dummy ${ac_tool_prefix}cc; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_prog_CC+:} false; then :
$as_echo_n "(cached) " >&6
else
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_prog_CC="${ac_tool_prefix}cc"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
$as_echo "$CC" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
fi
fi
if test -z "$CC"; then
# Extract the first word of "cc", so it can be a program name with args.
set dummy cc; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_prog_CC+:} false; then :
$as_echo_n "(cached) " >&6
else
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
ac_prog_rejected=no
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
ac_prog_rejected=yes
continue
fi
ac_cv_prog_CC="cc"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
if test $ac_prog_rejected = yes; then
# We found a bogon in the path, so make sure we never use it.
set dummy $ac_cv_prog_CC
shift
if test $# != 0; then
# We chose a different compiler from the bogus one.
# However, it has the same basename, so the bogon will be chosen
# first if we set CC to just the basename; use the full file name.
shift
ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
fi
fi
fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
$as_echo "$CC" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
fi
if test -z "$CC"; then
if test -n "$ac_tool_prefix"; then
for ac_prog in cl.exe
do
# Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
set dummy $ac_tool_prefix$ac_prog; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_prog_CC+:} false; then :
$as_echo_n "(cached) " >&6
else
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
$as_echo "$CC" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
test -n "$CC" && break
done
fi
if test -z "$CC"; then
ac_ct_CC=$CC
for ac_prog in cl.exe
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_prog_ac_ct_CC+:} false; then :
$as_echo_n "(cached) " >&6
else
if test -n "$ac_ct_CC"; then
ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_CC="$ac_prog"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi
fi
ac_ct_CC=$ac_cv_prog_ac_ct_CC
if test -n "$ac_ct_CC"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
$as_echo "$ac_ct_CC" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
test -n "$ac_ct_CC" && break
done
if test "x$ac_ct_CC" = x; then
CC=""
else
case $cross_compiling:$ac_tool_warned in
yes:)
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
CC=$ac_ct_CC
fi
fi
fi
test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "no acceptable C compiler found in \$PATH
See \`config.log' for more details" "$LINENO" 5; }
# Provide some information about the compiler.
$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
set X $ac_compile
ac_compiler=$2
for ac_option in --version -v -V -qversion; do
{ { ac_try="$ac_compiler $ac_option >&5"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
$as_echo "$ac_try_echo"; } >&5
(eval "$ac_compiler $ac_option >&5") 2>conftest.err
ac_status=$?
if test -s conftest.err; then
sed '10a\
... rest of stderr output deleted ...
10q' conftest.err >conftest.er1
cat conftest.er1 >&5
fi
rm -f conftest.er1 conftest.err
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }
done
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
main ()
{
;
return 0;
}
_ACEOF
ac_clean_files_save=$ac_clean_files
ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
# Try to create an executable without -o first, disregard a.out.
# It will help us diagnose broken compilers, and finding out an intuition
# of exeext.
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
$as_echo_n "checking whether the C compiler works... " >&6; }
ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
# The possible output files:
ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
ac_rmfiles=
for ac_file in $ac_files
do
case $ac_file in
*.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
* ) ac_rmfiles="$ac_rmfiles $ac_file";;
esac
done
rm -f $ac_rmfiles
if { { ac_try="$ac_link_default"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
$as_echo "$ac_try_echo"; } >&5
(eval "$ac_link_default") 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then :
# Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
# in a Makefile. We should not override ac_cv_exeext if it was cached,
# so that the user can short-circuit this test for compilers unknown to
# Autoconf.
for ac_file in $ac_files ''
do
test -f "$ac_file" || continue
case $ac_file in
*.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
;;
[ab].out )
# We found the default executable, but exeext='' is most
# certainly right.
break;;
*.* )
if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
then :; else
ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
fi
# We set ac_cv_exeext here because the later test for it is not
# safe: cross compilers may not add the suffix if given an `-o'
# argument, so we may need to know it at that point already.
# Even if this section looks crufty: it has the advantage of
# actually working.
break;;
* )
break;;
esac
done
test "$ac_cv_exeext" = no && ac_cv_exeext=
else
ac_file=''
fi
if test -z "$ac_file"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
$as_echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "C compiler cannot create executables
See \`config.log' for more details" "$LINENO" 5; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
$as_echo_n "checking for C compiler default output file name... " >&6; }
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
$as_echo "$ac_file" >&6; }
ac_exeext=$ac_cv_exeext
rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
ac_clean_files=$ac_clean_files_save
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
$as_echo_n "checking for suffix of executables... " >&6; }
if { { ac_try="$ac_link"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
$as_echo "$ac_try_echo"; } >&5
(eval "$ac_link") 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then :
# If both `conftest.exe' and `conftest' are `present' (well, observable)
# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
# work properly (i.e., refer to `conftest.exe'), while it won't with
# `rm'.
for ac_file in conftest.exe conftest conftest.*; do
test -f "$ac_file" || continue
case $ac_file in
*.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
*.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
break;;
* ) break;;
esac
done
else
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "cannot compute suffix of executables: cannot compile and link
See \`config.log' for more details" "$LINENO" 5; }
fi
rm -f conftest conftest$ac_cv_exeext
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
$as_echo "$ac_cv_exeext" >&6; }
rm -f conftest.$ac_ext
EXEEXT=$ac_cv_exeext
ac_exeext=$EXEEXT
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include
int
main ()
{
FILE *f = fopen ("conftest.out", "w");
return ferror (f) || fclose (f) != 0;
;
return 0;
}
_ACEOF
ac_clean_files="$ac_clean_files conftest.out"
# Check that the compiler produces executables we can run. If not, either
# the compiler is broken, or we cross compile.
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
$as_echo_n "checking whether we are cross compiling... " >&6; }
if test "$cross_compiling" != yes; then
{ { ac_try="$ac_link"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
$as_echo "$ac_try_echo"; } >&5
(eval "$ac_link") 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }
if { ac_try='./conftest$ac_cv_exeext'
{ { case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
$as_echo "$ac_try_echo"; } >&5
(eval "$ac_try") 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; }; then
cross_compiling=no
else
if test "$cross_compiling" = maybe; then
cross_compiling=yes
else
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "cannot run C compiled programs.
If you meant to cross compile, use \`--host'.
See \`config.log' for more details" "$LINENO" 5; }
fi
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
$as_echo "$cross_compiling" >&6; }
rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
ac_clean_files=$ac_clean_files_save
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
$as_echo_n "checking for suffix of object files... " >&6; }
if ${ac_cv_objext+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
main ()
{
;
return 0;
}
_ACEOF
rm -f conftest.o conftest.obj
if { { ac_try="$ac_compile"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
$as_echo "$ac_try_echo"; } >&5
(eval "$ac_compile") 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then :
for ac_file in conftest.o conftest.obj conftest.*; do
test -f "$ac_file" || continue;
case $ac_file in
*.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
*) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
break;;
esac
done
else
$as_echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "cannot compute suffix of object files: cannot compile
See \`config.log' for more details" "$LINENO" 5; }
fi
rm -f conftest.$ac_cv_objext conftest.$ac_ext
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
$as_echo "$ac_cv_objext" >&6; }
OBJEXT=$ac_cv_objext
ac_objext=$OBJEXT
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
if ${ac_cv_c_compiler_gnu+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
main ()
{
#ifndef __GNUC__
choke me
#endif
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
ac_compiler_gnu=yes
else
ac_compiler_gnu=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
ac_cv_c_compiler_gnu=$ac_compiler_gnu
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
$as_echo "$ac_cv_c_compiler_gnu" >&6; }
if test $ac_compiler_gnu = yes; then
GCC=yes
else
GCC=
fi
ac_test_CFLAGS=${CFLAGS+set}
ac_save_CFLAGS=$CFLAGS
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
$as_echo_n "checking whether $CC accepts -g... " >&6; }
if ${ac_cv_prog_cc_g+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_save_c_werror_flag=$ac_c_werror_flag
ac_c_werror_flag=yes
ac_cv_prog_cc_g=no
CFLAGS="-g"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
main ()
{
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_prog_cc_g=yes
else
CFLAGS=""
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
main ()
{
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
else
ac_c_werror_flag=$ac_save_c_werror_flag
CFLAGS="-g"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
main ()
{
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_prog_cc_g=yes
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
ac_c_werror_flag=$ac_save_c_werror_flag
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
$as_echo "$ac_cv_prog_cc_g" >&6; }
if test "$ac_test_CFLAGS" = set; then
CFLAGS=$ac_save_CFLAGS
elif test $ac_cv_prog_cc_g = yes; then
if test "$GCC" = yes; then
CFLAGS="-g -O2"
else
CFLAGS="-g"
fi
else
if test "$GCC" = yes; then
CFLAGS="-O2"
else
CFLAGS=
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
if ${ac_cv_prog_cc_c89+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_cv_prog_cc_c89=no
ac_save_CC=$CC
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include
#include
struct stat;
/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
struct buf { int x; };
FILE * (*rcsopen) (struct buf *, struct stat *, int);
static char *e (p, i)
char **p;
int i;
{
return p[i];
}
static char *f (char * (*g) (char **, int), char **p, ...)
{
char *s;
va_list v;
va_start (v,p);
s = g (p, va_arg (v,int));
va_end (v);
return s;
}
/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
function prototypes and stuff, but not '\xHH' hex character constants.
These don't provoke an error unfortunately, instead are silently treated
as 'x'. The following induces an error, until -std is added to get
proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
array size at least. It's necessary to write '\x00'==0 to get something
that's true only with -std. */
int osf4_cc_array ['\x00' == 0 ? 1 : -1];
/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
inside strings and character constants. */
#define FOO(x) 'x'
int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
int test (int i, double x);
struct s1 {int (*f) (int a);};
struct s2 {int (*f) (double a);};
int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
int argc;
char **argv;
int
main ()
{
return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
;
return 0;
}
_ACEOF
for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
-Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
do
CC="$ac_save_CC $ac_arg"
if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_prog_cc_c89=$ac_arg
fi
rm -f core conftest.err conftest.$ac_objext
test "x$ac_cv_prog_cc_c89" != "xno" && break
done
rm -f conftest.$ac_ext
CC=$ac_save_CC
fi
# AC_CACHE_VAL
case "x$ac_cv_prog_cc_c89" in
x)
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
$as_echo "none needed" >&6; } ;;
xno)
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
$as_echo "unsupported" >&6; } ;;
*)
CC="$CC $ac_cv_prog_cc_c89"
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
esac
if test "x$ac_cv_prog_cc_c89" != xno; then :
fi
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
$as_echo_n "checking how to run the C preprocessor... " >&6; }
# On Suns, sometimes $CPP names a directory.
if test -n "$CPP" && test -d "$CPP"; then
CPP=
fi
if test -z "$CPP"; then
if ${ac_cv_prog_CPP+:} false; then :
$as_echo_n "(cached) " >&6
else
# Double quotes because CPP needs to be expanded
for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
do
ac_preproc_ok=false
for ac_c_preproc_warn_flag in '' yes
do
# Use a header file that comes with gcc, so configuring glibc
# with a fresh cross-compiler works.
# Prefer to if __STDC__ is defined, since
# exists even on freestanding compilers.
# On the NeXT, cc -E runs the code through the compiler's parser,
# not just through cpp. "Syntax error" is here to catch this case.
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#ifdef __STDC__
# include
#else
# include
#endif
Syntax error
_ACEOF
if ac_fn_c_try_cpp "$LINENO"; then :
else
# Broken: fails on valid input.
continue
fi
rm -f conftest.err conftest.i conftest.$ac_ext
# OK, works on sane cases. Now check whether nonexistent headers
# can be detected and how.
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include
_ACEOF
if ac_fn_c_try_cpp "$LINENO"; then :
# Broken: success on invalid input.
continue
else
# Passes both tests.
ac_preproc_ok=:
break
fi
rm -f conftest.err conftest.i conftest.$ac_ext
done
# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
rm -f conftest.i conftest.err conftest.$ac_ext
if $ac_preproc_ok; then :
break
fi
done
ac_cv_prog_CPP=$CPP
fi
CPP=$ac_cv_prog_CPP
else
ac_cv_prog_CPP=$CPP
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
$as_echo "$CPP" >&6; }
ac_preproc_ok=false
for ac_c_preproc_warn_flag in '' yes
do
# Use a header file that comes with gcc, so configuring glibc
# with a fresh cross-compiler works.
# Prefer to if __STDC__ is defined, since
# exists even on freestanding compilers.
# On the NeXT, cc -E runs the code through the compiler's parser,
# not just through cpp. "Syntax error" is here to catch this case.
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#ifdef __STDC__
# include
#else
# include
#endif
Syntax error
_ACEOF
if ac_fn_c_try_cpp "$LINENO"; then :
else
# Broken: fails on valid input.
continue
fi
rm -f conftest.err conftest.i conftest.$ac_ext
# OK, works on sane cases. Now check whether nonexistent headers
# can be detected and how.
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include
_ACEOF
if ac_fn_c_try_cpp "$LINENO"; then :
# Broken: success on invalid input.
continue
else
# Passes both tests.
ac_preproc_ok=:
break
fi
rm -f conftest.err conftest.i conftest.$ac_ext
done
# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
rm -f conftest.i conftest.err conftest.$ac_ext
if $ac_preproc_ok; then :
else
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
See \`config.log' for more details" "$LINENO" 5; }
fi
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
if ${ac_cv_path_GREP+:} false; then :
$as_echo_n "(cached) " >&6
else
if test -z "$GREP"; then
ac_path_GREP_found=false
# Loop through the user's path and test for each of PROGNAME-LIST
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_prog in grep ggrep; do
for ac_exec_ext in '' $ac_executable_extensions; do
ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
as_fn_executable_p "$ac_path_GREP" || continue
# Check for GNU ac_path_GREP and select it if it is found.
# Check for GNU $ac_path_GREP
case `"$ac_path_GREP" --version 2>&1` in
*GNU*)
ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
*)
ac_count=0
$as_echo_n 0123456789 >"conftest.in"
while :
do
cat "conftest.in" "conftest.in" >"conftest.tmp"
mv "conftest.tmp" "conftest.in"
cp "conftest.in" "conftest.nl"
$as_echo 'GREP' >> "conftest.nl"
"$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
as_fn_arith $ac_count + 1 && ac_count=$as_val
if test $ac_count -gt ${ac_path_GREP_max-0}; then
# Best one so far, save it but keep looking for a better one
ac_cv_path_GREP="$ac_path_GREP"
ac_path_GREP_max=$ac_count
fi
# 10*(2^10) chars as input seems more than enough
test $ac_count -gt 10 && break
done
rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
esac
$ac_path_GREP_found && break 3
done
done
done
IFS=$as_save_IFS
if test -z "$ac_cv_path_GREP"; then
as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
fi
else
ac_cv_path_GREP=$GREP
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
$as_echo "$ac_cv_path_GREP" >&6; }
GREP="$ac_cv_path_GREP"
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
$as_echo_n "checking for egrep... " >&6; }
if ${ac_cv_path_EGREP+:} false; then :
$as_echo_n "(cached) " >&6
else
if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
then ac_cv_path_EGREP="$GREP -E"
else
if test -z "$EGREP"; then
ac_path_EGREP_found=false
# Loop through the user's path and test for each of PROGNAME-LIST
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_prog in egrep; do
for ac_exec_ext in '' $ac_executable_extensions; do
ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
as_fn_executable_p "$ac_path_EGREP" || continue
# Check for GNU ac_path_EGREP and select it if it is found.
# Check for GNU $ac_path_EGREP
case `"$ac_path_EGREP" --version 2>&1` in
*GNU*)
ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
*)
ac_count=0
$as_echo_n 0123456789 >"conftest.in"
while :
do
cat "conftest.in" "conftest.in" >"conftest.tmp"
mv "conftest.tmp" "conftest.in"
cp "conftest.in" "conftest.nl"
$as_echo 'EGREP' >> "conftest.nl"
"$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
as_fn_arith $ac_count + 1 && ac_count=$as_val
if test $ac_count -gt ${ac_path_EGREP_max-0}; then
# Best one so far, save it but keep looking for a better one
ac_cv_path_EGREP="$ac_path_EGREP"
ac_path_EGREP_max=$ac_count
fi
# 10*(2^10) chars as input seems more than enough
test $ac_count -gt 10 && break
done
rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
esac
$ac_path_EGREP_found && break 3
done
done
done
IFS=$as_save_IFS
if test -z "$ac_cv_path_EGREP"; then
as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
fi
else
ac_cv_path_EGREP=$EGREP
fi
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
$as_echo "$ac_cv_path_EGREP" >&6; }
EGREP="$ac_cv_path_EGREP"
# Find a good install program. We prefer a C program (faster),
# so one script is as good as another. But avoid the broken or
# incompatible versions:
# SysV /etc/install, /usr/sbin/install
# SunOS /usr/etc/install
# IRIX /sbin/install
# AIX /bin/install
# AmigaOS /C/install, which installs bootblocks on floppy discs
# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
# AFS /usr/afsws/bin/install, which mishandles nonexistent args
# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
# OS/2's system install, which has a completely different semantic
# ./install, which can be erroneously created by make from ./install.sh.
# Reject install programs that cannot install multiple files.
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
$as_echo_n "checking for a BSD-compatible install... " >&6; }
if test -z "$INSTALL"; then
if ${ac_cv_path_install+:} false; then :
$as_echo_n "(cached) " >&6
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
# Account for people who put trailing slashes in PATH elements.
case $as_dir/ in #((
./ | .// | /[cC]/* | \
/etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \
/usr/ucb/* ) ;;
*)
# OSF1 and SCO ODT 3.0 have their own names for install.
# Don't use installbsd from OSF since it installs stuff as root
# by default.
for ac_prog in ginstall scoinst install; do
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
if test $ac_prog = install &&
grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
# AIX install. It has an incompatible calling convention.
:
elif test $ac_prog = install &&
grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
# program-specific install script used by HP pwplus--don't use.
:
else
rm -rf conftest.one conftest.two conftest.dir
echo one > conftest.one
echo two > conftest.two
mkdir conftest.dir
if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" &&
test -s conftest.one && test -s conftest.two &&
test -s conftest.dir/conftest.one &&
test -s conftest.dir/conftest.two
then
ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
break 3
fi
fi
fi
done
done
;;
esac
done
IFS=$as_save_IFS
rm -rf conftest.one conftest.two conftest.dir
fi
if test "${ac_cv_path_install+set}" = set; then
INSTALL=$ac_cv_path_install
else
# As a last resort, use the slow shell script. Don't cache a
# value for INSTALL within a source directory, because that will
# break other packages using the cache if that directory is
# removed, or if the value is a relative name.
INSTALL=$ac_install_sh
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5
$as_echo "$INSTALL" >&6; }
# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
# It thinks the first close brace ends the variable substitution.
test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5
$as_echo_n "checking for a thread-safe mkdir -p... " >&6; }
if test -z "$MKDIR_P"; then
if ${ac_cv_path_mkdir+:} false; then :
$as_echo_n "(cached) " >&6
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_prog in mkdir gmkdir; do
for ac_exec_ext in '' $ac_executable_extensions; do
as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue
case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #(
'mkdir (GNU coreutils) '* | \
'mkdir (coreutils) '* | \
'mkdir (fileutils) '4.1*)
ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext
break 3;;
esac
done
done
done
IFS=$as_save_IFS
fi
test -d ./--version && rmdir ./--version
if test "${ac_cv_path_mkdir+set}" = set; then
MKDIR_P="$ac_cv_path_mkdir -p"
else
# As a last resort, use the slow shell script. Don't cache a
# value for MKDIR_P within a source directory, because that will
# break other packages using the cache if that directory is
# removed, or if the value is a relative name.
MKDIR_P="$ac_install_sh -d"
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5
$as_echo "$MKDIR_P" >&6; }
case $ac_cv_prog_cc_stdc in #(
no) :
ac_cv_prog_cc_c99=no; ac_cv_prog_cc_c89=no ;; #(
*) :
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C99" >&5
$as_echo_n "checking for $CC option to accept ISO C99... " >&6; }
if ${ac_cv_prog_cc_c99+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_cv_prog_cc_c99=no
ac_save_CC=$CC
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include
#include
#include
#include
#include
// Check varargs macros. These examples are taken from C99 6.10.3.5.
#define debug(...) fprintf (stderr, __VA_ARGS__)
#define showlist(...) puts (#__VA_ARGS__)
#define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__))
static void
test_varargs_macros (void)
{
int x = 1234;
int y = 5678;
debug ("Flag");
debug ("X = %d\n", x);
showlist (The first, second, and third items.);
report (x>y, "x is %d but y is %d", x, y);
}
// Check long long types.
#define BIG64 18446744073709551615ull
#define BIG32 4294967295ul
#define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0)
#if !BIG_OK
your preprocessor is broken;
#endif
#if BIG_OK
#else
your preprocessor is broken;
#endif
static long long int bignum = -9223372036854775807LL;
static unsigned long long int ubignum = BIG64;
struct incomplete_array
{
int datasize;
double data[];
};
struct named_init {
int number;
const wchar_t *name;
double average;
};
typedef const char *ccp;
static inline int
test_restrict (ccp restrict text)
{
// See if C++-style comments work.
// Iterate through items via the restricted pointer.
// Also check for declarations in for loops.
for (unsigned int i = 0; *(text+i) != '\0'; ++i)
continue;
return 0;
}
// Check varargs and va_copy.
static void
test_varargs (const char *format, ...)
{
va_list args;
va_start (args, format);
va_list args_copy;
va_copy (args_copy, args);
const char *str;
int number;
float fnumber;
while (*format)
{
switch (*format++)
{
case 's': // string
str = va_arg (args_copy, const char *);
break;
case 'd': // int
number = va_arg (args_copy, int);
break;
case 'f': // float
fnumber = va_arg (args_copy, double);
break;
default:
break;
}
}
va_end (args_copy);
va_end (args);
}
int
main ()
{
// Check bool.
_Bool success = false;
// Check restrict.
if (test_restrict ("String literal") == 0)
success = true;
char *restrict newvar = "Another string";
// Check varargs.
test_varargs ("s, d' f .", "string", 65, 34.234);
test_varargs_macros ();
// Check flexible array members.
struct incomplete_array *ia =
malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10));
ia->datasize = 10;
for (int i = 0; i < ia->datasize; ++i)
ia->data[i] = i * 1.234;
// Check named initializers.
struct named_init ni = {
.number = 34,
.name = L"Test wide string",
.average = 543.34343,
};
ni.number = 58;
int dynamic_array[ni.number];
dynamic_array[ni.number - 1] = 543;
// work around unused variable warnings
return (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == 'x'
|| dynamic_array[ni.number - 1] != 543);
;
return 0;
}
_ACEOF
for ac_arg in '' -std=gnu99 -std=c99 -c99 -AC99 -D_STDC_C99= -qlanglvl=extc99
do
CC="$ac_save_CC $ac_arg"
if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_prog_cc_c99=$ac_arg
fi
rm -f core conftest.err conftest.$ac_objext
test "x$ac_cv_prog_cc_c99" != "xno" && break
done
rm -f conftest.$ac_ext
CC=$ac_save_CC
fi
# AC_CACHE_VAL
case "x$ac_cv_prog_cc_c99" in
x)
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
$as_echo "none needed" >&6; } ;;
xno)
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
$as_echo "unsupported" >&6; } ;;
*)
CC="$CC $ac_cv_prog_cc_c99"
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5
$as_echo "$ac_cv_prog_cc_c99" >&6; } ;;
esac
if test "x$ac_cv_prog_cc_c99" != xno; then :
ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
if ${ac_cv_prog_cc_c89+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_cv_prog_cc_c89=no
ac_save_CC=$CC
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include
#include
struct stat;
/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
struct buf { int x; };
FILE * (*rcsopen) (struct buf *, struct stat *, int);
static char *e (p, i)
char **p;
int i;
{
return p[i];
}
static char *f (char * (*g) (char **, int), char **p, ...)
{
char *s;
va_list v;
va_start (v,p);
s = g (p, va_arg (v,int));
va_end (v);
return s;
}
/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
function prototypes and stuff, but not '\xHH' hex character constants.
These don't provoke an error unfortunately, instead are silently treated
as 'x'. The following induces an error, until -std is added to get
proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
array size at least. It's necessary to write '\x00'==0 to get something
that's true only with -std. */
int osf4_cc_array ['\x00' == 0 ? 1 : -1];
/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
inside strings and character constants. */
#define FOO(x) 'x'
int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
int test (int i, double x);
struct s1 {int (*f) (int a);};
struct s2 {int (*f) (double a);};
int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
int argc;
char **argv;
int
main ()
{
return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
;
return 0;
}
_ACEOF
for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
-Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
do
CC="$ac_save_CC $ac_arg"
if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_prog_cc_c89=$ac_arg
fi
rm -f core conftest.err conftest.$ac_objext
test "x$ac_cv_prog_cc_c89" != "xno" && break
done
rm -f conftest.$ac_ext
CC=$ac_save_CC
fi
# AC_CACHE_VAL
case "x$ac_cv_prog_cc_c89" in
x)
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
$as_echo "none needed" >&6; } ;;
xno)
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
$as_echo "unsupported" >&6; } ;;
*)
CC="$CC $ac_cv_prog_cc_c89"
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
esac
if test "x$ac_cv_prog_cc_c89" != xno; then :
ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89
else
ac_cv_prog_cc_stdc=no
fi
fi
;;
esac
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO Standard C" >&5
$as_echo_n "checking for $CC option to accept ISO Standard C... " >&6; }
if ${ac_cv_prog_cc_stdc+:} false; then :
$as_echo_n "(cached) " >&6
fi
case $ac_cv_prog_cc_stdc in #(
no) :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
$as_echo "unsupported" >&6; } ;; #(
'') :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
$as_echo "none needed" >&6; } ;; #(
*) :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_stdc" >&5
$as_echo "$ac_cv_prog_cc_stdc" >&6; } ;;
esac
# Extract the first word of "perl", so it can be a program name with args.
set dummy perl; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_path_PERL+:} false; then :
$as_echo_n "(cached) " >&6
else
case $PERL in
[\\/]* | ?:[\\/]*)
ac_cv_path_PERL="$PERL" # Let the user override the test with a path.
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_path_PERL="$as_dir/$ac_word$ac_exec_ext"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
;;
esac
fi
PERL=$ac_cv_path_PERL
if test -n "$PERL"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $PERL" >&5
$as_echo "$PERL" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
$as_echo "#define _GNU_SOURCE 1" >>confdefs.h
if test x"$ac_cv_prog_cc_stdc" = x"no"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: rsync requires an ANSI C compiler and you do not seem to have one" >&5
$as_echo "$as_me: WARNING: rsync requires an ANSI C compiler and you do not seem to have one" >&2;}
fi
# Check whether --enable-profile was given.
if test "${enable_profile+set}" = set; then :
enableval=$enable_profile;
fi
if test x"$enable_profile" = x"yes"; then
CFLAGS="$CFLAGS -pg"
fi
# Specifically, this turns on panic_action handling.
# Check whether --enable-maintainer-mode was given.
if test "${enable_maintainer_mode+set}" = set; then :
enableval=$enable_maintainer_mode;
fi
if test x"$enable_maintainer_mode" = x"yes"; then
CFLAGS="$CFLAGS -DMAINTAINER_MODE"
fi
# This is needed for our included version of popt. Kind of silly, but
# I don't want our version too far out of sync.
CFLAGS="$CFLAGS -DHAVE_CONFIG_H"
# If GCC, turn on warnings.
if test x"$GCC" = x"yes"; then
CFLAGS="$CFLAGS -Wall -W"
fi
# Check whether --with-included-popt was given.
if test "${with_included_popt+set}" = set; then :
withval=$with_included_popt;
fi
# Check whether --with-included-zlib was given.
if test "${with_included_zlib+set}" = set; then :
withval=$with_included_zlib;
fi
# Check whether --with-protected-args was given.
if test "${with_protected_args+set}" = set; then :
withval=$with_protected_args;
fi
if test x"$with_protected_args" = x"yes"; then
cat >>confdefs.h <<_ACEOF
#define RSYNC_USE_PROTECTED_ARGS 1
_ACEOF
fi
# Check whether --with-rsync-path was given.
if test "${with_rsync_path+set}" = set; then :
withval=$with_rsync_path; RSYNC_PATH="$with_rsync_path"
else
RSYNC_PATH="rsync"
fi
cat >>confdefs.h <<_ACEOF
#define RSYNC_PATH "$RSYNC_PATH"
_ACEOF
# Check whether --with-rsyncd-conf was given.
if test "${with_rsyncd_conf+set}" = set; then :
withval=$with_rsyncd_conf; if test ! -z "$with_rsyncd_conf" ; then
case $with_rsyncd_conf in
yes|no)
RSYNCD_SYSCONF="/etc/rsyncd.conf"
;;
/*)
RSYNCD_SYSCONF="$with_rsyncd_conf"
;;
*)
as_fn_error $? "You must specify an absolute path to --with-rsyncd-conf=PATH" "$LINENO" 5
;;
esac
else
RSYNCD_SYSCONF="/etc/rsyncd.conf"
fi
else
RSYNCD_SYSCONF="/etc/rsyncd.conf"
fi
cat >>confdefs.h <<_ACEOF
#define RSYNCD_SYSCONF "$RSYNCD_SYSCONF"
_ACEOF
# Check whether --with-rsh was given.
if test "${with_rsh+set}" = set; then :
withval=$with_rsh;
fi
# Extract the first word of "remsh", so it can be a program name with args.
set dummy remsh; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_prog_HAVE_REMSH+:} false; then :
$as_echo_n "(cached) " >&6
else
if test -n "$HAVE_REMSH"; then
ac_cv_prog_HAVE_REMSH="$HAVE_REMSH" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_prog_HAVE_REMSH="1"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
test -z "$ac_cv_prog_HAVE_REMSH" && ac_cv_prog_HAVE_REMSH="0"
fi
fi
HAVE_REMSH=$ac_cv_prog_HAVE_REMSH
if test -n "$HAVE_REMSH"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $HAVE_REMSH" >&5
$as_echo "$HAVE_REMSH" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
if test x$HAVE_REMSH = x1; then
$as_echo "#define HAVE_REMSH 1" >>confdefs.h
fi
if test x"$with_rsh" != x; then
RSYNC_RSH="$with_rsh"
else
RSYNC_RSH="ssh"
fi
cat >>confdefs.h <<_ACEOF
#define RSYNC_RSH "$RSYNC_RSH"
_ACEOF
# Extract the first word of "yodl2man", so it can be a program name with args.
set dummy yodl2man; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_prog_HAVE_YODL2MAN+:} false; then :
$as_echo_n "(cached) " >&6
else
if test -n "$HAVE_YODL2MAN"; then
ac_cv_prog_HAVE_YODL2MAN="$HAVE_YODL2MAN" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_prog_HAVE_YODL2MAN="1"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
test -z "$ac_cv_prog_HAVE_YODL2MAN" && ac_cv_prog_HAVE_YODL2MAN="0"
fi
fi
HAVE_YODL2MAN=$ac_cv_prog_HAVE_YODL2MAN
if test -n "$HAVE_YODL2MAN"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $HAVE_YODL2MAN" >&5
$as_echo "$HAVE_YODL2MAN" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
if test x$HAVE_YODL2MAN = x1; then
MAKE_MAN=man
else
MAKE_MAN=man-copy
fi
# Some programs on solaris are only found in /usr/xpg4/bin (or work better than others versions).
# Extract the first word of "sh", so it can be a program name with args.
set dummy sh; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_path_SHELL_PATH+:} false; then :
$as_echo_n "(cached) " >&6
else
case $SHELL_PATH in
[\\/]* | ?:[\\/]*)
ac_cv_path_SHELL_PATH="$SHELL_PATH" # Let the user override the test with a path.
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in /usr/xpg4/bin$PATH_SEPARATOR$PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_path_SHELL_PATH="$as_dir/$ac_word$ac_exec_ext"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
test -z "$ac_cv_path_SHELL_PATH" && ac_cv_path_SHELL_PATH="/bin/sh"
;;
esac
fi
SHELL_PATH=$ac_cv_path_SHELL_PATH
if test -n "$SHELL_PATH"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $SHELL_PATH" >&5
$as_echo "$SHELL_PATH" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
# Extract the first word of "fakeroot", so it can be a program name with args.
set dummy fakeroot; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_path_FAKEROOT_PATH+:} false; then :
$as_echo_n "(cached) " >&6
else
case $FAKEROOT_PATH in
[\\/]* | ?:[\\/]*)
ac_cv_path_FAKEROOT_PATH="$FAKEROOT_PATH" # Let the user override the test with a path.
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in /usr/xpg4/bin$PATH_SEPARATOR$PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_path_FAKEROOT_PATH="$as_dir/$ac_word$ac_exec_ext"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
test -z "$ac_cv_path_FAKEROOT_PATH" && ac_cv_path_FAKEROOT_PATH="/usr/bin/fakeroot"
;;
esac
fi
FAKEROOT_PATH=$ac_cv_path_FAKEROOT_PATH
if test -n "$FAKEROOT_PATH"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $FAKEROOT_PATH" >&5
$as_echo "$FAKEROOT_PATH" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
# Check whether --with-nobody-group was given.
if test "${with_nobody_group+set}" = set; then :
withval=$with_nobody_group; NOBODY_GROUP="$with_nobody_group"
fi
if test x"$with_nobody_group" = x; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the group for user \"nobody\"" >&5
$as_echo_n "checking the group for user \"nobody\"... " >&6; }
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
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $NOBODY_GROUP" >&5
$as_echo "$NOBODY_GROUP" >&6; }
fi
cat >>confdefs.h <<_ACEOF
#define NOBODY_USER "nobody"
_ACEOF
cat >>confdefs.h <<_ACEOF
#define NOBODY_GROUP "$NOBODY_GROUP"
_ACEOF
# arrgh. libc in some old debian version screwed up the largefile
# stuff, getting byte range locking wrong
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for broken largefile support" >&5
$as_echo_n "checking for broken largefile support... " >&6; }
if ${rsync_cv_HAVE_BROKEN_LARGEFILE+:} false; then :
$as_echo_n "(cached) " >&6
else
if test "$cross_compiling" = yes; then :
rsync_cv_HAVE_BROKEN_LARGEFILE=cross
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#define _FILE_OFFSET_BITS 64
#include
#include
#include
#include
int main(void)
{
struct flock lock;
int status;
char tpl[32] = "/tmp/locktest.XXXXXX";
int fd = mkstemp(tpl);
if (fd < 0) {
strcpy(tpl, "conftest.dat");
fd = open(tpl, O_CREAT|O_RDWR, 0600);
}
lock.l_type = F_WRLCK;
lock.l_whence = SEEK_SET;
lock.l_start = 0;
lock.l_len = 1;
lock.l_pid = 0;
fcntl(fd,F_SETLK,&lock);
if (fork() == 0) {
lock.l_start = 1;
_exit(fcntl(fd,F_SETLK,&lock) == 0);
}
wait(&status);
unlink(tpl);
exit(WEXITSTATUS(status));
}
_ACEOF
if ac_fn_c_try_run "$LINENO"; then :
rsync_cv_HAVE_BROKEN_LARGEFILE=yes
else
rsync_cv_HAVE_BROKEN_LARGEFILE=no
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $rsync_cv_HAVE_BROKEN_LARGEFILE" >&5
$as_echo "$rsync_cv_HAVE_BROKEN_LARGEFILE" >&6; }
if test x"$rsync_cv_HAVE_BROKEN_LARGEFILE" != x"yes"; then
# Check whether --enable-largefile was given.
if test "${enable_largefile+set}" = set; then :
enableval=$enable_largefile;
fi
if test "$enable_largefile" != no; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for special C compiler options needed for large files" >&5
$as_echo_n "checking for special C compiler options needed for large files... " >&6; }
if ${ac_cv_sys_largefile_CC+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_cv_sys_largefile_CC=no
if test "$GCC" != yes; then
ac_save_CC=$CC
while :; do
# IRIX 6.2 and later do not support large files by default,
# so use the C compiler's -n32 option if that helps.
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include
/* Check that off_t can represent 2**63 - 1 correctly.
We can't simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1)
? 1 : -1];
int
main ()
{
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
break
fi
rm -f core conftest.err conftest.$ac_objext
CC="$CC -n32"
if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_sys_largefile_CC=' -n32'; break
fi
rm -f core conftest.err conftest.$ac_objext
break
done
CC=$ac_save_CC
rm -f conftest.$ac_ext
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_CC" >&5
$as_echo "$ac_cv_sys_largefile_CC" >&6; }
if test "$ac_cv_sys_largefile_CC" != no; then
CC=$CC$ac_cv_sys_largefile_CC
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for _FILE_OFFSET_BITS value needed for large files" >&5
$as_echo_n "checking for _FILE_OFFSET_BITS value needed for large files... " >&6; }
if ${ac_cv_sys_file_offset_bits+:} false; then :
$as_echo_n "(cached) " >&6
else
while :; do
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include
/* Check that off_t can represent 2**63 - 1 correctly.
We can't simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1)
? 1 : -1];
int
main ()
{
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_sys_file_offset_bits=no; break
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#define _FILE_OFFSET_BITS 64
#include
/* Check that off_t can represent 2**63 - 1 correctly.
We can't simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1)
? 1 : -1];
int
main ()
{
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_sys_file_offset_bits=64; break
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
ac_cv_sys_file_offset_bits=unknown
break
done
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_file_offset_bits" >&5
$as_echo "$ac_cv_sys_file_offset_bits" >&6; }
case $ac_cv_sys_file_offset_bits in #(
no | unknown) ;;
*)
cat >>confdefs.h <<_ACEOF
#define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits
_ACEOF
;;
esac
rm -rf conftest*
if test $ac_cv_sys_file_offset_bits = unknown; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for _LARGE_FILES value needed for large files" >&5
$as_echo_n "checking for _LARGE_FILES value needed for large files... " >&6; }
if ${ac_cv_sys_large_files+:} false; then :
$as_echo_n "(cached) " >&6
else
while :; do
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include
/* Check that off_t can represent 2**63 - 1 correctly.
We can't simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1)
? 1 : -1];
int
main ()
{
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_sys_large_files=no; break
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#define _LARGE_FILES 1
#include
/* Check that off_t can represent 2**63 - 1 correctly.
We can't simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1)
? 1 : -1];
int
main ()
{
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_sys_large_files=1; break
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
ac_cv_sys_large_files=unknown
break
done
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_large_files" >&5
$as_echo "$ac_cv_sys_large_files" >&6; }
case $ac_cv_sys_large_files in #(
no | unknown) ;;
*)
cat >>confdefs.h <<_ACEOF
#define _LARGE_FILES $ac_cv_sys_large_files
_ACEOF
;;
esac
rm -rf conftest*
fi
fi
fi
ipv6type=unknown
ipv6lib=none
ipv6trylibc=yes
# Check whether --enable-ipv6 was given.
if test "${enable_ipv6+set}" = set; then :
enableval=$enable_ipv6;
fi
if test x"$enable_ipv6" != x"no"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking ipv6 stack type" >&5
$as_echo_n "checking ipv6 stack type... " >&6; }
for i in inria kame linux-glibc linux-inet6 solaris toshiba v6d zeta cygwin; do
case $i in
inria)
# http://www.kame.net/
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include
#ifdef IPV6_INRIA_VERSION
yes
#endif
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
$EGREP "yes" >/dev/null 2>&1; then :
ipv6type=$i;
$as_echo "#define INET6 1" >>confdefs.h
fi
rm -f conftest*
;;
kame)
# http://www.kame.net/
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include
#ifdef __KAME__
yes
#endif
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
$EGREP "yes" >/dev/null 2>&1; then :
ipv6type=$i;
$as_echo "#define INET6 1" >>confdefs.h
fi
rm -f conftest*
;;
linux-glibc)
# http://www.v6.linux.or.jp/
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include
#if defined(__GLIBC__) && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1
yes
#endif
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
$EGREP "yes" >/dev/null 2>&1; then :
ipv6type=$i;
$as_echo "#define INET6 1" >>confdefs.h
fi
rm -f conftest*
;;
linux-inet6)
# http://www.v6.linux.or.jp/
if test -d /usr/inet6 -o -f /usr/inet6/lib/libinet6.a; then
ipv6type=$i
ipv6lib=inet6
ipv6libdir=/usr/inet6/lib
ipv6trylibc=yes;
$as_echo "#define INET6 1" >>confdefs.h
CFLAGS="-I/usr/inet6/include $CFLAGS"
fi
;;
solaris)
# http://www.sun.com
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include
#ifdef __sun
yes
#endif
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
$EGREP "yes" >/dev/null 2>&1; then :
ipv6type=$i;
$as_echo "#define INET6 1" >>confdefs.h
fi
rm -f conftest*
;;
toshiba)
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include
#ifdef _TOSHIBA_INET6
yes
#endif
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
$EGREP "yes" >/dev/null 2>&1; then :
ipv6type=$i;
ipv6lib=inet6;
ipv6libdir=/usr/local/v6/lib;
$as_echo "#define INET6 1" >>confdefs.h
fi
rm -f conftest*
;;
v6d)
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include
#ifdef __V6D__
yes
#endif
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
$EGREP "yes" >/dev/null 2>&1; then :
ipv6type=$i;
ipv6lib=v6;
ipv6libdir=/usr/local/v6/lib;
$as_echo "#define INET6 1" >>confdefs.h
fi
rm -f conftest*
;;
zeta)
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include