Import Upstream version 2.7.6

This commit is contained in:
openKylinBot 2022-05-14 02:38:20 +08:00
commit 9c1d3c7169
529 changed files with 161822 additions and 0 deletions

1
.tarball-version Normal file
View File

@ -0,0 +1 @@
2.7.6

1
.version Normal file
View File

@ -0,0 +1 @@
2.7.6

11
AUTHORS Normal file
View File

@ -0,0 +1,11 @@
Larry Wall wrote the original version of `patch'.
Paul Eggert removed arbitrary limits; added support for binary
files, setting file times, and deleting files; and made it conform
better to POSIX.
Wayne Davison added unidiff support.
David MacKenzie added configuration and backup support.
Andreas Gruenbacher added merge support.

674
COPYING Normal file
View File

@ -0,0 +1,674 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
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.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
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 <http://www.gnu.org/licenses/>.
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:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, 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
<http://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.

1351
ChangeLog Normal file

File diff suppressed because it is too large Load Diff

3680
ChangeLog-2011 Normal file

File diff suppressed because it is too large Load Diff

127
GNUmakefile Normal file
View File

@ -0,0 +1,127 @@
# Having a separate GNUmakefile lets me 'include' the dynamically
# generated rules created via cfg.mk (package-local configuration)
# as well as maint.mk (generic maintainer rules).
# This makefile is used only if you run GNU Make.
# It is necessary if you want to build targets usually of interest
# only to the maintainer.
# Copyright (C) 2001, 2003, 2006-2018 Free Software Foundation, Inc.
# 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 <https://www.gnu.org/licenses/>.
# If the user runs GNU make but has not yet run ./configure,
# give them a diagnostic.
_gl-Makefile := $(wildcard [M]akefile)
ifneq ($(_gl-Makefile),)
# Make tar archive easier to reproduce.
export TAR_OPTIONS = --owner=0 --group=0 --numeric-owner
# Allow the user to add to this in the Makefile.
ALL_RECURSIVE_TARGETS =
include Makefile
# Some projects override e.g., _autoreconf here.
-include $(srcdir)/cfg.mk
# Allow cfg.mk to override these.
_build-aux ?= build-aux
_autoreconf ?= autoreconf -v
include $(srcdir)/maint.mk
# Ensure that $(VERSION) is up to date for dist-related targets, but not
# for others: rerunning autoreconf and recompiling everything isn't cheap.
_have-git-version-gen := \
$(shell test -f $(srcdir)/$(_build-aux)/git-version-gen && echo yes)
ifeq ($(_have-git-version-gen)0,yes$(MAKELEVEL))
_is-dist-target ?= $(filter-out %clean, \
$(filter maintainer-% dist% alpha beta stable,$(MAKECMDGOALS)))
_is-install-target ?= $(filter-out %check, $(filter install%,$(MAKECMDGOALS)))
ifneq (,$(_is-dist-target)$(_is-install-target))
_curr-ver := $(shell cd $(srcdir) \
&& $(_build-aux)/git-version-gen \
.tarball-version \
$(git-version-gen-tag-sed-script))
ifneq ($(_curr-ver),$(VERSION))
ifeq ($(_curr-ver),UNKNOWN)
$(info WARNING: unable to verify if $(VERSION) is the correct version)
else
ifneq (,$(_is-install-target))
# GNU Coding Standards state that 'make install' should not cause
# recompilation after 'make all'. But as long as changing the version
# string alters config.h, the cost of having 'make all' always have an
# up-to-date version is prohibitive. So, as a compromise, we merely
# warn when installing a version string that is out of date; the user
# should run 'autoreconf' (or something like 'make distcheck') to
# fix the version, 'make all' to propagate it, then 'make install'.
$(info WARNING: version string $(VERSION) is out of date;)
$(info run '$(MAKE) _version' to fix it)
else
$(info INFO: running autoreconf for new version string: $(_curr-ver))
GNUmakefile: _version
touch GNUmakefile
endif
endif
endif
endif
endif
.PHONY: _version
_version:
cd $(srcdir) && rm -rf autom4te.cache .version && $(_autoreconf)
$(MAKE) $(AM_MAKEFLAGS) Makefile
else
.DEFAULT_GOAL := abort-due-to-no-makefile
srcdir = .
# The package can override .DEFAULT_GOAL to run actions like autoreconf.
-include ./cfg.mk
# Allow cfg.mk to override these.
_build-aux ?= build-aux
_autoreconf ?= autoreconf -v
include ./maint.mk
ifeq ($(.DEFAULT_GOAL),abort-due-to-no-makefile)
$(MAKECMDGOALS): abort-due-to-no-makefile
endif
abort-due-to-no-makefile:
@echo There seems to be no Makefile in this directory. 1>&2
@echo "You must run ./configure before running 'make'." 1>&2
@exit 1
endif
# Tell version 3.79 and up of GNU make to not build goals in this
# directory in parallel, in case someone tries to build multiple
# targets, and one of them can cause a recursive target to be invoked.
# Only set this if Automake doesn't provide it.
AM_RECURSIVE_TARGETS ?= $(RECURSIVE_TARGETS:-recursive=) \
$(RECURSIVE_CLEAN_TARGETS:-recursive=) \
dist distcheck tags ctags
ALL_RECURSIVE_TARGETS += $(AM_RECURSIVE_TARGETS)
ifneq ($(word 2, $(MAKECMDGOALS)), )
ifneq ($(filter $(ALL_RECURSIVE_TARGETS), $(MAKECMDGOALS)), )
.NOTPARALLEL:
endif
endif

368
INSTALL Normal file
View File

@ -0,0 +1,368 @@
Installation Instructions
*************************
Copyright (C) 1994-1996, 1999-2002, 2004-2016 Free Software
Foundation, Inc.
Copying and distribution of this file, with or without modification,
are permitted in any medium without royalty provided the copyright
notice and this notice are preserved. This file is offered as-is,
without warranty of any kind.
Basic Installation
==================
Briefly, the shell command './configure && make && make install'
should configure, build, and install this package. The following
more-detailed instructions are generic; see the 'README' file for
instructions specific to this package. Some packages provide this
'INSTALL' file but do not implement all of the features documented
below. The lack of an optional feature in a given package is not
necessarily a bug. More recommendations for GNU packages can be found
in *note Makefile Conventions: (standards)Makefile Conventions.
The 'configure' shell script attempts to guess correct values for
various system-dependent variables used during compilation. It uses
those values to create a 'Makefile' in each directory of the package.
It may also create one or more '.h' files containing system-dependent
definitions. Finally, it creates a shell script 'config.status' that
you can run in the future to recreate the current configuration, and a
file 'config.log' containing compiler output (useful mainly for
debugging 'configure').
It can also use an optional file (typically called 'config.cache' and
enabled with '--cache-file=config.cache' or simply '-C') that saves the
results of its tests to speed up reconfiguring. Caching is disabled by
default to prevent problems with accidental use of stale cache files.
If you need to do unusual things to compile the package, please try
to figure out how 'configure' could check whether to do them, and mail
diffs or instructions to the address given in the 'README' so they can
be considered for the next release. If you are using the cache, and at
some point 'config.cache' contains results you don't want to keep, you
may remove or edit it.
The file 'configure.ac' (or 'configure.in') is used to create
'configure' by a program called 'autoconf'. You need 'configure.ac' if
you want to change it or regenerate 'configure' using a newer version of
'autoconf'.
The simplest way to compile this package is:
1. 'cd' to the directory containing the package's source code and type
'./configure' to configure the package for your system.
Running 'configure' might take a while. While running, it prints
some messages telling which features it is checking for.
2. Type 'make' to compile the package.
3. Optionally, type 'make check' to run any self-tests that come with
the package, generally using the just-built uninstalled binaries.
4. Type 'make install' to install the programs and any data files and
documentation. When installing into a prefix owned by root, it is
recommended that the package be configured and built as a regular
user, and only the 'make install' phase executed with root
privileges.
5. Optionally, type 'make installcheck' to repeat any self-tests, but
this time using the binaries in their final installed location.
This target does not install anything. Running this target as a
regular user, particularly if the prior 'make install' required
root privileges, verifies that the installation completed
correctly.
6. You can remove the program binaries and object files from the
source code directory by typing 'make clean'. To also remove the
files that 'configure' created (so you can compile the package for
a different kind of computer), type 'make distclean'. There is
also a 'make maintainer-clean' target, but that is intended mainly
for the package's developers. If you use it, you may have to get
all sorts of other programs in order to regenerate files that came
with the distribution.
7. Often, you can also type 'make uninstall' to remove the installed
files again. In practice, not all packages have tested that
uninstallation works correctly, even though it is required by the
GNU Coding Standards.
8. Some packages, particularly those that use Automake, provide 'make
distcheck', which can by used by developers to test that all other
targets like 'make install' and 'make uninstall' work correctly.
This target is generally not run by end users.
Compilers and Options
=====================
Some systems require unusual options for compilation or linking that
the 'configure' script does not know about. Run './configure --help'
for details on some of the pertinent environment variables.
You can give 'configure' initial values for configuration parameters
by setting variables in the command line or in the environment. Here is
an example:
./configure CC=c99 CFLAGS=-g LIBS=-lposix
*Note Defining Variables::, for more details.
Compiling For Multiple Architectures
====================================
You can compile the package for more than one kind of computer at the
same time, by placing the object files for each architecture in their
own directory. To do this, you can use GNU 'make'. 'cd' to the
directory where you want the object files and executables to go and run
the 'configure' script. 'configure' automatically checks for the source
code in the directory that 'configure' is in and in '..'. This is known
as a "VPATH" build.
With a non-GNU 'make', it is safer to compile the package for one
architecture at a time in the source code directory. After you have
installed the package for one architecture, use 'make distclean' before
reconfiguring for another architecture.
On MacOS X 10.5 and later systems, you can create libraries and
executables that work on multiple system types--known as "fat" or
"universal" binaries--by specifying multiple '-arch' options to the
compiler but only a single '-arch' option to the preprocessor. Like
this:
./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
CPP="gcc -E" CXXCPP="g++ -E"
This is not guaranteed to produce working output in all cases, you
may have to build one architecture at a time and combine the results
using the 'lipo' tool if you have problems.
Installation Names
==================
By default, 'make install' installs the package's commands under
'/usr/local/bin', include files under '/usr/local/include', etc. You
can specify an installation prefix other than '/usr/local' by giving
'configure' the option '--prefix=PREFIX', where PREFIX must be an
absolute file name.
You can specify separate installation prefixes for
architecture-specific files and architecture-independent files. If you
pass the option '--exec-prefix=PREFIX' to 'configure', the package uses
PREFIX as the prefix for installing programs and libraries.
Documentation and other data files still use the regular prefix.
In addition, if you use an unusual directory layout you can give
options like '--bindir=DIR' to specify different values for particular
kinds of files. Run 'configure --help' for a list of the directories
you can set and what kinds of files go in them. In general, the default
for these options is expressed in terms of '${prefix}', so that
specifying just '--prefix' will affect all of the other directory
specifications that were not explicitly provided.
The most portable way to affect installation locations is to pass the
correct locations to 'configure'; however, many packages provide one or
both of the following shortcuts of passing variable assignments to the
'make install' command line to change installation locations without
having to reconfigure or recompile.
The first method involves providing an override variable for each
affected directory. For example, 'make install
prefix=/alternate/directory' will choose an alternate location for all
directory configuration variables that were expressed in terms of
'${prefix}'. Any directories that were specified during 'configure',
but not in terms of '${prefix}', must each be overridden at install time
for the entire installation to be relocated. The approach of makefile
variable overrides for each directory variable is required by the GNU
Coding Standards, and ideally causes no recompilation. However, some
platforms have known limitations with the semantics of shared libraries
that end up requiring recompilation when using this method, particularly
noticeable in packages that use GNU Libtool.
The second method involves providing the 'DESTDIR' variable. For
example, 'make install DESTDIR=/alternate/directory' will prepend
'/alternate/directory' before all installation names. The approach of
'DESTDIR' overrides is not required by the GNU Coding Standards, and
does not work on platforms that have drive letters. On the other hand,
it does better at avoiding recompilation issues, and works well even
when some directory options were not specified in terms of '${prefix}'
at 'configure' time.
Optional Features
=================
If the package supports it, you can cause programs to be installed
with an extra prefix or suffix on their names by giving 'configure' the
option '--program-prefix=PREFIX' or '--program-suffix=SUFFIX'.
Some packages pay attention to '--enable-FEATURE' options to
'configure', where FEATURE indicates an optional part of the package.
They may also pay attention to '--with-PACKAGE' options, where PACKAGE
is something like 'gnu-as' or 'x' (for the X Window System). The
'README' should mention any '--enable-' and '--with-' options that the
package recognizes.
For packages that use the X Window System, 'configure' can usually
find the X include and library files automatically, but if it doesn't,
you can use the 'configure' options '--x-includes=DIR' and
'--x-libraries=DIR' to specify their locations.
Some packages offer the ability to configure how verbose the
execution of 'make' will be. For these packages, running './configure
--enable-silent-rules' sets the default to minimal output, which can be
overridden with 'make V=1'; while running './configure
--disable-silent-rules' sets the default to verbose, which can be
overridden with 'make V=0'.
Particular systems
==================
On HP-UX, the default C compiler is not ANSI C compatible. If GNU CC
is not installed, it is recommended to use the following options in
order to use an ANSI C compiler:
./configure CC="cc -Ae -D_XOPEN_SOURCE=500"
and if that doesn't work, install pre-built binaries of GCC for HP-UX.
HP-UX 'make' updates targets which have the same time stamps as their
prerequisites, which makes it generally unusable when shipped generated
files such as 'configure' are involved. Use GNU 'make' instead.
On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
parse its '<wchar.h>' header file. The option '-nodtk' can be used as a
workaround. If GNU CC is not installed, it is therefore recommended to
try
./configure CC="cc"
and if that doesn't work, try
./configure CC="cc -nodtk"
On Solaris, don't put '/usr/ucb' early in your 'PATH'. This
directory contains several dysfunctional programs; working variants of
these programs are available in '/usr/bin'. So, if you need '/usr/ucb'
in your 'PATH', put it _after_ '/usr/bin'.
On Haiku, software installed for all users goes in '/boot/common',
not '/usr/local'. It is recommended to use the following options:
./configure --prefix=/boot/common
Specifying the System Type
==========================
There may be some features 'configure' cannot figure out
automatically, but needs to determine by the type of machine the package
will run on. Usually, assuming the package is built to be run on the
_same_ architectures, 'configure' can figure that out, but if it prints
a message saying it cannot guess the machine type, give it the
'--build=TYPE' option. TYPE can either be a short name for the system
type, such as 'sun4', or a canonical name which has the form:
CPU-COMPANY-SYSTEM
where SYSTEM can have one of these forms:
OS
KERNEL-OS
See the file 'config.sub' for the possible values of each field. If
'config.sub' isn't included in this package, then this package doesn't
need to know the machine type.
If you are _building_ compiler tools for cross-compiling, you should
use the option '--target=TYPE' to select the type of system they will
produce code for.
If you want to _use_ a cross compiler, that generates code for a
platform different from the build platform, you should specify the
"host" platform (i.e., that on which the generated programs will
eventually be run) with '--host=TYPE'.
Sharing Defaults
================
If you want to set default values for 'configure' scripts to share,
you can create a site shell script called 'config.site' that gives
default values for variables like 'CC', 'cache_file', and 'prefix'.
'configure' looks for 'PREFIX/share/config.site' if it exists, then
'PREFIX/etc/config.site' if it exists. Or, you can set the
'CONFIG_SITE' environment variable to the location of the site script.
A warning: not all 'configure' scripts look for a site script.
Defining Variables
==================
Variables not defined in a site shell script can be set in the
environment passed to 'configure'. However, some packages may run
configure again during the build, and the customized values of these
variables may be lost. In order to avoid this problem, you should set
them in the 'configure' command line, using 'VAR=value'. For example:
./configure CC=/usr/local2/bin/gcc
causes the specified 'gcc' to be used as the C compiler (unless it is
overridden in the site shell script).
Unfortunately, this technique does not work for 'CONFIG_SHELL' due to an
Autoconf limitation. Until the limitation is lifted, you can use this
workaround:
CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash
'configure' Invocation
======================
'configure' recognizes the following options to control how it
operates.
'--help'
'-h'
Print a summary of all of the options to 'configure', and exit.
'--help=short'
'--help=recursive'
Print a summary of the options unique to this package's
'configure', and exit. The 'short' variant lists options used only
in the top level, while the 'recursive' variant lists options also
present in any nested packages.
'--version'
'-V'
Print the version of Autoconf used to generate the 'configure'
script, and exit.
'--cache-file=FILE'
Enable the cache: use and save the results of the tests in FILE,
traditionally 'config.cache'. FILE defaults to '/dev/null' to
disable caching.
'--config-cache'
'-C'
Alias for '--cache-file=config.cache'.
'--quiet'
'--silent'
'-q'
Do not print messages saying which checks are being made. To
suppress all normal output, redirect it to '/dev/null' (any error
messages will still be shown).
'--srcdir=DIR'
Look for the package's source code in directory DIR. Usually
'configure' can determine that directory automatically.
'--prefix=DIR'
Use DIR as the installation prefix. *note Installation Names:: for
more details, including other options available for fine-tuning the
installation locations.
'--no-create'
'-n'
Run the configure checks, but stop before creating any output
files.
'configure' also accepts some other, not widely useful, options. Run
'configure --help' for more details.

55
Makefile.am Normal file
View File

@ -0,0 +1,55 @@
# Copyright (C) 1989-1993, 1997-1999, 2002-2003, 2006, 2009-2012 Free Software
# Foundation, Inc.
# 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 <http://www.gnu.org/licenses/>.
## Process this file with automake to produce Makefile.in.
ACLOCAL_AMFLAGS = -I m4
SUBDIRS = lib src tests
dist_man1_MANS = patch.man
EXTRA_DIST = \
ChangeLog-2011 \
cfg.mk \
m4/mkdir.m4 \
m4/setmode.m4 \
bootstrap \
pc
if ALPHA_VERSION
EXTRA_DIST += README-alpha
GNU_SERVER = alpha.gnu.org
RELEASE_TYPE = alpha
else
GNU_SERVER = ftp.gnu.org
RELEASE_TYPE = stable
endif
EXTRA_DIST += $(top_srcdir)/.version
BUILT_SOURCES = $(top_srcdir)/.version
$(top_srcdir)/.version:
echo $(VERSION) > $@-t && mv $@-t $@
dist-hook: gen-ChangeLog
echo $(VERSION) > $(distdir)/.tarball-version
gen_start_date = 2011-02-22
.PHONY: gen-ChangeLog
gen-ChangeLog:
$(AM_V_GEN)if test -d .git; then \
$(top_srcdir)/build-aux/gitlog-to-changelog \
--since=$(gen_start_date) > $(distdir)/cl-t; \
rm -f $(distdir)/ChangeLog; \
mv $(distdir)/cl-t $(distdir)/ChangeLog; \
fi

1761
Makefile.in Normal file

File diff suppressed because it is too large Load Diff

363
NEWS Normal file
View File

@ -0,0 +1,363 @@
Changes in version 2.7.6:
* Files specififed on the command line are no longer verified to be inside the
current working directory, so commands like "patch -i foo.diff ../foo" will
work again.
* Various fixes.
Changes in version 2.7.5:
* There are users which expect patch to follow symbolic links in the working
directory, so patch now again follows symbolic links as long as they do not
leave the working directory.
Changes until version 2.7.4:
* When a file isn't being deleted because the file contents don't match the
patch, the resulting message is now "Not deleting file ... as content
differs from patch" instead of "File ... is not empty after patch; not
deleting".
* Function names in hunks (from diff -p) are now preserved in reject files.
* Patch no longer follows symbolic links to input and output files. This
ensures that symbolic links created by git-style patches cannot cause
patch to write outside the working directory (CVE-2015-1196).
* Various fixes.
Changes in version 2.7.1:
* Two critical bug fixes in the "diff --git" format support.
* Clarify the message printed when a patch is expected to empty out and delete
a file, but the file does not become empty.
* Various improvements to messages when applying a patch to a file of different
type (regular file vs. symlink), when there are line ending differences (LF
vs. CRLF), and when in --dry-run mode.
* When in the root directory, allow file names that are absolute or that
contain a component of "..".
* New --follow-symlinks option to allow to treat symlinks as files: this was
patch's behavior before version 2.7.
* Ignore when extended attributes cannot be preserved because they are
unsupported or because permission to set them is denied.
* License clarifications in NEWS and README.
* Portability bug fixes.
Changes in version 2.7:
* Patch no longer gets a failed assertion for certain mangled patches.
* Ignore destination file names that are absolute or that contain a component
of "..". This addresses CVE-2010-4651.
* Support for most features of the "diff --git" format, including renames and
copies, permission changes, and symlink diffs. Binary diffs are not
supported yet; patch will complain and skip them.
* Support for double-quoted filenames: when a filename starts with a double
quote, it is interpreted as a C string literal. The escape sequences \\, \",
\a, \b, \f, \n, \r, \t, \v, and \ooo (a three-digit octal number between 0
and 255) are recognized.
* Refuse to apply a normal patch to a symlink. (Previous versions of patch
were replacing the symlink with a regular file.)
* When trying to modify a read-only file, warn about the potential problem
by default. The --read-only command line option allows to change this
behavior.
* Files to be deleted are deleted once the entire input has been processed, not
immediately. This fixes a bug with numbered backup files.
* When a timestamp specifies a time zone, honor that instead of assuming the
local time zone (--set-date) or Universal Coordinated Time (--set-utc).
* Support for nanosecond precision timestamps.
* Many portability and bug fixes.
Changes in version 2.6.1:
* Support for diff3(1) style merges which show the old, original, and new lines
of a conflict has been added (--merge=diff3). The default still is the
merge(1) format (--merge or --merge=merge).
* Bug and portability fixes.
Changes in version 2.6:
* A regression test suite has been added ("make check").
* A --merge option has been added which will merge a patch file into
the original files similar to merge(1). See the patch(1) manual page for
documentation.
* Unless a filename has been specified on the command line, look only
for filenames in the patch until one has been found. This prevents
patch from tripping over garbage that isn't a patch. When conforming
to POSIX, this behavior is turned off and patch will ask for a
filename if none is found.
* All reject files have file name headers, which allows them to be used as
regular patches.
* When a patch file modifies the same file more than once, patch makes
sure it backs up the original version of the file rather than any
intermediary versions.
* In the above situation, if there are rejects in more than one of those
patches, they all go into the same reject file.
* When the file to be patched is specified on the command line, all patches
are applied to that file. (Previously, the first patch was applied to the
file specified on the command line, and the names of additional files to
patch were taken from header lines in the patch file.)
* The -r option now works correctly even if there are rejects in more than
one file. Use the - argument to discard rejects.
* Rejected hunks come out in unified diff format if the input patch was of
that format, otherwise in ordinary context diff form. Use the
--reject-format option to enforce either "context" or "unified" format.
Timestamps and the "diff -p" (--show-c-function) output are preserved.
Changed lines in context format reject files are correctly indicated
with '!' markers as the format defines. Added and removed lines are
still marked with '+' and '-', respectively.
* The file permissions of reject files are no longer set to match the files
they modify. Instead, they retain the default permissions. This is
consistent with reject files produced with the -r option.
* The --binary option disables the heuristic for stripping CRs from
line endings in patches. This allows to preserve CRs even in mangled
patches, or in patches generated on non-POSIX systems and without the
--binary option.
* Backup files for nonexisting files are now created with default
permissions rather than with mode 0: backup files with mode 0 were
causing problems with applications which do not expect unreadable
files.
* The -B, -Y, and -z options (--prefix, --basename-prefix, --suffix) now
imply the simple version control mode, and can be combined.
* Patch rejects more malformed normal format commands and checks for trailing
garbage. It now recognizes ed commands without addresses.
* Change the default value of PATCH_GET to 0. (Previously, the default was 0
under POSIXLY_CORRECT and negative otherwise; this is causing problems
particularly with Perforce.)
* Handle missing timestamps better.
* Various bug fixes.
* Switch to GNU General Public License version 3.
Changes in versions 2.5.8 and 2.5.9: bug fixes only.
Changes in version 2.5.7:
* patch -D now outputs preprocessor lines without comments, as required
by POSIX 1003.1-2001.
Changes in version 2.5.6:
* File names in context patches may now contain spaces, so long
as the context patch headers use a tab to separate the file name
from the time stamp.
* Perforce is now supported.
* Patch lines beginning with "#" are comments and are ignored.
Changes in version 2.5.5:
* The bug reporting address is now <bug-patch@gnu.org>.
Changes in version 2.5.4:
* A security hole has been closed.
It involved race conditions with temporary files.
* The default quoting style is 'shell', which causes `patch' to quote
file names with funny characters like `$'. This prevents their
misinterpretation if you cut them from its output and paste them into
the shell.
* `patch' now works correctly with large files on Large File Summit
hosts like Solaris 2.6.
* `patch' now ignores trailing carriage returns in lines of context diffs
if the context diff headers end in carriage return.
* `patch' now ignores context diff header file names that have fewer slashes
than the count specified by the -p or --strip option.
* New options:
--posix
--quoting-style=WORD
* New environment variables:
QUOTING_STYLE
* `patch' now supports ClearCase version management.
Changes in version 2.5:
* Version control is now independent of whether backups are made.
The -V or --version-control option and the VERSION_CONTROL and
PATCH_VERSION_CONTROL environment variables no longer affect whether
backups are made; they affect only the names of the backup files.
* When asking the user whether to reverse a patch,
the default answer is now `no' instead of `yes'.
* `patch' can now recognize context diffs that have been encapsulated
by prepending "- " to lines beginning with "-" (as per Internet RFC 934).
* `patch' now reports an error if the input contains garbage and no patches.
Changes in version 2.4:
* New options:
-Z or --set-utc sets times of patched files, assuming diff uses UTC (GMT).
-T or --set-time is similar, assuming local time (not recommended).
--backup-if-mismatch makes a backup if the patch does not match exactly
--no-backup-if-mismatch makes a backup only if otherwise requested
* The default is now --backup-if-mismatch unless POSIXLY_CORRECT is set.
* The -B or --prefix, -Y or --basename-prefix, and -z or --suffix options
no longer affect whether backups are made (as they did in patch 2.2 and 2.3);
they now merely specify the file names used when simple backups are made.
* When patching a nonexistent file and making backups, an empty backup file
is now made (just as with traditional patch); but the backup file is
unreadable, as a way of indicating that it represents a nonexistent file.
* `patch' now matches against empty and nonexistent files more generously.
A patch against an empty file applies to a nonexistent file, and vice versa.
* -g or --get and PATCH_GET now have a numeric value that specifies
whether `patch' is getting files.
If the value is positive, working files are gotten from RCS or SCCS files;
if zero, `patch' ignores RCS and SCCS and working files are not gotten;
and if negative, `patch' asks the user whether to get each file.
The default is normally negative, but it is zero if POSIXLY_CORRECT is set.
* The -G or --no-get option introduced in GNU patch 2.3 has been removed;
use -g0 instead.
* The method used to intuit names of files to be patched is changed again:
`Index:' lines are normally ignored for context diffs,
and RCS and SCCS files are normally looked for when files do not exist.
The complete new method is described in the man page.
* By default, `patch' is now more verbose when patches do not match exactly.
* The manual page has a new COMPATIBILITY ISSUES section.
Changes in version 2.3:
* Unless the POSIXLY_CORRECT environment variable is set:
- `patch' now distinguishes more accurately between empty and
nonexistent files if the input is a context diff.
A file is assumed to not exist if its context diff header
suggests that it is empty, and if the header timestamp
looks like it might be equivalent to 1970-01-01 00:00:00 UTC.
- Files that ``become nonexistent'' after patching are now removed.
When a file is removed, any empty ancestor directories are also removed.
* Files are now automatically gotten from RCS and SCCS
if the -g or --get option is specified.
(The -G or --no-get option, also introduced in 2.3, was withdrawn in 2.4.)
* If the PATCH_VERSION_CONTROL environment variable is set,
it overrides the VERSION_CONTROL environment variable.
* The method used to intuit names of files to be patched is changed.
(It was further revised in 2.4; see above.)
* The new --binary option makes `patch' read and write files in binary mode.
This option has no effect on POSIX-compliant hosts;
it is useful only in on operating systems like DOS
that distinguish between text and binary I/O.
* The environment variables TMP and TEMP are consulted for the name of
the temporary directory if TMPDIR is not set.
* A port to MS-DOS and MS-Windows is available; see the `pc' directory.
* Backup file names are no longer ever computed by uppercasing characters,
since this isn't portable to systems with case-insensitive file names.
Changes in version 2.2:
* Arbitrary limits removed (e.g. line length, file name length).
* On POSIX.1-compliant hosts, you can now patch binary files using the output
of GNU `diff -a'.
* New options:
--dry-run
--help
--verbose
-i FILE or --input=FILE
-Y PREF or --basename-prefix=PREF
* patch is now quieter by default; use --verbose for the old chatty behavior.
* Patch now complies better with POSIX.2 if your host complies with POSIX.1.
Therefore:
- By default, no backups are made.
(But this was changed again in patch 2.4; see above.)
- The simple backup file name for F defaults to F.orig
regardless of whether the file system supports long file names,
and F~ is used only if F.orig is too long for that particular file.
- Similarly for the reject file names F.rej and F#.
Also:
- The pseudo-option `+' has been withdrawn.
- -b is equivalent to --version-control=simple;
`-z SUFF' has the meaning that `-b SUFF' used to.
- Names of files to be patched are taken first from *** line and then from
--- line of context diffs; then from Index: line; /dev/tty is
consulted if none of the above files exist. However, if the patch
appears to create a file, the file does not have to exist: instead,
the first name with the longest existing directory prefix is taken.
(These rules were changed again in patch 2.3 and 2.4; see above.)
- Exit status 0 means success, 1 means hunks were rejected, 2 means trouble.
- `-l' ignores changes only in spaces and tabs, not in other white space.
- If no `-p' option is given, `-pINFINITY' is assumed, instead of trying
to guess the proper value.
- `-p' now requires an operand; use `-p 0' to get the effect of the old plain
`-p' option.
- `-p' treats two or more adjacent slashes as if it were one slash.
- The TERM signal is caught.
- New option `-i F' reads patch from F instead of stdin.
* The `patch' options and build procedure conform to current GNU standards.
For example, the `--version' option now outputs copyright information.
* When the patch is creating a file, but a nonempty file of that name already
exists, `patch' now asks for confirmation before patching.
* RCS is used only if the version control method is `existing'
and there is already an RCS file. Similarly for SCCS.
(But this was changed again in patch 2.3 and 2.4; see above.)
* Copyright notices have been clarified. Every file in this version of `patch'
can be distributed under the GNU General Public License. See README for
details.
Changes in version 2.1:
* A few more portability bugs have been fixed. The version number has
been changed from 2.0.12g11 to 2.1, because the name
`patch-2.0.12g10' was too long for traditional Unix file systems.
Versions 2.0.12g9 through 2.0.12g11 fix various portability bugs.
Changes in version 2.0.12g8:
* Start of the 12g series, with a GNU-style configure script and
long-named options.
* Added the -t --batch option, similar to -f.
* Improved detection of files that are locked under RCS or SCCS.
* Reinstate the -E option to remove output files that are empty after
being patched.
* Print the system error message when system calls fail.
* Fixed various bugs and portability problems.
Copyright (C) 1992-1993, 1997-2003, 2006, 2009, 2011-2012 Free Software
Foundation, Inc.
This file is part of GNU Patch.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that they 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; see the file COPYING. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.

62
README Normal file
View File

@ -0,0 +1,62 @@
This is GNU patch, which applies diff files to original files.
This version of patch has many changes made by the Free Software Foundation.
They add support for:
* handling arbitrary binary data and large files
* the unified context diff format that GNU diff can produce
* merging into files instead of creating reject files
* making GNU Emacs-style backup files
* improved interaction with RCS and SCCS
* the GNU conventions for option parsing and configuring and compilation.
* better POSIX compliance
They also fix some bugs.
If you obtained this file as part of a "git clone", then see the
README-hacking file. If this file came to you as part of a tar archive,
then see the file INSTALL for compilation and installation instructions.
See the file NEWS for a list of major changes in the current release.
A more detailed description of all changes can be found in the file ChangeLog
in tar archives, and with "git log" which shows the version control history.
Tutorial-style documentation for patch is included in the GNU
Diffutils package; get GNU Diffutils 2.8 or later for up-to-date
documentation for patch.
Use `configure --disable-largefile' to disable large file support;
this is reportedly necessary on Red Hat GNU/Linux 6.0 to avoid a C library bug.
For MS-DOS using DJGPP tools, see the file pc/djgpp/README.
For other systems, copy config.hin to config.h and change
#undef statements in it to #define as appropriate for your system,
and copy Makefile.in to Makefile and set the variables that are
enclosed in @ signs as appropriate for your system.
Please send bug reports for this version of patch to
<bug-patch@gnu.org>.
The Free Software Foundation is distributing this version of patch
independently because as of this writing, Larry Wall has not released a
new version of patch since mid-1988. We have heard that he has been
too busy working on other things, like Perl. He has graciously agreed
to let GNU `patch' be distributed under the terms of the GNU General
Public License.
------
Copyright (C) 1984, 1985, 1986, 1987, 1988 Larry Wall
Copyright (C) 1989-1993, 1997, 1999, 2002, 2009, 2011-2012 Free Software
Foundation, Inc.
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 <http://www.gnu.org/licenses/>.

7
TODO Normal file
View File

@ -0,0 +1,7 @@
Announcement ...
* Fix Savannah patches.
* Reduce the number of unnecessary syscalls: for example, stat is often called
repeatedly.
* Call makedirs() before creating files inside the directory; with the dirfd
cache, this causes no extra syscalls anymore.

1830
aclocal.m4 vendored Normal file

File diff suppressed because it is too large Load Diff

1028
bootstrap Executable file

File diff suppressed because it is too large Load Diff

270
build-aux/ar-lib Executable file
View File

@ -0,0 +1,270 @@
#! /bin/sh
# Wrapper for Microsoft lib.exe
me=ar-lib
scriptversion=2012-03-01.08; # UTC
# Copyright (C) 2010-2017 Free Software Foundation, Inc.
# Written by Peter Rosin <peda@lysator.liu.se>.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, 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 <http://www.gnu.org/licenses/>.
# 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 file is maintained in Automake, please report
# bugs to <bug-automake@gnu.org> or send patches to
# <automake-patches@gnu.org>.
# func_error message
func_error ()
{
echo "$me: $1" 1>&2
exit 1
}
file_conv=
# func_file_conv build_file
# Convert a $build file to $host form and store it in $file
# Currently only supports Windows hosts.
func_file_conv ()
{
file=$1
case $file in
/ | /[!/]*) # absolute file, and not a UNC file
if test -z "$file_conv"; then
# lazily determine how to convert abs files
case `uname -s` in
MINGW*)
file_conv=mingw
;;
CYGWIN*)
file_conv=cygwin
;;
*)
file_conv=wine
;;
esac
fi
case $file_conv in
mingw)
file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
;;
cygwin)
file=`cygpath -m "$file" || echo "$file"`
;;
wine)
file=`winepath -w "$file" || echo "$file"`
;;
esac
;;
esac
}
# func_at_file at_file operation archive
# Iterate over all members in AT_FILE performing OPERATION on ARCHIVE
# for each of them.
# When interpreting the content of the @FILE, do NOT use func_file_conv,
# since the user would need to supply preconverted file names to
# binutils ar, at least for MinGW.
func_at_file ()
{
operation=$2
archive=$3
at_file_contents=`cat "$1"`
eval set x "$at_file_contents"
shift
for member
do
$AR -NOLOGO $operation:"$member" "$archive" || exit $?
done
}
case $1 in
'')
func_error "no command. Try '$0 --help' for more information."
;;
-h | --h*)
cat <<EOF
Usage: $me [--help] [--version] PROGRAM ACTION ARCHIVE [MEMBER...]
Members may be specified in a file named with @FILE.
EOF
exit $?
;;
-v | --v*)
echo "$me, version $scriptversion"
exit $?
;;
esac
if test $# -lt 3; then
func_error "you must specify a program, an action and an archive"
fi
AR=$1
shift
while :
do
if test $# -lt 2; then
func_error "you must specify a program, an action and an archive"
fi
case $1 in
-lib | -LIB \
| -ltcg | -LTCG \
| -machine* | -MACHINE* \
| -subsystem* | -SUBSYSTEM* \
| -verbose | -VERBOSE \
| -wx* | -WX* )
AR="$AR $1"
shift
;;
*)
action=$1
shift
break
;;
esac
done
orig_archive=$1
shift
func_file_conv "$orig_archive"
archive=$file
# strip leading dash in $action
action=${action#-}
delete=
extract=
list=
quick=
replace=
index=
create=
while test -n "$action"
do
case $action in
d*) delete=yes ;;
x*) extract=yes ;;
t*) list=yes ;;
q*) quick=yes ;;
r*) replace=yes ;;
s*) index=yes ;;
S*) ;; # the index is always updated implicitly
c*) create=yes ;;
u*) ;; # TODO: don't ignore the update modifier
v*) ;; # TODO: don't ignore the verbose modifier
*)
func_error "unknown action specified"
;;
esac
action=${action#?}
done
case $delete$extract$list$quick$replace,$index in
yes,* | ,yes)
;;
yesyes*)
func_error "more than one action specified"
;;
*)
func_error "no action specified"
;;
esac
if test -n "$delete"; then
if test ! -f "$orig_archive"; then
func_error "archive not found"
fi
for member
do
case $1 in
@*)
func_at_file "${1#@}" -REMOVE "$archive"
;;
*)
func_file_conv "$1"
$AR -NOLOGO -REMOVE:"$file" "$archive" || exit $?
;;
esac
done
elif test -n "$extract"; then
if test ! -f "$orig_archive"; then
func_error "archive not found"
fi
if test $# -gt 0; then
for member
do
case $1 in
@*)
func_at_file "${1#@}" -EXTRACT "$archive"
;;
*)
func_file_conv "$1"
$AR -NOLOGO -EXTRACT:"$file" "$archive" || exit $?
;;
esac
done
else
$AR -NOLOGO -LIST "$archive" | sed -e 's/\\/\\\\/g' | while read member
do
$AR -NOLOGO -EXTRACT:"$member" "$archive" || exit $?
done
fi
elif test -n "$quick$replace"; then
if test ! -f "$orig_archive"; then
if test -z "$create"; then
echo "$me: creating $orig_archive"
fi
orig_archive=
else
orig_archive=$archive
fi
for member
do
case $1 in
@*)
func_file_conv "${1#@}"
set x "$@" "@$file"
;;
*)
func_file_conv "$1"
set x "$@" "$file"
;;
esac
shift
shift
done
if test -n "$orig_archive"; then
$AR -NOLOGO -OUT:"$archive" "$orig_archive" "$@" || exit $?
else
$AR -NOLOGO -OUT:"$archive" "$@" || exit $?
fi
elif test -n "$list"; then
if test ! -f "$orig_archive"; then
func_error "archive not found"
fi
$AR -NOLOGO -LIST "$archive" || exit $?
fi

348
build-aux/compile Executable file
View File

@ -0,0 +1,348 @@
#! /bin/sh
# Wrapper for compilers which do not understand '-c -o'.
scriptversion=2016-01-11.22; # UTC
# Copyright (C) 1999-2017 Free Software Foundation, Inc.
# Written by Tom Tromey <tromey@cygnus.com>.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, 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 <http://www.gnu.org/licenses/>.
# 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 file is maintained in Automake, please report
# bugs to <bug-automake@gnu.org> or send patches to
# <automake-patches@gnu.org>.
nl='
'
# We need space, tab and new line, in precisely that order. Quoting is
# there to prevent tools from complaining about whitespace usage.
IFS=" "" $nl"
file_conv=
# func_file_conv build_file lazy
# Convert a $build file to $host form and store it in $file
# Currently only supports Windows hosts. If the determined conversion
# type is listed in (the comma separated) LAZY, no conversion will
# take place.
func_file_conv ()
{
file=$1
case $file in
/ | /[!/]*) # absolute file, and not a UNC file
if test -z "$file_conv"; then
# lazily determine how to convert abs files
case `uname -s` in
MINGW*)
file_conv=mingw
;;
CYGWIN*)
file_conv=cygwin
;;
*)
file_conv=wine
;;
esac
fi
case $file_conv/,$2, in
*,$file_conv,*)
;;
mingw/*)
file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
;;
cygwin/*)
file=`cygpath -m "$file" || echo "$file"`
;;
wine/*)
file=`winepath -w "$file" || echo "$file"`
;;
esac
;;
esac
}
# func_cl_dashL linkdir
# Make cl look for libraries in LINKDIR
func_cl_dashL ()
{
func_file_conv "$1"
if test -z "$lib_path"; then
lib_path=$file
else
lib_path="$lib_path;$file"
fi
linker_opts="$linker_opts -LIBPATH:$file"
}
# func_cl_dashl library
# Do a library search-path lookup for cl
func_cl_dashl ()
{
lib=$1
found=no
save_IFS=$IFS
IFS=';'
for dir in $lib_path $LIB
do
IFS=$save_IFS
if $shared && test -f "$dir/$lib.dll.lib"; then
found=yes
lib=$dir/$lib.dll.lib
break
fi
if test -f "$dir/$lib.lib"; then
found=yes
lib=$dir/$lib.lib
break
fi
if test -f "$dir/lib$lib.a"; then
found=yes
lib=$dir/lib$lib.a
break
fi
done
IFS=$save_IFS
if test "$found" != yes; then
lib=$lib.lib
fi
}
# func_cl_wrapper cl arg...
# Adjust compile command to suit cl
func_cl_wrapper ()
{
# Assume a capable shell
lib_path=
shared=:
linker_opts=
for arg
do
if test -n "$eat"; then
eat=
else
case $1 in
-o)
# configure might choose to run compile as 'compile cc -o foo foo.c'.
eat=1
case $2 in
*.o | *.[oO][bB][jJ])
func_file_conv "$2"
set x "$@" -Fo"$file"
shift
;;
*)
func_file_conv "$2"
set x "$@" -Fe"$file"
shift
;;
esac
;;
-I)
eat=1
func_file_conv "$2" mingw
set x "$@" -I"$file"
shift
;;
-I*)
func_file_conv "${1#-I}" mingw
set x "$@" -I"$file"
shift
;;
-l)
eat=1
func_cl_dashl "$2"
set x "$@" "$lib"
shift
;;
-l*)
func_cl_dashl "${1#-l}"
set x "$@" "$lib"
shift
;;
-L)
eat=1
func_cl_dashL "$2"
;;
-L*)
func_cl_dashL "${1#-L}"
;;
-static)
shared=false
;;
-Wl,*)
arg=${1#-Wl,}
save_ifs="$IFS"; IFS=','
for flag in $arg; do
IFS="$save_ifs"
linker_opts="$linker_opts $flag"
done
IFS="$save_ifs"
;;
-Xlinker)
eat=1
linker_opts="$linker_opts $2"
;;
-*)
set x "$@" "$1"
shift
;;
*.cc | *.CC | *.cxx | *.CXX | *.[cC]++)
func_file_conv "$1"
set x "$@" -Tp"$file"
shift
;;
*.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO])
func_file_conv "$1" mingw
set x "$@" "$file"
shift
;;
*)
set x "$@" "$1"
shift
;;
esac
fi
shift
done
if test -n "$linker_opts"; then
linker_opts="-link$linker_opts"
fi
exec "$@" $linker_opts
exit 1
}
eat=
case $1 in
'')
echo "$0: No command. Try '$0 --help' for more information." 1>&2
exit 1;
;;
-h | --h*)
cat <<\EOF
Usage: compile [--help] [--version] PROGRAM [ARGS]
Wrapper for compilers which do not understand '-c -o'.
Remove '-o dest.o' from ARGS, run PROGRAM with the remaining
arguments, and rename the output as expected.
If you are trying to build a whole package this is not the
right script to run: please start by reading the file 'INSTALL'.
Report bugs to <bug-automake@gnu.org>.
EOF
exit $?
;;
-v | --v*)
echo "compile $scriptversion"
exit $?
;;
cl | *[/\\]cl | cl.exe | *[/\\]cl.exe | \
icl | *[/\\]icl | icl.exe | *[/\\]icl.exe )
func_cl_wrapper "$@" # Doesn't return...
;;
esac
ofile=
cfile=
for arg
do
if test -n "$eat"; then
eat=
else
case $1 in
-o)
# configure might choose to run compile as 'compile cc -o foo foo.c'.
# So we strip '-o arg' only if arg is an object.
eat=1
case $2 in
*.o | *.obj)
ofile=$2
;;
*)
set x "$@" -o "$2"
shift
;;
esac
;;
*.c)
cfile=$1
set x "$@" "$1"
shift
;;
*)
set x "$@" "$1"
shift
;;
esac
fi
shift
done
if test -z "$ofile" || test -z "$cfile"; then
# If no '-o' option was seen then we might have been invoked from a
# pattern rule where we don't need one. That is ok -- this is a
# normal compilation that the losing compiler can handle. If no
# '.c' file was seen then we are probably linking. That is also
# ok.
exec "$@"
fi
# Name of file we expect compiler to create.
cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'`
# Create the lock directory.
# Note: use '[/\\:.-]' here to ensure that we don't use the same name
# that we are using for the .o file. Also, base the name on the expected
# object file name, since that is what matters with a parallel build.
lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d
while true; do
if mkdir "$lockdir" >/dev/null 2>&1; then
break
fi
sleep 1
done
# FIXME: race condition here if user kills between mkdir and trap.
trap "rmdir '$lockdir'; exit 1" 1 2 15
# Run the compile.
"$@"
ret=$?
if test -f "$cofile"; then
test "$cofile" = "$ofile" || mv "$cofile" "$ofile"
elif test -f "${cofile}bj"; then
test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile"
fi
rmdir "$lockdir"
exit $ret
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC0"
# time-stamp-end: "; # UTC"
# End:

1476
build-aux/config.guess vendored Executable file

File diff suppressed because it is too large Load Diff

1800
build-aux/config.sub vendored Executable file

File diff suppressed because it is too large Load Diff

791
build-aux/depcomp Executable file
View File

@ -0,0 +1,791 @@
#! /bin/sh
# depcomp - compile a program generating dependencies as side-effects
scriptversion=2017-09-16.17; # UTC
# Copyright (C) 1999-2018 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, 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 <https://www.gnu.org/licenses/>.
# 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.
# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
case $1 in
'')
echo "$0: No command. Try '$0 --help' for more information." 1>&2
exit 1;
;;
-h | --h*)
cat <<\EOF
Usage: depcomp [--help] [--version] PROGRAM [ARGS]
Run PROGRAMS ARGS to compile a file, generating dependencies
as side-effects.
Environment variables:
depmode Dependency tracking mode.
source Source file read by 'PROGRAMS ARGS'.
object Object file output by 'PROGRAMS ARGS'.
DEPDIR directory where to store dependencies.
depfile Dependency file to output.
tmpdepfile Temporary file to use when outputting dependencies.
libtool Whether libtool is used (yes/no).
Report bugs to <bug-automake@gnu.org>.
EOF
exit $?
;;
-v | --v*)
echo "depcomp $scriptversion"
exit $?
;;
esac
# Get the directory component of the given path, and save it in the
# global variables '$dir'. Note that this directory component will
# be either empty or ending with a '/' character. This is deliberate.
set_dir_from ()
{
case $1 in
*/*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;;
*) dir=;;
esac
}
# Get the suffix-stripped basename of the given path, and save it the
# global variable '$base'.
set_base_from ()
{
base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'`
}
# If no dependency file was actually created by the compiler invocation,
# we still have to create a dummy depfile, to avoid errors with the
# Makefile "include basename.Plo" scheme.
make_dummy_depfile ()
{
echo "#dummy" > "$depfile"
}
# Factor out some common post-processing of the generated depfile.
# Requires the auxiliary global variable '$tmpdepfile' to be set.
aix_post_process_depfile ()
{
# If the compiler actually managed to produce a dependency file,
# post-process it.
if test -f "$tmpdepfile"; then
# Each line is of the form 'foo.o: dependency.h'.
# Do two passes, one to just change these to
# $object: dependency.h
# and one to simply output
# dependency.h:
# which is needed to avoid the deleted-header problem.
{ sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile"
sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile"
} > "$depfile"
rm -f "$tmpdepfile"
else
make_dummy_depfile
fi
}
# A tabulation character.
tab=' '
# A newline character.
nl='
'
# Character ranges might be problematic outside the C locale.
# These definitions help.
upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ
lower=abcdefghijklmnopqrstuvwxyz
digits=0123456789
alpha=${upper}${lower}
if test -z "$depmode" || test -z "$source" || test -z "$object"; then
echo "depcomp: Variables source, object and depmode must be set" 1>&2
exit 1
fi
# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
depfile=${depfile-`echo "$object" |
sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
rm -f "$tmpdepfile"
# Avoid interferences from the environment.
gccflag= dashmflag=
# Some modes work just like other modes, but use different flags. We
# parameterize here, but still list the modes in the big case below,
# to make depend.m4 easier to write. Note that we *cannot* use a case
# here, because this file can only contain one case statement.
if test "$depmode" = hp; then
# HP compiler uses -M and no extra arg.
gccflag=-M
depmode=gcc
fi
if test "$depmode" = dashXmstdout; then
# This is just like dashmstdout with a different argument.
dashmflag=-xM
depmode=dashmstdout
fi
cygpath_u="cygpath -u -f -"
if test "$depmode" = msvcmsys; then
# This is just like msvisualcpp but w/o cygpath translation.
# Just convert the backslash-escaped backslashes to single forward
# slashes to satisfy depend.m4
cygpath_u='sed s,\\\\,/,g'
depmode=msvisualcpp
fi
if test "$depmode" = msvc7msys; then
# This is just like msvc7 but w/o cygpath translation.
# Just convert the backslash-escaped backslashes to single forward
# slashes to satisfy depend.m4
cygpath_u='sed s,\\\\,/,g'
depmode=msvc7
fi
if test "$depmode" = xlc; then
# IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information.
gccflag=-qmakedep=gcc,-MF
depmode=gcc
fi
case "$depmode" in
gcc3)
## gcc 3 implements dependency tracking that does exactly what
## we want. Yay! Note: for some reason libtool 1.4 doesn't like
## it if -MD -MP comes after the -MF stuff. Hmm.
## Unfortunately, FreeBSD c89 acceptance of flags depends upon
## the command line argument order; so add the flags where they
## appear in depend2.am. Note that the slowdown incurred here
## affects only configure: in makefiles, %FASTDEP% shortcuts this.
for arg
do
case $arg in
-c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;;
*) set fnord "$@" "$arg" ;;
esac
shift # fnord
shift # $arg
done
"$@"
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
mv "$tmpdepfile" "$depfile"
;;
gcc)
## Note that this doesn't just cater to obsosete pre-3.x GCC compilers.
## but also to in-use compilers like IMB xlc/xlC and the HP C compiler.
## (see the conditional assignment to $gccflag above).
## There are various ways to get dependency output from gcc. Here's
## why we pick this rather obscure method:
## - Don't want to use -MD because we'd like the dependencies to end
## up in a subdir. Having to rename by hand is ugly.
## (We might end up doing this anyway to support other compilers.)
## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
## -MM, not -M (despite what the docs say). Also, it might not be
## supported by the other compilers which use the 'gcc' depmode.
## - Using -M directly means running the compiler twice (even worse
## than renaming).
if test -z "$gccflag"; then
gccflag=-MD,
fi
"$@" -Wp,"$gccflag$tmpdepfile"
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
echo "$object : \\" > "$depfile"
# The second -e expression handles DOS-style file names with drive
# letters.
sed -e 's/^[^:]*: / /' \
-e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
## This next piece of magic avoids the "deleted header file" problem.
## The problem is that when a header file which appears in a .P file
## is deleted, the dependency causes make to die (because there is
## typically no way to rebuild the header). We avoid this by adding
## dummy dependencies for each header file. Too bad gcc doesn't do
## this for us directly.
## Some versions of gcc put a space before the ':'. On the theory
## that the space means something, we add a space to the output as
## well. hp depmode also adds that space, but also prefixes the VPATH
## to the object. Take care to not repeat it in the output.
## Some versions of the HPUX 10.20 sed can't process this invocation
## correctly. Breaking it into two sed invocations is a workaround.
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \
| sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
hp)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
sgi)
if test "$libtool" = yes; then
"$@" "-Wp,-MDupdate,$tmpdepfile"
else
"$@" -MDupdate "$tmpdepfile"
fi
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files
echo "$object : \\" > "$depfile"
# Clip off the initial element (the dependent). Don't try to be
# clever and replace this with sed code, as IRIX sed won't handle
# lines with more than a fixed number of characters (4096 in
# IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
# the IRIX cc adds comments like '#:fec' to the end of the
# dependency line.
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \
| tr "$nl" ' ' >> "$depfile"
echo >> "$depfile"
# The second pass generates a dummy entry for each header file.
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
>> "$depfile"
else
make_dummy_depfile
fi
rm -f "$tmpdepfile"
;;
xlc)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
aix)
# The C for AIX Compiler uses -M and outputs the dependencies
# in a .u file. In older versions, this file always lives in the
# current directory. Also, the AIX compiler puts '$object:' at the
# start of each line; $object doesn't have directory information.
# Version 6 uses the directory in both cases.
set_dir_from "$object"
set_base_from "$object"
if test "$libtool" = yes; then
tmpdepfile1=$dir$base.u
tmpdepfile2=$base.u
tmpdepfile3=$dir.libs/$base.u
"$@" -Wc,-M
else
tmpdepfile1=$dir$base.u
tmpdepfile2=$dir$base.u
tmpdepfile3=$dir$base.u
"$@" -M
fi
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
do
test -f "$tmpdepfile" && break
done
aix_post_process_depfile
;;
tcc)
# tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26
# FIXME: That version still under development at the moment of writing.
# Make that this statement remains true also for stable, released
# versions.
# It will wrap lines (doesn't matter whether long or short) with a
# trailing '\', as in:
#
# foo.o : \
# foo.c \
# foo.h \
#
# It will put a trailing '\' even on the last line, and will use leading
# spaces rather than leading tabs (at least since its commit 0394caf7
# "Emit spaces for -MD").
"$@" -MD -MF "$tmpdepfile"
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
# Each non-empty line is of the form 'foo.o : \' or ' dep.h \'.
# We have to change lines of the first kind to '$object: \'.
sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile"
# And for each line of the second kind, we have to emit a 'dep.h:'
# dummy dependency, to avoid the deleted-header problem.
sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile"
rm -f "$tmpdepfile"
;;
## The order of this option in the case statement is important, since the
## shell code in configure will try each of these formats in the order
## listed in this file. A plain '-MD' option would be understood by many
## compilers, so we must ensure this comes after the gcc and icc options.
pgcc)
# Portland's C compiler understands '-MD'.
# Will always output deps to 'file.d' where file is the root name of the
# source file under compilation, even if file resides in a subdirectory.
# The object file name does not affect the name of the '.d' file.
# pgcc 10.2 will output
# foo.o: sub/foo.c sub/foo.h
# and will wrap long lines using '\' :
# foo.o: sub/foo.c ... \
# sub/foo.h ... \
# ...
set_dir_from "$object"
# Use the source, not the object, to determine the base name, since
# that's sadly what pgcc will do too.
set_base_from "$source"
tmpdepfile=$base.d
# For projects that build the same source file twice into different object
# files, the pgcc approach of using the *source* file root name can cause
# problems in parallel builds. Use a locking strategy to avoid stomping on
# the same $tmpdepfile.
lockdir=$base.d-lock
trap "
echo '$0: caught signal, cleaning up...' >&2
rmdir '$lockdir'
exit 1
" 1 2 13 15
numtries=100
i=$numtries
while test $i -gt 0; do
# mkdir is a portable test-and-set.
if mkdir "$lockdir" 2>/dev/null; then
# This process acquired the lock.
"$@" -MD
stat=$?
# Release the lock.
rmdir "$lockdir"
break
else
# If the lock is being held by a different process, wait
# until the winning process is done or we timeout.
while test -d "$lockdir" && test $i -gt 0; do
sleep 1
i=`expr $i - 1`
done
fi
i=`expr $i - 1`
done
trap - 1 2 13 15
if test $i -le 0; then
echo "$0: failed to acquire lock after $numtries attempts" >&2
echo "$0: check lockdir '$lockdir'" >&2
exit 1
fi
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
# Each line is of the form `foo.o: dependent.h',
# or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
# Do two passes, one to just change these to
# `$object: dependent.h' and one to simply `dependent.h:'.
sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
# Some versions of the HPUX 10.20 sed can't process this invocation
# correctly. Breaking it into two sed invocations is a workaround.
sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \
| sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
hp2)
# The "hp" stanza above does not work with aCC (C++) and HP's ia64
# compilers, which have integrated preprocessors. The correct option
# to use with these is +Maked; it writes dependencies to a file named
# 'foo.d', which lands next to the object file, wherever that
# happens to be.
# Much of this is similar to the tru64 case; see comments there.
set_dir_from "$object"
set_base_from "$object"
if test "$libtool" = yes; then
tmpdepfile1=$dir$base.d
tmpdepfile2=$dir.libs/$base.d
"$@" -Wc,+Maked
else
tmpdepfile1=$dir$base.d
tmpdepfile2=$dir$base.d
"$@" +Maked
fi
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile1" "$tmpdepfile2"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2"
do
test -f "$tmpdepfile" && break
done
if test -f "$tmpdepfile"; then
sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile"
# Add 'dependent.h:' lines.
sed -ne '2,${
s/^ *//
s/ \\*$//
s/$/:/
p
}' "$tmpdepfile" >> "$depfile"
else
make_dummy_depfile
fi
rm -f "$tmpdepfile" "$tmpdepfile2"
;;
tru64)
# The Tru64 compiler uses -MD to generate dependencies as a side
# effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'.
# At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
# dependencies in 'foo.d' instead, so we check for that too.
# Subdirectories are respected.
set_dir_from "$object"
set_base_from "$object"
if test "$libtool" = yes; then
# Libtool generates 2 separate objects for the 2 libraries. These
# two compilations output dependencies in $dir.libs/$base.o.d and
# in $dir$base.o.d. We have to check for both files, because
# one of the two compilations can be disabled. We should prefer
# $dir$base.o.d over $dir.libs/$base.o.d because the latter is
# automatically cleaned when .libs/ is deleted, while ignoring
# the former would cause a distcleancheck panic.
tmpdepfile1=$dir$base.o.d # libtool 1.5
tmpdepfile2=$dir.libs/$base.o.d # Likewise.
tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504
"$@" -Wc,-MD
else
tmpdepfile1=$dir$base.d
tmpdepfile2=$dir$base.d
tmpdepfile3=$dir$base.d
"$@" -MD
fi
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
do
test -f "$tmpdepfile" && break
done
# Same post-processing that is required for AIX mode.
aix_post_process_depfile
;;
msvc7)
if test "$libtool" = yes; then
showIncludes=-Wc,-showIncludes
else
showIncludes=-showIncludes
fi
"$@" $showIncludes > "$tmpdepfile"
stat=$?
grep -v '^Note: including file: ' "$tmpdepfile"
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
echo "$object : \\" > "$depfile"
# The first sed program below extracts the file names and escapes
# backslashes for cygpath. The second sed program outputs the file
# name when reading, but also accumulates all include files in the
# hold buffer in order to output them again at the end. This only
# works with sed implementations that can handle large buffers.
sed < "$tmpdepfile" -n '
/^Note: including file: *\(.*\)/ {
s//\1/
s/\\/\\\\/g
p
}' | $cygpath_u | sort -u | sed -n '
s/ /\\ /g
s/\(.*\)/'"$tab"'\1 \\/p
s/.\(.*\) \\/\1:/
H
$ {
s/.*/'"$tab"'/
G
p
}' >> "$depfile"
echo >> "$depfile" # make sure the fragment doesn't end with a backslash
rm -f "$tmpdepfile"
;;
msvc7msys)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
#nosideeffect)
# This comment above is used by automake to tell side-effect
# dependency tracking mechanisms from slower ones.
dashmstdout)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout, regardless of -o.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
# Remove '-o $object'.
IFS=" "
for arg
do
case $arg in
-o)
shift
;;
$object)
shift
;;
*)
set fnord "$@" "$arg"
shift # fnord
shift # $arg
;;
esac
done
test -z "$dashmflag" && dashmflag=-M
# Require at least two characters before searching for ':'
# in the target name. This is to cope with DOS-style filenames:
# a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise.
"$@" $dashmflag |
sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile"
rm -f "$depfile"
cat < "$tmpdepfile" > "$depfile"
# Some versions of the HPUX 10.20 sed can't process this sed invocation
# correctly. Breaking it into two sed invocations is a workaround.
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
| sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
dashXmstdout)
# This case only exists to satisfy depend.m4. It is never actually
# run, as this mode is specially recognized in the preamble.
exit 1
;;
makedepend)
"$@" || exit $?
# Remove any Libtool call
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
# X makedepend
shift
cleared=no eat=no
for arg
do
case $cleared in
no)
set ""; shift
cleared=yes ;;
esac
if test $eat = yes; then
eat=no
continue
fi
case "$arg" in
-D*|-I*)
set fnord "$@" "$arg"; shift ;;
# Strip any option that makedepend may not understand. Remove
# the object too, otherwise makedepend will parse it as a source file.
-arch)
eat=yes ;;
-*|$object)
;;
*)
set fnord "$@" "$arg"; shift ;;
esac
done
obj_suffix=`echo "$object" | sed 's/^.*\././'`
touch "$tmpdepfile"
${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
rm -f "$depfile"
# makedepend may prepend the VPATH from the source file name to the object.
# No need to regex-escape $object, excess matching of '.' is harmless.
sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile"
# Some versions of the HPUX 10.20 sed can't process the last invocation
# correctly. Breaking it into two sed invocations is a workaround.
sed '1,2d' "$tmpdepfile" \
| tr ' ' "$nl" \
| sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
| sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile" "$tmpdepfile".bak
;;
cpp)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
# Remove '-o $object'.
IFS=" "
for arg
do
case $arg in
-o)
shift
;;
$object)
shift
;;
*)
set fnord "$@" "$arg"
shift # fnord
shift # $arg
;;
esac
done
"$@" -E \
| sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
-e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
| sed '$ s: \\$::' > "$tmpdepfile"
rm -f "$depfile"
echo "$object : \\" > "$depfile"
cat < "$tmpdepfile" >> "$depfile"
sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
msvisualcpp)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
IFS=" "
for arg
do
case "$arg" in
-o)
shift
;;
$object)
shift
;;
"-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
set fnord "$@"
shift
shift
;;
*)
set fnord "$@" "$arg"
shift
shift
;;
esac
done
"$@" -E 2>/dev/null |
sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile"
rm -f "$depfile"
echo "$object : \\" > "$depfile"
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile"
echo "$tab" >> "$depfile"
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile"
rm -f "$tmpdepfile"
;;
msvcmsys)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
none)
exec "$@"
;;
*)
echo "Unknown depmode $depmode" 1>&2
exit 1
;;
esac
exit 0
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC0"
# time-stamp-end: "; # UTC"
# End:

227
build-aux/git-version-gen Executable file
View File

@ -0,0 +1,227 @@
#!/bin/sh
# Print a version string.
scriptversion=2017-09-13.06; # UTC
# Copyright (C) 2007-2018 Free Software Foundation, Inc.
#
# 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 <https://www.gnu.org/licenses/>.
# This script is derived from GIT-VERSION-GEN from GIT: https://git-scm.com/.
# It may be run two ways:
# - from a git repository in which the "git describe" command below
# produces useful output (thus requiring at least one signed tag)
# - from a non-git-repo directory containing a .tarball-version file, which
# presumes this script is invoked like "./git-version-gen .tarball-version".
# In order to use intra-version strings in your project, you will need two
# separate generated version string files:
#
# .tarball-version - present only in a distribution tarball, and not in
# a checked-out repository. Created with contents that were learned at
# the last time autoconf was run, and used by git-version-gen. Must not
# be present in either $(srcdir) or $(builddir) for git-version-gen to
# give accurate answers during normal development with a checked out tree,
# but must be present in a tarball when there is no version control system.
# Therefore, it cannot be used in any dependencies. GNUmakefile has
# hooks to force a reconfigure at distribution time to get the value
# correct, without penalizing normal development with extra reconfigures.
#
# .version - present in a checked-out repository and in a distribution
# tarball. Usable in dependencies, particularly for files that don't
# want to depend on config.h but do want to track version changes.
# Delete this file prior to any autoconf run where you want to rebuild
# files to pick up a version string change; and leave it stale to
# minimize rebuild time after unrelated changes to configure sources.
#
# As with any generated file in a VC'd directory, you should add
# /.version to .gitignore, so that you don't accidentally commit it.
# .tarball-version is never generated in a VC'd directory, so needn't
# be listed there.
#
# Use the following line in your configure.ac, so that $(VERSION) will
# automatically be up-to-date each time configure is run (and note that
# since configure.ac no longer includes a version string, Makefile rules
# should not depend on configure.ac for version updates).
#
# AC_INIT([GNU project],
# m4_esyscmd([build-aux/git-version-gen .tarball-version]),
# [bug-project@example])
#
# Then use the following lines in your Makefile.am, so that .version
# will be present for dependencies, and so that .version and
# .tarball-version will exist in distribution tarballs.
#
# EXTRA_DIST = $(top_srcdir)/.version
# BUILT_SOURCES = $(top_srcdir)/.version
# $(top_srcdir)/.version:
# echo $(VERSION) > $@-t && mv $@-t $@
# dist-hook:
# echo $(VERSION) > $(distdir)/.tarball-version
me=$0
version="git-version-gen $scriptversion
Copyright 2011 Free Software Foundation, Inc.
There is NO warranty. You may redistribute this software
under the terms of the GNU General Public License.
For more information about these matters, see the files named COPYING."
usage="\
Usage: $me [OPTION]... \$srcdir/.tarball-version [TAG-NORMALIZATION-SED-SCRIPT]
Print a version string.
Options:
--prefix PREFIX prefix of git tags (default 'v')
--fallback VERSION
fallback version to use if \"git --version\" fails
--help display this help and exit
--version output version information and exit
Running without arguments will suffice in most cases."
prefix=v
fallback=
while test $# -gt 0; do
case $1 in
--help) echo "$usage"; exit 0;;
--version) echo "$version"; exit 0;;
--prefix) shift; prefix=${1?};;
--fallback) shift; fallback=${1?};;
-*)
echo "$0: Unknown option '$1'." >&2
echo "$0: Try '--help' for more information." >&2
exit 1;;
*)
if test "x$tarball_version_file" = x; then
tarball_version_file="$1"
elif test "x$tag_sed_script" = x; then
tag_sed_script="$1"
else
echo "$0: extra non-option argument '$1'." >&2
exit 1
fi;;
esac
shift
done
if test "x$tarball_version_file" = x; then
echo "$usage"
exit 1
fi
tag_sed_script="${tag_sed_script:-s/x/x/}"
nl='
'
# Avoid meddling by environment variable of the same name.
v=
v_from_git=
# First see if there is a tarball-only version file.
# then try "git describe", then default.
if test -f $tarball_version_file
then
v=`cat $tarball_version_file` || v=
case $v in
*$nl*) v= ;; # reject multi-line output
[0-9]*) ;;
*) v= ;;
esac
test "x$v" = x \
&& echo "$0: WARNING: $tarball_version_file is missing or damaged" 1>&2
fi
if test "x$v" != x
then
: # use $v
# Otherwise, if there is at least one git commit involving the working
# directory, and "git describe" output looks sensible, use that to
# derive a version string.
elif test "`git log -1 --pretty=format:x . 2>&1`" = x \
&& v=`git describe --abbrev=4 --match="$prefix*" HEAD 2>/dev/null \
|| git describe --abbrev=4 HEAD 2>/dev/null` \
&& v=`printf '%s\n' "$v" | sed "$tag_sed_script"` \
&& case $v in
$prefix[0-9]*) ;;
*) (exit 1) ;;
esac
then
# Is this a new git that lists number of commits since the last
# tag or the previous older version that did not?
# Newer: v6.10-77-g0f8faeb
# Older: v6.10-g0f8faeb
vprefix=`expr "X$v" : 'X\(.*\)-g[^-]*$'` || vprefix=$v
case $vprefix in
*-*) : git describe is probably okay three part flavor ;;
*)
: git describe is older two part flavor
# Recreate the number of commits and rewrite such that the
# result is the same as if we were using the newer version
# of git describe.
vtag=`echo "$v" | sed 's/-.*//'`
commit_list=`git rev-list "$vtag"..HEAD 2>/dev/null` \
|| { commit_list=failed;
echo "$0: WARNING: git rev-list failed" 1>&2; }
numcommits=`echo "$commit_list" | wc -l`
v=`echo "$v" | sed "s/\(.*\)-\(.*\)/\1-$numcommits-\2/"`;
test "$commit_list" = failed && v=UNKNOWN
;;
esac
# Change the penultimate "-" to ".", for version-comparing tools.
# Remove the "g" to save a byte.
v=`echo "$v" | sed 's/-\([^-]*\)-g\([^-]*\)$/.\1-\2/'`;
v_from_git=1
elif test "x$fallback" = x || git --version >/dev/null 2>&1; then
v=UNKNOWN
else
v=$fallback
fi
v=`echo "$v" |sed "s/^$prefix//"`
# Test whether to append the "-dirty" suffix only if the version
# string we're using came from git. I.e., skip the test if it's "UNKNOWN"
# or if it came from .tarball-version.
if test "x$v_from_git" != x; then
# Don't declare a version "dirty" merely because a timestamp has changed.
git update-index --refresh > /dev/null 2>&1
dirty=`exec 2>/dev/null;git diff-index --name-only HEAD` || dirty=
case "$dirty" in
'') ;;
*) # Append the suffix only if there isn't one already.
case $v in
*-dirty) ;;
*) v="$v-dirty" ;;
esac ;;
esac
fi
# Omit the trailing newline, so that m4_esyscmd can use the result directly.
printf %s "$v"
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC0"
# time-stamp-end: "; # UTC"
# End:

499
build-aux/gitlog-to-changelog Executable file
View File

@ -0,0 +1,499 @@
eval '(exit $?0)' && eval 'exec perl -wS "$0" "$@"'
& eval 'exec perl -wS "$0" $argv:q'
if 0;
# Convert git log output to ChangeLog format.
my $VERSION = '2017-09-13 06:45'; # UTC
# The definition above must lie within the first 8 lines in order
# for the Emacs time-stamp write hook (at end) to update it.
# If you change this file with Emacs, please let the write hook
# do its job. Otherwise, update this string manually.
# Copyright (C) 2008-2018 Free Software Foundation, Inc.
# 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 <https://www.gnu.org/licenses/>.
# Written by Jim Meyering
use strict;
use warnings;
use Getopt::Long;
use POSIX qw(strftime);
(my $ME = $0) =~ s|.*/||;
# use File::Coda; # https://meyering.net/code/Coda/
END {
defined fileno STDOUT or return;
close STDOUT and return;
warn "$ME: failed to close standard output: $!\n";
$? ||= 1;
}
sub usage ($)
{
my ($exit_code) = @_;
my $STREAM = ($exit_code == 0 ? *STDOUT : *STDERR);
if ($exit_code != 0)
{
print $STREAM "Try '$ME --help' for more information.\n";
}
else
{
print $STREAM <<EOF;
Usage: $ME [OPTIONS] [ARGS]
Convert git log output to ChangeLog format. If present, any ARGS
are passed to "git log". To avoid ARGS being parsed as options to
$ME, they may be preceded by '--'.
OPTIONS:
--amend=FILE FILE maps from an SHA1 to perl code (i.e., s/old/new/) that
makes a change to SHA1's commit log text or metadata.
--append-dot append a dot to the first line of each commit message if
there is no other punctuation or blank at the end.
--no-cluster never cluster commit messages under the same date/author
header; the default is to cluster adjacent commit messages
if their headers are the same and neither commit message
contains multiple paragraphs.
--srcdir=DIR the root of the source tree, from which the .git/
directory can be derived.
--since=DATE convert only the logs since DATE;
the default is to convert all log entries.
--until=DATE convert only the logs older than DATE.
--ignore-matching=PAT ignore commit messages whose first lines match PAT.
--ignore-line=PAT ignore lines of commit messages that match PAT.
--format=FMT set format string for commit subject and body;
see 'man git-log' for the list of format metacharacters;
the default is '%s%n%b%n'
--strip-tab remove one additional leading TAB from commit message lines.
--strip-cherry-pick remove data inserted by "git cherry-pick";
this includes the "cherry picked from commit ..." line,
and the possible final "Conflicts:" paragraph.
--help display this help and exit
--version output version information and exit
EXAMPLE:
$ME --since=2008-01-01 > ChangeLog
$ME -- -n 5 foo > last-5-commits-to-branch-foo
SPECIAL SYNTAX:
The following types of strings are interpreted specially when they appear
at the beginning of a log message line. They are not copied to the output.
Copyright-paperwork-exempt: Yes
Append the "(tiny change)" notation to the usual "date name email"
ChangeLog header to mark a change that does not require a copyright
assignment.
Co-authored-by: Joe User <user\@example.com>
List the specified name and email address on a second
ChangeLog header, denoting a co-author.
Signed-off-by: Joe User <user\@example.com>
These lines are simply elided.
In a FILE specified via --amend, comment lines (starting with "#") are ignored.
FILE must consist of <SHA,CODE+> pairs where SHA is a 40-byte SHA1 (alone on
a line) referring to a commit in the current project, and CODE refers to one
or more consecutive lines of Perl code. Pairs must be separated by one or
more blank line.
Here is sample input for use with --amend=FILE, from coreutils:
3a169f4c5d9159283548178668d2fae6fced3030
# fix typo in title:
s/all tile types/all file types/
1379ed974f1fa39b12e2ffab18b3f7a607082202
# Due to a bug in vc-dwim, I mis-attributed a patch by Paul to myself.
# Change the author to be Paul. Note the escaped "@":
s,Jim .*>,Paul Eggert <eggert\\\@cs.ucla.edu>,
EOF
}
exit $exit_code;
}
# If the string $S is a well-behaved file name, simply return it.
# If it contains white space, quotes, etc., quote it, and return the new string.
sub shell_quote($)
{
my ($s) = @_;
if ($s =~ m![^\w+/.,-]!)
{
# Convert each single quote to '\''
$s =~ s/\'/\'\\\'\'/g;
# Then single quote the string.
$s = "'$s'";
}
return $s;
}
sub quoted_cmd(@)
{
return join (' ', map {shell_quote $_} @_);
}
# Parse file F.
# Comment lines (starting with "#") are ignored.
# F must consist of <SHA,CODE+> pairs where SHA is a 40-byte SHA1
# (alone on a line) referring to a commit in the current project, and
# CODE refers to one or more consecutive lines of Perl code.
# Pairs must be separated by one or more blank line.
sub parse_amend_file($)
{
my ($f) = @_;
open F, '<', $f
or die "$ME: $f: failed to open for reading: $!\n";
my $fail;
my $h = {};
my $in_code = 0;
my $sha;
while (defined (my $line = <F>))
{
$line =~ /^\#/
and next;
chomp $line;
$line eq ''
and $in_code = 0, next;
if (!$in_code)
{
$line =~ /^([0-9a-fA-F]{40})$/
or (warn "$ME: $f:$.: invalid line; expected an SHA1\n"),
$fail = 1, next;
$sha = lc $1;
$in_code = 1;
exists $h->{$sha}
and (warn "$ME: $f:$.: duplicate SHA1\n"),
$fail = 1, next;
}
else
{
$h->{$sha} ||= '';
$h->{$sha} .= "$line\n";
}
}
close F;
$fail
and exit 1;
return $h;
}
# git_dir_option $SRCDIR
#
# From $SRCDIR, the --git-dir option to pass to git (none if $SRCDIR
# is undef). Return as a list (0 or 1 element).
sub git_dir_option($)
{
my ($srcdir) = @_;
my @res = ();
if (defined $srcdir)
{
my $qdir = shell_quote $srcdir;
my $cmd = "cd $qdir && git rev-parse --show-toplevel";
my $qcmd = shell_quote $cmd;
my $git_dir = qx($cmd);
defined $git_dir
or die "$ME: cannot run $qcmd: $!\n";
$? == 0
or die "$ME: $qcmd had unexpected exit code or signal ($?)\n";
chomp $git_dir;
push @res, "--git-dir=$git_dir/.git";
}
@res;
}
{
my $since_date;
my $until_date;
my $format_string = '%s%n%b%n';
my $amend_file;
my $append_dot = 0;
my $cluster = 1;
my $ignore_matching;
my $ignore_line;
my $strip_tab = 0;
my $strip_cherry_pick = 0;
my $srcdir;
GetOptions
(
help => sub { usage 0 },
version => sub { print "$ME version $VERSION\n"; exit },
'since=s' => \$since_date,
'until=s' => \$until_date,
'format=s' => \$format_string,
'amend=s' => \$amend_file,
'append-dot' => \$append_dot,
'cluster!' => \$cluster,
'ignore-matching=s' => \$ignore_matching,
'ignore-line=s' => \$ignore_line,
'strip-tab' => \$strip_tab,
'strip-cherry-pick' => \$strip_cherry_pick,
'srcdir=s' => \$srcdir,
) or usage 1;
defined $since_date
and unshift @ARGV, "--since=$since_date";
defined $until_date
and unshift @ARGV, "--until=$until_date";
# This is a hash that maps an SHA1 to perl code (i.e., s/old/new/)
# that makes a correction in the log or attribution of that commit.
my $amend_code = defined $amend_file ? parse_amend_file $amend_file : {};
my @cmd = ('git',
git_dir_option $srcdir,
qw(log --log-size),
'--pretty=format:%H:%ct %an <%ae>%n%n'.$format_string, @ARGV);
open PIPE, '-|', @cmd
or die ("$ME: failed to run '". quoted_cmd (@cmd) ."': $!\n"
. "(Is your Git too old? Version 1.5.1 or later is required.)\n");
my $prev_multi_paragraph;
my $prev_date_line = '';
my @prev_coauthors = ();
my @skipshas = ();
while (1)
{
defined (my $in = <PIPE>)
or last;
$in =~ /^log size (\d+)$/
or die "$ME:$.: Invalid line (expected log size):\n$in";
my $log_nbytes = $1;
my $log;
my $n_read = read PIPE, $log, $log_nbytes;
$n_read == $log_nbytes
or die "$ME:$.: unexpected EOF\n";
# Extract leading hash.
my ($sha, $rest) = split ':', $log, 2;
defined $sha
or die "$ME:$.: malformed log entry\n";
$sha =~ /^[0-9a-fA-F]{40}$/
or die "$ME:$.: invalid SHA1: $sha\n";
my $skipflag = 0;
if (@skipshas)
{
foreach(@skipshas)
{
if ($sha =~ /^$_/)
{
$skipflag = $_;
last;
}
}
}
# If this commit's log requires any transformation, do it now.
my $code = $amend_code->{$sha};
if (defined $code)
{
eval 'use Safe';
my $s = new Safe;
# Put the unpreprocessed entry into "$_".
$_ = $rest;
# Let $code operate on it, safely.
my $r = $s->reval("$code")
or die "$ME:$.:$sha: failed to eval \"$code\":\n$@\n";
# Note that we've used this entry.
delete $amend_code->{$sha};
# Update $rest upon success.
$rest = $_;
}
# Remove lines inserted by "git cherry-pick".
if ($strip_cherry_pick)
{
$rest =~ s/^\s*Conflicts:\n.*//sm;
$rest =~ s/^\s*\(cherry picked from commit [\da-f]+\)\n//m;
}
my @line = split /[ \t]*\n/, $rest;
my $author_line = shift @line;
defined $author_line
or die "$ME:$.: unexpected EOF\n";
$author_line =~ /^(\d+) (.*>)$/
or die "$ME:$.: Invalid line "
. "(expected date/author/email):\n$author_line\n";
# Format 'Copyright-paperwork-exempt: Yes' as a standard ChangeLog
# `(tiny change)' annotation.
my $tiny = (grep (/^(?:Copyright-paperwork-exempt|Tiny-change):\s+[Yy]es$/, @line)
? ' (tiny change)' : '');
my $date_line = sprintf "%s %s$tiny\n",
strftime ("%Y-%m-%d", localtime ($1)), $2;
my @coauthors = grep /^Co-authored-by:.*$/, @line;
# Omit meta-data lines we've already interpreted.
@line = grep !/^(?:Signed-off-by:[ ].*>$
|Co-authored-by:[ ]
|Copyright-paperwork-exempt:[ ]
|Tiny-change:[ ]
)/x, @line;
# Remove leading and trailing blank lines.
if (@line)
{
while ($line[0] =~ /^\s*$/) { shift @line; }
while ($line[$#line] =~ /^\s*$/) { pop @line; }
}
# Handle Emacs gitmerge.el "skipped" commits.
# Yes, this should be controlled by an option. So sue me.
if ( grep /^(; )?Merge from /, @line )
{
my $found = 0;
foreach (@line)
{
if (grep /^The following commit.*skipped:$/, $_)
{
$found = 1;
## Reset at each merge to reduce chance of false matches.
@skipshas = ();
next;
}
if ($found && $_ =~ /^([0-9a-fA-F]{7,}) [^ ]/)
{
push ( @skipshas, $1 );
}
}
}
# Ignore commits that match the --ignore-matching pattern, if specified.
if (defined $ignore_matching && @line && $line[0] =~ /$ignore_matching/)
{
$skipflag = 1;
}
elsif ($skipflag)
{
## Perhaps only warn if a pattern matches more than once?
warn "$ME: warning: skipping $sha due to $skipflag\n";
}
if (! $skipflag)
{
if (defined $ignore_line && @line)
{
@line = grep ! /$ignore_line/, @line;
while ($line[$#line] =~ /^\s*$/) { pop @line; }
}
# Record whether there are two or more paragraphs.
my $multi_paragraph = grep /^\s*$/, @line;
# Format 'Co-authored-by: A U Thor <email@example.com>' lines in
# standard multi-author ChangeLog format.
for (@coauthors)
{
s/^Co-authored-by:\s*/\t /;
s/\s*</ </;
/<.*?@.*\..*>/
or warn "$ME: warning: missing email address for "
. substr ($_, 5) . "\n";
}
# If clustering of commit messages has been disabled, if this header
# would be different from the previous date/name/etc. header,
# or if this or the previous entry consists of two or more paragraphs,
# then print the header.
if ( ! $cluster
|| $date_line ne $prev_date_line
|| "@coauthors" ne "@prev_coauthors"
|| $multi_paragraph
|| $prev_multi_paragraph)
{
$prev_date_line eq ''
or print "\n";
print $date_line;
@coauthors
and print join ("\n", @coauthors), "\n";
}
$prev_date_line = $date_line;
@prev_coauthors = @coauthors;
$prev_multi_paragraph = $multi_paragraph;
# If there were any lines
if (@line == 0)
{
warn "$ME: warning: empty commit message:\n $date_line\n";
}
else
{
if ($append_dot)
{
# If the first line of the message has enough room, then
if (length $line[0] < 72)
{
# append a dot if there is no other punctuation or blank
# at the end.
$line[0] =~ /[[:punct:]\s]$/
or $line[0] .= '.';
}
}
# Remove one additional leading TAB from each line.
$strip_tab
and map { s/^\t// } @line;
# Prefix each non-empty line with a TAB.
@line = map { length $_ ? "\t$_" : '' } @line;
print "\n", join ("\n", @line), "\n";
}
}
defined ($in = <PIPE>)
or last;
$in ne "\n"
and die "$ME:$.: unexpected line:\n$in";
}
close PIPE
or die "$ME: error closing pipe from " . quoted_cmd (@cmd) . "\n";
# FIXME-someday: include $PROCESS_STATUS in the diagnostic
# Complain about any unused entry in the --amend=F specified file.
my $fail = 0;
foreach my $sha (keys %$amend_code)
{
warn "$ME:$amend_file: unused entry: $sha\n";
$fail = 1;
}
exit $fail;
}
# Local Variables:
# mode: perl
# indent-tabs-mode: nil
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "my $VERSION = '"
# time-stamp-format: "%:y-%02m-%02d %02H:%02M"
# time-stamp-time-zone: "UTC0"
# time-stamp-end: "'; # UTC"
# End:

440
build-aux/gnupload Executable file
View File

@ -0,0 +1,440 @@
#!/bin/sh
# Sign files and upload them.
scriptversion=2017-09-13.06; # UTC
# Copyright (C) 2004-2018 Free Software Foundation, Inc.
#
# 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, 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 <https://www.gnu.org/licenses/>.
# Originally written by Alexandre Duret-Lutz <adl@gnu.org>.
# The master copy of this file is maintained in the gnulib Git repository.
# Please send bug reports and feature requests to bug-gnulib@gnu.org.
set -e
GPG='gpg --batch --no-tty'
conffile=.gnuploadrc
to=
dry_run=false
replace=
symlink_files=
delete_files=
delete_symlinks=
collect_var=
dbg=
nl='
'
usage="Usage: $0 [OPTION]... [CMD] FILE... [[CMD] FILE...]
Sign all FILES, and process them at the destinations specified with --to.
If CMD is not given, it defaults to uploading. See examples below.
Commands:
--delete delete FILES from destination
--symlink create symbolic links
--rmsymlink remove symbolic links
-- treat the remaining arguments as files to upload
Options:
--to DEST specify a destination DEST for FILES
(multiple --to options are allowed)
--user NAME sign with key NAME
--replace allow replacements of existing files
--symlink-regex[=EXPR] use sed script EXPR to compute symbolic link names
--dry-run do nothing, show what would have been done
(including the constructed directive file)
--version output version information and exit
--help print this help text and exit
If --symlink-regex is given without EXPR, then the link target name
is created by replacing the version information with '-latest', e.g.:
foo-1.3.4.tar.gz -> foo-latest.tar.gz
Recognized destinations are:
alpha.gnu.org:DIRECTORY
savannah.gnu.org:DIRECTORY
savannah.nongnu.org:DIRECTORY
ftp.gnu.org:DIRECTORY
build directive files and upload files by FTP
download.gnu.org.ua:{alpha|ftp}/DIRECTORY
build directive files and upload files by SFTP
[user@]host:DIRECTORY upload files with scp
Options and commands are applied in order. If the file $conffile exists
in the current working directory, its contents are prepended to the
actual command line options. Use this to keep your defaults. Comments
(#) and empty lines in $conffile are allowed.
<https://www.gnu.org/prep/maintain/html_node/Automated-FTP-Uploads.html>
gives some further background.
Examples:
1. Upload foobar-1.0.tar.gz to ftp.gnu.org:
gnupload --to ftp.gnu.org:foobar foobar-1.0.tar.gz
2. Upload foobar-1.0.tar.gz and foobar-1.0.tar.xz to ftp.gnu.org:
gnupload --to ftp.gnu.org:foobar foobar-1.0.tar.gz foobar-1.0.tar.xz
3. Same as above, and also create symbolic links to foobar-latest.tar.*:
gnupload --to ftp.gnu.org:foobar \\
--symlink-regex \\
foobar-1.0.tar.gz foobar-1.0.tar.xz
4. Upload foobar-0.9.90.tar.gz to two sites:
gnupload --to alpha.gnu.org:foobar \\
--to sources.redhat.com:~ftp/pub/foobar \\
foobar-0.9.90.tar.gz
5. Delete oopsbar-0.9.91.tar.gz and upload foobar-0.9.91.tar.gz
(the -- terminates the list of files to delete):
gnupload --to alpha.gnu.org:foobar \\
--to sources.redhat.com:~ftp/pub/foobar \\
--delete oopsbar-0.9.91.tar.gz \\
-- foobar-0.9.91.tar.gz
gnupload executes a program ncftpput to do the transfers; if you don't
happen to have an ncftp package installed, the ncftpput-ftp script in
the build-aux/ directory of the gnulib package
(https://savannah.gnu.org/projects/gnulib) may serve as a replacement.
Send patches and bug reports to <bug-gnulib@gnu.org>."
# Read local configuration file
if test -r "$conffile"; then
echo "$0: Reading configuration file $conffile"
conf=`sed 's/#.*$//;/^$/d' "$conffile" | tr "\015$nl" ' '`
eval set x "$conf \"\$@\""
shift
fi
while test -n "$1"; do
case $1 in
-*)
collect_var=
case $1 in
--help)
echo "$usage"
exit $?
;;
--to)
if test -z "$2"; then
echo "$0: Missing argument for --to" 1>&2
exit 1
elif echo "$2" | grep 'ftp-upload\.gnu\.org' >/dev/null; then
echo "$0: Use ftp.gnu.org:PKGNAME or alpha.gnu.org:PKGNAME" >&2
echo "$0: for the destination, not ftp-upload.gnu.org (which" >&2
echo "$0: is used for direct ftp uploads, not with gnupload)." >&2
echo "$0: See --help and its examples if need be." >&2
exit 1
else
to="$to $2"
shift
fi
;;
--user)
if test -z "$2"; then
echo "$0: Missing argument for --user" 1>&2
exit 1
else
GPG="$GPG --local-user $2"
shift
fi
;;
--delete)
collect_var=delete_files
;;
--replace)
replace="replace: true"
;;
--rmsymlink)
collect_var=delete_symlinks
;;
--symlink-regex=*)
symlink_expr=`expr "$1" : '[^=]*=\(.*\)'`
;;
--symlink-regex)
symlink_expr='s|-[0-9][0-9\.]*\(-[0-9][0-9]*\)\{0,1\}\.|-latest.|'
;;
--symlink)
collect_var=symlink_files
;;
--dry-run|-n)
dry_run=:
;;
--version)
echo "gnupload $scriptversion"
exit $?
;;
--)
shift
break
;;
-*)
echo "$0: Unknown option '$1', try '$0 --help'" 1>&2
exit 1
;;
esac
;;
*)
if test -z "$collect_var"; then
break
else
eval "$collect_var=\"\$$collect_var $1\""
fi
;;
esac
shift
done
dprint()
{
echo "Running $* ..."
}
if $dry_run; then
dbg=dprint
fi
if test -z "$to"; then
echo "$0: Missing destination sites" >&2
exit 1
fi
if test -n "$symlink_files"; then
x=`echo "$symlink_files" | sed 's/[^ ]//g;s/ //g'`
if test -n "$x"; then
echo "$0: Odd number of symlink arguments" >&2
exit 1
fi
fi
if test $# = 0; then
if test -z "${symlink_files}${delete_files}${delete_symlinks}"; then
echo "$0: No file to upload" 1>&2
exit 1
fi
else
# Make sure all files exist. We don't want to ask
# for the passphrase if the script will fail.
for file
do
if test ! -f $file; then
echo "$0: Cannot find '$file'" 1>&2
exit 1
elif test -n "$symlink_expr"; then
linkname=`echo $file | sed "$symlink_expr"`
if test -z "$linkname"; then
echo "$0: symlink expression produces empty results" >&2
exit 1
elif test "$linkname" = $file; then
echo "$0: symlink expression does not alter file name" >&2
exit 1
fi
fi
done
fi
# Make sure passphrase is not exported in the environment.
unset passphrase
unset passphrase_fd_0
GNUPGHOME=${GNUPGHOME:-$HOME/.gnupg}
# Reset PATH to be sure that echo is a built-in. We will later use
# 'echo $passphrase' to output the passphrase, so it is important that
# it is a built-in (third-party programs tend to appear in 'ps'
# listings with their arguments...).
# Remember this script runs with 'set -e', so if echo is not built-in
# it will exit now.
if $dry_run || grep -q "^use-agent" $GNUPGHOME/gpg.conf; then :; else
PATH=/empty echo -n "Enter GPG passphrase: "
stty -echo
read -r passphrase
stty echo
echo
passphrase_fd_0="--passphrase-fd 0"
fi
if test $# -ne 0; then
for file
do
echo "Signing $file ..."
rm -f $file.sig
echo "$passphrase" | $dbg $GPG $passphrase_fd_0 -ba -o $file.sig $file
done
fi
# mkdirective DESTDIR BASE FILE STMT
# Arguments: See upload, below
mkdirective ()
{
stmt="$4"
if test -n "$3"; then
stmt="
filename: $3$stmt"
fi
cat >${2}.directive<<EOF
version: 1.2
directory: $1
comment: gnupload v. $scriptversion$stmt
EOF
if $dry_run; then
echo "File ${2}.directive:"
cat ${2}.directive
echo "File ${2}.directive:" | sed 's/./-/g'
fi
}
mksymlink ()
{
while test $# -ne 0
do
echo "symlink: $1 $2"
shift
shift
done
}
# upload DEST DESTDIR BASE FILE STMT FILES
# Arguments:
# DEST Destination site;
# DESTDIR Destination directory;
# BASE Base name for the directive file;
# FILE Name of the file to distribute (may be empty);
# STMT Additional statements for the directive file;
# FILES List of files to upload.
upload ()
{
dest=$1
destdir=$2
base=$3
file=$4
stmt=$5
files=$6
rm -f $base.directive $base.directive.asc
case $dest in
alpha.gnu.org:*)
mkdirective "$destdir" "$base" "$file" "$stmt"
echo "$passphrase" | $dbg $GPG $passphrase_fd_0 --clearsign $base.directive
$dbg ncftpput ftp-upload.gnu.org /incoming/alpha $files $base.directive.asc
;;
ftp.gnu.org:*)
mkdirective "$destdir" "$base" "$file" "$stmt"
echo "$passphrase" | $dbg $GPG $passphrase_fd_0 --clearsign $base.directive
$dbg ncftpput ftp-upload.gnu.org /incoming/ftp $files $base.directive.asc
;;
savannah.gnu.org:*)
if test -z "$files"; then
echo "$0: warning: standalone directives not applicable for $dest" >&2
fi
$dbg ncftpput savannah.gnu.org /incoming/savannah/$destdir $files
;;
savannah.nongnu.org:*)
if test -z "$files"; then
echo "$0: warning: standalone directives not applicable for $dest" >&2
fi
$dbg ncftpput savannah.nongnu.org /incoming/savannah/$destdir $files
;;
download.gnu.org.ua:alpha/*|download.gnu.org.ua:ftp/*)
destdir_p1=`echo "$destdir" | sed 's,^[^/]*/,,'`
destdir_topdir=`echo "$destdir" | sed 's,/.*,,'`
mkdirective "$destdir_p1" "$base" "$file" "$stmt"
echo "$passphrase" | $dbg $GPG $passphrase_fd_0 --clearsign $base.directive
for f in $files $base.directive.asc
do
echo put $f
done | $dbg sftp -b - puszcza.gnu.org.ua:/incoming/$destdir_topdir
;;
/*)
dest_host=`echo "$dest" | sed 's,:.*,,'`
mkdirective "$destdir" "$base" "$file" "$stmt"
echo "$passphrase" | $dbg $GPG $passphrase_fd_0 --clearsign $base.directive
$dbg cp $files $base.directive.asc $dest_host
;;
*)
if test -z "$files"; then
echo "$0: warning: standalone directives not applicable for $dest" >&2
fi
$dbg scp $files $dest
;;
esac
rm -f $base.directive $base.directive.asc
}
#####
# Process any standalone directives
stmt=
if test -n "$symlink_files"; then
stmt="$stmt
`mksymlink $symlink_files`"
fi
for file in $delete_files
do
stmt="$stmt
archive: $file"
done
for file in $delete_symlinks
do
stmt="$stmt
rmsymlink: $file"
done
if test -n "$stmt"; then
for dest in $to
do
destdir=`echo $dest | sed 's/[^:]*://'`
upload "$dest" "$destdir" "`hostname`-$$" "" "$stmt"
done
fi
# Process actual uploads
for dest in $to
do
for file
do
echo "Uploading $file to $dest ..."
stmt=
#
# allowing file replacement is all or nothing.
if test -n "$replace"; then stmt="$stmt
$replace"
fi
#
files="$file $file.sig"
destdir=`echo $dest | sed 's/[^:]*://'`
if test -n "$symlink_expr"; then
linkname=`echo $file | sed "$symlink_expr"`
stmt="$stmt
symlink: $file $linkname
symlink: $file.sig $linkname.sig"
fi
upload "$dest" "$destdir" "$file" "$file" "$stmt" "$files"
done
done
exit 0
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC0"
# time-stamp-end: "; # UTC"
# End:

509
build-aux/install-sh Executable file
View File

@ -0,0 +1,509 @@
#!/bin/sh
# install - install a program, script, or datafile
scriptversion=2017-09-23.17; # UTC
# This originates from X11R5 (mit/util/scripts/install.sh), which was
# later released in X11R6 (xc/config/util/install.sh) with the
# following copyright and license.
#
# Copyright (C) 1994 X Consortium
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
# Except as contained in this notice, the name of the X Consortium shall not
# be used in advertising or otherwise to promote the sale, use or other deal-
# ings in this Software without prior written authorization from the X Consor-
# tium.
#
#
# FSF changes to this file are in the public domain.
#
# Calling this script install-sh is preferred over install.sh, to prevent
# 'make' implicit rules from creating a file called install from it
# when there is no Makefile.
#
# This script is compatible with the BSD install script, but was written
# from scratch.
tab=' '
nl='
'
IFS=" $tab$nl"
# Set DOITPROG to "echo" to test this script.
doit=${DOITPROG-}
doit_exec=${doit:-exec}
# Put in absolute file names if you don't have them in your path;
# or use environment vars.
chgrpprog=${CHGRPPROG-chgrp}
chmodprog=${CHMODPROG-chmod}
chownprog=${CHOWNPROG-chown}
cmpprog=${CMPPROG-cmp}
cpprog=${CPPROG-cp}
mkdirprog=${MKDIRPROG-mkdir}
mvprog=${MVPROG-mv}
rmprog=${RMPROG-rm}
stripprog=${STRIPPROG-strip}
posix_mkdir=
# Desired mode of installed file.
mode=0755
chgrpcmd=
chmodcmd=$chmodprog
chowncmd=
mvcmd=$mvprog
rmcmd="$rmprog -f"
stripcmd=
src=
dst=
dir_arg=
dst_arg=
copy_on_change=false
is_target_a_directory=possibly
usage="\
Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
or: $0 [OPTION]... SRCFILES... DIRECTORY
or: $0 [OPTION]... -t DIRECTORY SRCFILES...
or: $0 [OPTION]... -d DIRECTORIES...
In the 1st form, copy SRCFILE to DSTFILE.
In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
In the 4th, create DIRECTORIES.
Options:
--help display this help and exit.
--version display version info and exit.
-c (ignored)
-C install only if different (preserve the last data modification time)
-d create directories instead of installing files.
-g GROUP $chgrpprog installed files to GROUP.
-m MODE $chmodprog installed files to MODE.
-o USER $chownprog installed files to USER.
-s $stripprog installed files.
-t DIRECTORY install into DIRECTORY.
-T report an error if DSTFILE is a directory.
Environment variables override the default commands:
CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
RMPROG STRIPPROG
"
while test $# -ne 0; do
case $1 in
-c) ;;
-C) copy_on_change=true;;
-d) dir_arg=true;;
-g) chgrpcmd="$chgrpprog $2"
shift;;
--help) echo "$usage"; exit $?;;
-m) mode=$2
case $mode in
*' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
echo "$0: invalid mode: $mode" >&2
exit 1;;
esac
shift;;
-o) chowncmd="$chownprog $2"
shift;;
-s) stripcmd=$stripprog;;
-t)
is_target_a_directory=always
dst_arg=$2
# Protect names problematic for 'test' and other utilities.
case $dst_arg in
-* | [=\(\)!]) dst_arg=./$dst_arg;;
esac
shift;;
-T) is_target_a_directory=never;;
--version) echo "$0 $scriptversion"; exit $?;;
--) shift
break;;
-*) echo "$0: invalid option: $1" >&2
exit 1;;
*) break;;
esac
shift
done
# We allow the use of options -d and -T together, by making -d
# take the precedence; this is for compatibility with GNU install.
if test -n "$dir_arg"; then
if test -n "$dst_arg"; then
echo "$0: target directory not allowed when installing a directory." >&2
exit 1
fi
fi
if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
# When -d is used, all remaining arguments are directories to create.
# When -t is used, the destination is already specified.
# Otherwise, the last argument is the destination. Remove it from $@.
for arg
do
if test -n "$dst_arg"; then
# $@ is not empty: it contains at least $arg.
set fnord "$@" "$dst_arg"
shift # fnord
fi
shift # arg
dst_arg=$arg
# Protect names problematic for 'test' and other utilities.
case $dst_arg in
-* | [=\(\)!]) dst_arg=./$dst_arg;;
esac
done
fi
if test $# -eq 0; then
if test -z "$dir_arg"; then
echo "$0: no input file specified." >&2
exit 1
fi
# It's OK to call 'install-sh -d' without argument.
# This can happen when creating conditional directories.
exit 0
fi
if test -z "$dir_arg"; then
if test $# -gt 1 || test "$is_target_a_directory" = always; then
if test ! -d "$dst_arg"; then
echo "$0: $dst_arg: Is not a directory." >&2
exit 1
fi
fi
fi
if test -z "$dir_arg"; then
do_exit='(exit $ret); exit $ret'
trap "ret=129; $do_exit" 1
trap "ret=130; $do_exit" 2
trap "ret=141; $do_exit" 13
trap "ret=143; $do_exit" 15
# Set umask so as not to create temps with too-generous modes.
# However, 'strip' requires both read and write access to temps.
case $mode in
# Optimize common cases.
*644) cp_umask=133;;
*755) cp_umask=22;;
*[0-7])
if test -z "$stripcmd"; then
u_plus_rw=
else
u_plus_rw='% 200'
fi
cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
*)
if test -z "$stripcmd"; then
u_plus_rw=
else
u_plus_rw=,u+rw
fi
cp_umask=$mode$u_plus_rw;;
esac
fi
for src
do
# Protect names problematic for 'test' and other utilities.
case $src in
-* | [=\(\)!]) src=./$src;;
esac
if test -n "$dir_arg"; then
dst=$src
dstdir=$dst
test -d "$dstdir"
dstdir_status=$?
else
# Waiting for this to be detected by the "$cpprog $src $dsttmp" command
# might cause directories to be created, which would be especially bad
# if $src (and thus $dsttmp) contains '*'.
if test ! -f "$src" && test ! -d "$src"; then
echo "$0: $src does not exist." >&2
exit 1
fi
if test -z "$dst_arg"; then
echo "$0: no destination specified." >&2
exit 1
fi
dst=$dst_arg
# If destination is a directory, append the input filename.
if test -d "$dst"; then
if test "$is_target_a_directory" = never; then
echo "$0: $dst_arg: Is a directory" >&2
exit 1
fi
dstdir=$dst
dstbase=`basename "$src"`
case $dst in
*/) dst=$dst$dstbase;;
*) dst=$dst/$dstbase;;
esac
dstdir_status=0
else
dstdir=`dirname "$dst"`
test -d "$dstdir"
dstdir_status=$?
fi
fi
case $dstdir in
*/) dstdirslash=$dstdir;;
*) dstdirslash=$dstdir/;;
esac
obsolete_mkdir_used=false
if test $dstdir_status != 0; then
case $posix_mkdir in
'')
# Create intermediate dirs using mode 755 as modified by the umask.
# This is like FreeBSD 'install' as of 1997-10-28.
umask=`umask`
case $stripcmd.$umask in
# Optimize common cases.
*[2367][2367]) mkdir_umask=$umask;;
.*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
*[0-7])
mkdir_umask=`expr $umask + 22 \
- $umask % 100 % 40 + $umask % 20 \
- $umask % 10 % 4 + $umask % 2
`;;
*) mkdir_umask=$umask,go-w;;
esac
# With -d, create the new directory with the user-specified mode.
# Otherwise, rely on $mkdir_umask.
if test -n "$dir_arg"; then
mkdir_mode=-m$mode
else
mkdir_mode=
fi
posix_mkdir=false
case $umask in
*[123567][0-7][0-7])
# POSIX mkdir -p sets u+wx bits regardless of umask, which
# is incompatible with FreeBSD 'install' when (umask & 300) != 0.
;;
*)
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
if (umask $mkdir_umask &&
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
then
if test -z "$dir_arg" || {
# Check for POSIX incompatibilities with -m.
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
# other-writable bit of parent directory when it shouldn't.
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
ls_ld_tmpdir=`ls -ld "$tmpdir"`
case $ls_ld_tmpdir in
d????-?r-*) different_mode=700;;
d????-?--*) different_mode=755;;
*) false;;
esac &&
$mkdirprog -m$different_mode -p -- "$tmpdir" && {
ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
}
}
then posix_mkdir=:
fi
rmdir "$tmpdir/d" "$tmpdir"
else
# Remove any dirs left behind by ancient mkdir implementations.
rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
fi
trap '' 0;;
esac;;
esac
if
$posix_mkdir && (
umask $mkdir_umask &&
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
)
then :
else
# The umask is ridiculous, or mkdir does not conform to POSIX,
# or it failed possibly due to a race condition. Create the
# directory the slow way, step by step, checking for races as we go.
case $dstdir in
/*) prefix='/';;
[-=\(\)!]*) prefix='./';;
*) prefix='';;
esac
oIFS=$IFS
IFS=/
set -f
set fnord $dstdir
shift
set +f
IFS=$oIFS
prefixes=
for d
do
test X"$d" = X && continue
prefix=$prefix$d
if test -d "$prefix"; then
prefixes=
else
if $posix_mkdir; then
(umask=$mkdir_umask &&
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
# Don't fail if two instances are running concurrently.
test -d "$prefix" || exit 1
else
case $prefix in
*\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
*) qprefix=$prefix;;
esac
prefixes="$prefixes '$qprefix'"
fi
fi
prefix=$prefix/
done
if test -n "$prefixes"; then
# Don't fail if two instances are running concurrently.
(umask $mkdir_umask &&
eval "\$doit_exec \$mkdirprog $prefixes") ||
test -d "$dstdir" || exit 1
obsolete_mkdir_used=true
fi
fi
fi
if test -n "$dir_arg"; then
{ test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
{ test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
else
# Make a couple of temp file names in the proper directory.
dsttmp=${dstdirslash}_inst.$$_
rmtmp=${dstdirslash}_rm.$$_
# Trap to clean up those temp files at exit.
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
# Copy the file name to the temp name.
(umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
# and set any options; do chmod last to preserve setuid bits.
#
# If any of these fail, we abort the whole thing. If we want to
# ignore errors from any of these, just make sure not to ignore
# errors from the above "$doit $cpprog $src $dsttmp" command.
#
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
{ test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
{ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
# If -C, don't bother to copy if it wouldn't change the file.
if $copy_on_change &&
old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
set -f &&
set X $old && old=:$2:$4:$5:$6 &&
set X $new && new=:$2:$4:$5:$6 &&
set +f &&
test "$old" = "$new" &&
$cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
then
rm -f "$dsttmp"
else
# Rename the file to the real destination.
$doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
# The rename failed, perhaps because mv can't rename something else
# to itself, or perhaps because mv is so ancient that it does not
# support -f.
{
# Now remove or move aside any old file at destination location.
# We try this two ways since rm can't unlink itself on some
# systems and the destination file might be busy for other
# reasons. In this case, the final cleanup might fail but the new
# file should still install successfully.
{
test ! -f "$dst" ||
$doit $rmcmd -f "$dst" 2>/dev/null ||
{ $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
{ $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
} ||
{ echo "$0: cannot unlink or rename $dst" >&2
(exit 1); exit 1
}
} &&
# Now rename the file to the real destination.
$doit $mvcmd "$dsttmp" "$dst"
}
fi || exit 1
trap '' 0
fi
done
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC0"
# time-stamp-end: "; # UTC"
# End:

228
build-aux/mdate-sh Executable file
View File

@ -0,0 +1,228 @@
#!/bin/sh
# Get modification time of a file or directory and pretty-print it.
scriptversion=2017-09-22.02; # UTC
# Copyright (C) 1995-2018 Free Software Foundation, Inc.
# written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, June 1995
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, 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 <https://www.gnu.org/licenses/>.
# 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 file is maintained in Automake, please report
# bugs to <bug-automake@gnu.org> or send patches to
# <automake-patches@gnu.org>.
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
fi
case $1 in
'')
echo "$0: No file. Try '$0 --help' for more information." 1>&2
exit 1;
;;
-h | --h*)
cat <<\EOF
Usage: mdate-sh [--help] [--version] FILE
Pretty-print the modification day of FILE, in the format:
1 January 1970
Report bugs to <bug-automake@gnu.org>.
EOF
exit $?
;;
-v | --v*)
echo "mdate-sh $scriptversion"
exit $?
;;
esac
error ()
{
echo "$0: $1" >&2
exit 1
}
# Prevent date giving response in another language.
LANG=C
export LANG
LC_ALL=C
export LC_ALL
LC_TIME=C
export LC_TIME
# Use UTC to get reproducible result.
TZ=UTC0
export TZ
# GNU ls changes its time format in response to the TIME_STYLE
# variable. Since we cannot assume 'unset' works, revert this
# variable to its documented default.
if test "${TIME_STYLE+set}" = set; then
TIME_STYLE=posix-long-iso
export TIME_STYLE
fi
save_arg1=$1
# Find out how to get the extended ls output of a file or directory.
if ls -L /dev/null 1>/dev/null 2>&1; then
ls_command='ls -L -l -d'
else
ls_command='ls -l -d'
fi
# Avoid user/group names that might have spaces, when possible.
if ls -n /dev/null 1>/dev/null 2>&1; then
ls_command="$ls_command -n"
fi
# A 'ls -l' line looks as follows on OS/2.
# drwxrwx--- 0 Aug 11 2001 foo
# This differs from Unix, which adds ownership information.
# drwxrwx--- 2 root root 4096 Aug 11 2001 foo
#
# To find the date, we split the line on spaces and iterate on words
# until we find a month. This cannot work with files whose owner is a
# user named "Jan", or "Feb", etc. However, it's unlikely that '/'
# will be owned by a user whose name is a month. So we first look at
# the extended ls output of the root directory to decide how many
# words should be skipped to get the date.
# On HPUX /bin/sh, "set" interprets "-rw-r--r--" as options, so the "x" below.
set x`$ls_command /`
# Find which argument is the month.
month=
command=
until test $month
do
test $# -gt 0 || error "failed parsing '$ls_command /' output"
shift
# Add another shift to the command.
command="$command shift;"
case $1 in
Jan) month=January; nummonth=1;;
Feb) month=February; nummonth=2;;
Mar) month=March; nummonth=3;;
Apr) month=April; nummonth=4;;
May) month=May; nummonth=5;;
Jun) month=June; nummonth=6;;
Jul) month=July; nummonth=7;;
Aug) month=August; nummonth=8;;
Sep) month=September; nummonth=9;;
Oct) month=October; nummonth=10;;
Nov) month=November; nummonth=11;;
Dec) month=December; nummonth=12;;
esac
done
test -n "$month" || error "failed parsing '$ls_command /' output"
# Get the extended ls output of the file or directory.
set dummy x`eval "$ls_command \"\\\$save_arg1\""`
# Remove all preceding arguments
eval $command
# Because of the dummy argument above, month is in $2.
#
# On a POSIX system, we should have
#
# $# = 5
# $1 = file size
# $2 = month
# $3 = day
# $4 = year or time
# $5 = filename
#
# On Darwin 7.7.0 and 7.6.0, we have
#
# $# = 4
# $1 = day
# $2 = month
# $3 = year or time
# $4 = filename
# Get the month.
case $2 in
Jan) month=January; nummonth=1;;
Feb) month=February; nummonth=2;;
Mar) month=March; nummonth=3;;
Apr) month=April; nummonth=4;;
May) month=May; nummonth=5;;
Jun) month=June; nummonth=6;;
Jul) month=July; nummonth=7;;
Aug) month=August; nummonth=8;;
Sep) month=September; nummonth=9;;
Oct) month=October; nummonth=10;;
Nov) month=November; nummonth=11;;
Dec) month=December; nummonth=12;;
esac
case $3 in
???*) day=$1;;
*) day=$3; shift;;
esac
# Here we have to deal with the problem that the ls output gives either
# the time of day or the year.
case $3 in
*:*) set `date`; eval year=\$$#
case $2 in
Jan) nummonthtod=1;;
Feb) nummonthtod=2;;
Mar) nummonthtod=3;;
Apr) nummonthtod=4;;
May) nummonthtod=5;;
Jun) nummonthtod=6;;
Jul) nummonthtod=7;;
Aug) nummonthtod=8;;
Sep) nummonthtod=9;;
Oct) nummonthtod=10;;
Nov) nummonthtod=11;;
Dec) nummonthtod=12;;
esac
# For the first six month of the year the time notation can also
# be used for files modified in the last year.
if (expr $nummonth \> $nummonthtod) > /dev/null;
then
year=`expr $year - 1`
fi;;
*) year=$3;;
esac
# The result.
echo $day $month $year
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC0"
# time-stamp-end: "; # UTC"
# End:

215
build-aux/missing Executable file
View File

@ -0,0 +1,215 @@
#! /bin/sh
# Common wrapper for a few potentially missing GNU programs.
scriptversion=2016-01-11.22; # UTC
# Copyright (C) 1996-2017 Free Software Foundation, Inc.
# Originally written by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, 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 <http://www.gnu.org/licenses/>.
# 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.
if test $# -eq 0; then
echo 1>&2 "Try '$0 --help' for more information"
exit 1
fi
case $1 in
--is-lightweight)
# Used by our autoconf macros to check whether the available missing
# script is modern enough.
exit 0
;;
--run)
# Back-compat with the calling convention used by older automake.
shift
;;
-h|--h|--he|--hel|--help)
echo "\
$0 [OPTION]... PROGRAM [ARGUMENT]...
Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due
to PROGRAM being missing or too old.
Options:
-h, --help display this help and exit
-v, --version output version information and exit
Supported PROGRAM values:
aclocal autoconf autoheader autom4te automake makeinfo
bison yacc flex lex help2man
Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and
'g' are ignored when checking the name.
Send bug reports to <bug-automake@gnu.org>."
exit $?
;;
-v|--v|--ve|--ver|--vers|--versi|--versio|--version)
echo "missing $scriptversion (GNU Automake)"
exit $?
;;
-*)
echo 1>&2 "$0: unknown '$1' option"
echo 1>&2 "Try '$0 --help' for more information"
exit 1
;;
esac
# Run the given program, remember its exit status.
"$@"; st=$?
# If it succeeded, we are done.
test $st -eq 0 && exit 0
# Also exit now if we it failed (or wasn't found), and '--version' was
# passed; such an option is passed most likely to detect whether the
# program is present and works.
case $2 in --version|--help) exit $st;; esac
# Exit code 63 means version mismatch. This often happens when the user
# tries to use an ancient version of a tool on a file that requires a
# minimum version.
if test $st -eq 63; then
msg="probably too old"
elif test $st -eq 127; then
# Program was missing.
msg="missing on your system"
else
# Program was found and executed, but failed. Give up.
exit $st
fi
perl_URL=http://www.perl.org/
flex_URL=http://flex.sourceforge.net/
gnu_software_URL=http://www.gnu.org/software
program_details ()
{
case $1 in
aclocal|automake)
echo "The '$1' program is part of the GNU Automake package:"
echo "<$gnu_software_URL/automake>"
echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:"
echo "<$gnu_software_URL/autoconf>"
echo "<$gnu_software_URL/m4/>"
echo "<$perl_URL>"
;;
autoconf|autom4te|autoheader)
echo "The '$1' program is part of the GNU Autoconf package:"
echo "<$gnu_software_URL/autoconf/>"
echo "It also requires GNU m4 and Perl in order to run:"
echo "<$gnu_software_URL/m4/>"
echo "<$perl_URL>"
;;
esac
}
give_advice ()
{
# Normalize program name to check for.
normalized_program=`echo "$1" | sed '
s/^gnu-//; t
s/^gnu//; t
s/^g//; t'`
printf '%s\n' "'$1' is $msg."
configure_deps="'configure.ac' or m4 files included by 'configure.ac'"
case $normalized_program in
autoconf*)
echo "You should only need it if you modified 'configure.ac',"
echo "or m4 files included by it."
program_details 'autoconf'
;;
autoheader*)
echo "You should only need it if you modified 'acconfig.h' or"
echo "$configure_deps."
program_details 'autoheader'
;;
automake*)
echo "You should only need it if you modified 'Makefile.am' or"
echo "$configure_deps."
program_details 'automake'
;;
aclocal*)
echo "You should only need it if you modified 'acinclude.m4' or"
echo "$configure_deps."
program_details 'aclocal'
;;
autom4te*)
echo "You might have modified some maintainer files that require"
echo "the 'autom4te' program to be rebuilt."
program_details 'autom4te'
;;
bison*|yacc*)
echo "You should only need it if you modified a '.y' file."
echo "You may want to install the GNU Bison package:"
echo "<$gnu_software_URL/bison/>"
;;
lex*|flex*)
echo "You should only need it if you modified a '.l' file."
echo "You may want to install the Fast Lexical Analyzer package:"
echo "<$flex_URL>"
;;
help2man*)
echo "You should only need it if you modified a dependency" \
"of a man page."
echo "You may want to install the GNU Help2man package:"
echo "<$gnu_software_URL/help2man/>"
;;
makeinfo*)
echo "You should only need it if you modified a '.texi' file, or"
echo "any other file indirectly affecting the aspect of the manual."
echo "You might want to install the Texinfo package:"
echo "<$gnu_software_URL/texinfo/>"
echo "The spurious makeinfo call might also be the consequence of"
echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might"
echo "want to install GNU make:"
echo "<$gnu_software_URL/make/>"
;;
*)
echo "You might have modified some files without having the proper"
echo "tools for further handling them. Check the 'README' file, it"
echo "often tells you about the needed prerequisites for installing"
echo "this package. You may also peek at any GNU archive site, in"
echo "case some other package contains this missing '$1' program."
;;
esac
}
give_advice "$1" | sed -e '1s/^/WARNING: /' \
-e '2,$s/^/ /' >&2
# Propagate the correct exit status (expected to be 127 for a program
# not found, 63 for a program that failed due to version mismatch).
exit $st
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC0"
# time-stamp-end: "; # UTC"
# End:

148
build-aux/test-driver Executable file
View File

@ -0,0 +1,148 @@
#! /bin/sh
# test-driver - basic testsuite driver script.
scriptversion=2016-01-11.22; # UTC
# Copyright (C) 2011-2017 Free Software Foundation, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, 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 <http://www.gnu.org/licenses/>.
# 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 file is maintained in Automake, please report
# bugs to <bug-automake@gnu.org> or send patches to
# <automake-patches@gnu.org>.
# Make unconditional expansion of undefined variables an error. This
# helps a lot in preventing typo-related bugs.
set -u
usage_error ()
{
echo "$0: $*" >&2
print_usage >&2
exit 2
}
print_usage ()
{
cat <<END
Usage:
test-driver --test-name=NAME --log-file=PATH --trs-file=PATH
[--expect-failure={yes|no}] [--color-tests={yes|no}]
[--enable-hard-errors={yes|no}] [--]
TEST-SCRIPT [TEST-SCRIPT-ARGUMENTS]
The '--test-name', '--log-file' and '--trs-file' options are mandatory.
END
}
test_name= # Used for reporting.
log_file= # Where to save the output of the test script.
trs_file= # Where to save the metadata of the test run.
expect_failure=no
color_tests=no
enable_hard_errors=yes
while test $# -gt 0; do
case $1 in
--help) print_usage; exit $?;;
--version) echo "test-driver $scriptversion"; exit $?;;
--test-name) test_name=$2; shift;;
--log-file) log_file=$2; shift;;
--trs-file) trs_file=$2; shift;;
--color-tests) color_tests=$2; shift;;
--expect-failure) expect_failure=$2; shift;;
--enable-hard-errors) enable_hard_errors=$2; shift;;
--) shift; break;;
-*) usage_error "invalid option: '$1'";;
*) break;;
esac
shift
done
missing_opts=
test x"$test_name" = x && missing_opts="$missing_opts --test-name"
test x"$log_file" = x && missing_opts="$missing_opts --log-file"
test x"$trs_file" = x && missing_opts="$missing_opts --trs-file"
if test x"$missing_opts" != x; then
usage_error "the following mandatory options are missing:$missing_opts"
fi
if test $# -eq 0; then
usage_error "missing argument"
fi
if test $color_tests = yes; then
# Keep this in sync with 'lib/am/check.am:$(am__tty_colors)'.
red='' # Red.
grn='' # Green.
lgn='' # Light green.
blu='' # Blue.
mgn='' # Magenta.
std='' # No color.
else
red= grn= lgn= blu= mgn= std=
fi
do_exit='rm -f $log_file $trs_file; (exit $st); exit $st'
trap "st=129; $do_exit" 1
trap "st=130; $do_exit" 2
trap "st=141; $do_exit" 13
trap "st=143; $do_exit" 15
# Test script is run here.
"$@" >$log_file 2>&1
estatus=$?
if test $enable_hard_errors = no && test $estatus -eq 99; then
tweaked_estatus=1
else
tweaked_estatus=$estatus
fi
case $tweaked_estatus:$expect_failure in
0:yes) col=$red res=XPASS recheck=yes gcopy=yes;;
0:*) col=$grn res=PASS recheck=no gcopy=no;;
77:*) col=$blu res=SKIP recheck=no gcopy=yes;;
99:*) col=$mgn res=ERROR recheck=yes gcopy=yes;;
*:yes) col=$lgn res=XFAIL recheck=no gcopy=yes;;
*:*) col=$red res=FAIL recheck=yes gcopy=yes;;
esac
# Report the test outcome and exit status in the logs, so that one can
# know whether the test passed or failed simply by looking at the '.log'
# file, without the need of also peaking into the corresponding '.trs'
# file (automake bug#11814).
echo "$res $test_name (exit status: $estatus)" >>$log_file
# Report outcome to console.
echo "${col}${res}${std}: $test_name"
# Register the test result, and other relevant metadata.
echo ":test-result: $res" > $trs_file
echo ":global-test-result: $res" >> $trs_file
echo ":recheck: $recheck" >> $trs_file
echo ":copy-in-global-log: $gcopy" >> $trs_file
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC0"
# time-stamp-end: "; # UTC"
# End:

11727
build-aux/texinfo.tex Normal file

File diff suppressed because it is too large Load Diff

277
build-aux/update-copyright Executable file
View File

@ -0,0 +1,277 @@
eval '(exit $?0)' && eval 'exec perl -wS -0777 -pi "$0" "$@"'
& eval 'exec perl -wS -0777 -pi "$0" $argv:q'
if 0;
# Update an FSF copyright year list to include the current year.
my $VERSION = '2018-01-04.14:48'; # UTC
# Copyright (C) 2009-2018 Free Software Foundation, Inc.
#
# 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, 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 <https://www.gnu.org/licenses/>.
# Written by Jim Meyering and Joel E. Denny
# The arguments to this script should be names of files that contain
# copyright statements to be updated. The copyright holder's name
# defaults to "Free Software Foundation, Inc." but may be changed to
# any other name by using the "UPDATE_COPYRIGHT_HOLDER" environment
# variable.
#
# For example, you might wish to use the update-copyright target rule
# in maint.mk from gnulib's maintainer-makefile module.
#
# Iff a copyright statement is recognized in a file and the final
# year is not the current year, then the statement is updated for the
# new year and it is reformatted to:
#
# 1. Fit within 72 columns.
# 2. Convert 2-digit years to 4-digit years by prepending "19".
# 3. Expand copyright year intervals. (See "Environment variables"
# below.)
#
# A warning is printed for every file for which no copyright
# statement is recognized.
#
# Each file's copyright statement must be formatted correctly in
# order to be recognized. For example, each of these is fine:
#
# Copyright @copyright{} 1990-2005, 2007-2009 Free Software
# Foundation, Inc.
#
# # Copyright (C) 1990-2005, 2007-2009 Free Software
# # Foundation, Inc.
#
# /*
# * Copyright &copy; 90,2005,2007-2009
# * Free Software Foundation, Inc.
# */
#
# However, the following format is not recognized because the line
# prefix changes after the first line:
#
# ## Copyright (C) 1990-2005, 2007-2009 Free Software
# # Foundation, Inc.
#
# However, any correctly formatted copyright statement following
# a non-matching copyright statements would be recognized.
#
# The exact conditions that a file's copyright statement must meet
# to be recognized are:
#
# 1. It is the first copyright statement that meets all of the
# following conditions. Subsequent copyright statements are
# ignored.
# 2. Its format is "Copyright (C)", then a list of copyright years,
# and then the name of the copyright holder.
# 3. The "(C)" takes one of the following forms or is omitted
# entirely:
#
# A. (C)
# B. (c)
# C. @copyright{}
# D. &copy;
# E. ©
#
# 4. The "Copyright" appears at the beginning of a line, except that it
# may be prefixed by any sequence (e.g., a comment) of no more than
# 5 characters -- including white space.
# 5. Iff such a prefix is present, the same prefix appears at the
# beginning of each remaining line within the FSF copyright
# statement. There is one exception in order to support C-style
# comments: if the first line's prefix contains nothing but
# whitespace surrounding a "/*", then the prefix for all subsequent
# lines is the same as the first line's prefix except with each of
# "/" and possibly "*" replaced by a " ". The replacement of "*"
# by " " is consistent throughout all subsequent lines.
# 6. Blank lines, even if preceded by the prefix, do not appear
# within the FSF copyright statement.
# 7. Each copyright year is 2 or 4 digits, and years are separated by
# commas or dashes. Whitespace may appear after commas.
#
# Environment variables:
#
# 1. If UPDATE_COPYRIGHT_FORCE=1, a recognized FSF copyright statement
# is reformatted even if it does not need updating for the new
# year. If unset or set to 0, only updated FSF copyright
# statements are reformatted.
# 2. If UPDATE_COPYRIGHT_USE_INTERVALS=1, every series of consecutive
# copyright years (such as 90, 1991, 1992-2007, 2008) in a
# reformatted FSF copyright statement is collapsed to a single
# interval (such as 1990-2008). If unset or set to 0, all existing
# copyright year intervals in a reformatted FSF copyright statement
# are expanded instead.
# If UPDATE_COPYRIGHT_USE_INTERVALS=2, convert a sequence with gaps
# to the minimal containing range. For example, convert
# 2000, 2004-2007, 2009 to 2000-2009.
# 3. For testing purposes, you can set the assumed current year in
# UPDATE_COPYRIGHT_YEAR.
# 4. The default maximum line length for a copyright line is 72.
# Set UPDATE_COPYRIGHT_MAX_LINE_LENGTH to use a different length.
# 5. Set UPDATE_COPYRIGHT_HOLDER if the copyright holder is other
# than "Free Software Foundation, Inc.".
use strict;
use warnings;
my $copyright_re = 'Copyright';
my $circle_c_re = '(?:\([cC]\)|@copyright\{}|\\\\\(co|&copy;|©)';
my $holder = $ENV{UPDATE_COPYRIGHT_HOLDER};
$holder ||= 'Free Software Foundation, Inc.';
my $prefix_max = 5;
my $margin = $ENV{UPDATE_COPYRIGHT_MAX_LINE_LENGTH};
!$margin || $margin !~ m/^\d+$/
and $margin = 72;
my $tab_width = 8;
my $this_year = $ENV{UPDATE_COPYRIGHT_YEAR};
if (!$this_year || $this_year !~ m/^\d{4}$/)
{
my ($sec, $min, $hour, $mday, $month, $year) = localtime (time ());
$this_year = $year + 1900;
}
# Unless the file consistently uses "\r\n" as the EOL, use "\n" instead.
my $eol = /(?:^|[^\r])\n/ ? "\n" : "\r\n";
my $leading;
my $prefix;
my $ws_re;
my $stmt_re;
while (/(^|\n)(.{0,$prefix_max})$copyright_re/g)
{
$leading = "$1$2";
$prefix = $2;
if ($prefix =~ /^(\s*\/)\*(\s*)$/)
{
$prefix =~ s,/, ,;
my $prefix_ws = $prefix;
$prefix_ws =~ s/\*/ /; # Only whitespace.
if (/\G(?:[^*\n]|\*[^\/\n])*\*?\n$prefix_ws/)
{
$prefix = $prefix_ws;
}
}
$ws_re = '[ \t\r\f]'; # \s without \n
$ws_re =
"(?:$ws_re*(?:$ws_re|\\n" . quotemeta($prefix) . ")$ws_re*)";
my $holder_re = $holder;
$holder_re =~ s/\s/$ws_re/g;
my $stmt_remainder_re =
"(?:$ws_re$circle_c_re)?"
. "$ws_re(?:(?:\\d\\d)?\\d\\d(?:,$ws_re?|-))*"
. "((?:\\d\\d)?\\d\\d)$ws_re$holder_re";
if (/\G$stmt_remainder_re/)
{
$stmt_re =
quotemeta($leading) . "($copyright_re$stmt_remainder_re)";
last;
}
}
if (defined $stmt_re)
{
/$stmt_re/ or die; # Should never die.
my $stmt = $1;
my $final_year_orig = $2;
# Handle two-digit year numbers like "98" and "99".
my $final_year = $final_year_orig;
$final_year <= 99
and $final_year += 1900;
if ($final_year != $this_year)
{
# Update the year.
$stmt =~ s/\b$final_year_orig\b/$final_year, $this_year/;
}
if ($final_year != $this_year || $ENV{'UPDATE_COPYRIGHT_FORCE'})
{
# Normalize all whitespace including newline-prefix sequences.
$stmt =~ s/$ws_re/ /g;
# Put spaces after commas.
$stmt =~ s/, ?/, /g;
# Convert 2-digit to 4-digit years.
$stmt =~ s/(\b\d\d\b)/19$1/g;
# Make the use of intervals consistent.
if (!$ENV{UPDATE_COPYRIGHT_USE_INTERVALS})
{
$stmt =~ s/(\d{4})-(\d{4})/join(', ', $1..$2)/eg;
}
else
{
$stmt =~
s/
(\d{4})
(?:
(,\ |-)
((??{
if ($2 eq '-') { '\d{4}'; }
elsif (!$3) { $1 + 1; }
else { $3 + 1; }
}))
)+
/$1-$3/gx;
# When it's 2, emit a single range encompassing all year numbers.
$ENV{UPDATE_COPYRIGHT_USE_INTERVALS} == 2
and $stmt =~ s/\b(\d{4})\b.*\b(\d{4})\b/$1-$2/;
}
# Format within margin.
my $stmt_wrapped;
my $text_margin = $margin - length($prefix);
if ($prefix =~ /^(\t+)/)
{
$text_margin -= length($1) * ($tab_width - 1);
}
while (length $stmt)
{
if (($stmt =~ s/^(.{1,$text_margin})(?: |$)//)
|| ($stmt =~ s/^([\S]+)(?: |$)//))
{
my $line = $1;
$stmt_wrapped .= $stmt_wrapped ? "$eol$prefix" : $leading;
$stmt_wrapped .= $line;
}
else
{
# Should be unreachable, but we don't want an infinite
# loop if it can be reached.
die;
}
}
# Replace the old copyright statement.
s/$stmt_re/$stmt_wrapped/;
}
}
else
{
print STDERR "$ARGV: warning: copyright statement not found\n";
}
# Hey Emacs!
# Local variables:
# coding: utf-8
# mode: perl
# indent-tabs-mode: nil
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "my $VERSION = '"
# time-stamp-format: "%:y-%02m-%02d.%02H:%02M"
# time-stamp-time-zone: "UTC0"
# time-stamp-end: "'; # UTC"
# End:

210
build-aux/useless-if-before-free Executable file
View File

@ -0,0 +1,210 @@
eval '(exit $?0)' && eval 'exec perl -wST "$0" "$@"'
& eval 'exec perl -wST "$0" $argv:q'
if 0;
# Detect instances of "if (p) free (p);".
# Likewise "if (p != 0)", "if (0 != p)", or with NULL; and with braces.
my $VERSION = '2017-09-13 06:45'; # UTC
# The definition above must lie within the first 8 lines in order
# for the Emacs time-stamp write hook (at end) to update it.
# If you change this file with Emacs, please let the write hook
# do its job. Otherwise, update this string manually.
# Copyright (C) 2008-2018 Free Software Foundation, Inc.
# 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 <https://www.gnu.org/licenses/>.
# Written by Jim Meyering
use strict;
use warnings;
use Getopt::Long;
(my $ME = $0) =~ s|.*/||;
# use File::Coda; # https://meyering.net/code/Coda/
END {
defined fileno STDOUT or return;
close STDOUT and return;
warn "$ME: failed to close standard output: $!\n";
$? ||= 1;
}
sub usage ($)
{
my ($exit_code) = @_;
my $STREAM = ($exit_code == 0 ? *STDOUT : *STDERR);
if ($exit_code != 0)
{
print $STREAM "Try '$ME --help' for more information.\n";
}
else
{
print $STREAM <<EOF;
Usage: $ME [OPTIONS] FILE...
Detect any instance in FILE of a useless "if" test before a free call, e.g.,
"if (p) free (p);". Any such test may be safely removed without affecting
the semantics of the C code in FILE. Use --name=FOO --name=BAR to also
detect free-like functions named FOO and BAR.
OPTIONS:
--list print only the name of each matching FILE (\\0-terminated)
--name=N add name N to the list of \'free\'-like functions to detect;
may be repeated
--help display this help and exit
--version output version information and exit
Exit status:
0 one or more matches
1 no match
2 an error
EXAMPLE:
For example, this command prints all removable "if" tests before "free"
and "kfree" calls in the linux kernel sources:
git ls-files -z |xargs -0 $ME --name=kfree
EOF
}
exit $exit_code;
}
sub is_NULL ($)
{
my ($expr) = @_;
return ($expr eq 'NULL' || $expr eq '0');
}
{
sub EXIT_MATCH {0}
sub EXIT_NO_MATCH {1}
sub EXIT_ERROR {2}
my $err = EXIT_NO_MATCH;
my $list;
my @name = qw(free);
GetOptions
(
help => sub { usage 0 },
version => sub { print "$ME version $VERSION\n"; exit },
list => \$list,
'name=s@' => \@name,
) or usage 1;
# Make sure we have the right number of non-option arguments.
# Always tell the user why we fail.
@ARGV < 1
and (warn "$ME: missing FILE argument\n"), usage EXIT_ERROR;
my $or = join '|', @name;
my $regexp = qr/(?:$or)/;
# Set the input record separator.
# Note: this makes it impractical to print line numbers.
$/ = '"';
my $found_match = 0;
FILE:
foreach my $file (@ARGV)
{
open FH, '<', $file
or (warn "$ME: can't open '$file' for reading: $!\n"),
$err = EXIT_ERROR, next;
while (defined (my $line = <FH>))
{
# Skip non-matching lines early to save time
$line =~ /\bif\b/
or next;
while ($line =~
/\b(if\s*\(\s*([^)]+?)(?:\s*!=\s*([^)]+?))?\s*\)
# 1 2 3
(?: \s*$regexp\s*\((?:\s*\([^)]+\))?\s*([^)]+)\)\s*;|
\s*\{\s*$regexp\s*\((?:\s*\([^)]+\))?\s*([^)]+)\)\s*;\s*\}))/sxg)
{
my $all = $1;
my ($lhs, $rhs) = ($2, $3);
my ($free_opnd, $braced_free_opnd) = ($4, $5);
my $non_NULL;
if (!defined $rhs) { $non_NULL = $lhs }
elsif (is_NULL $rhs) { $non_NULL = $lhs }
elsif (is_NULL $lhs) { $non_NULL = $rhs }
else { next }
# Compare the non-NULL part of the "if" expression and the
# free'd expression, without regard to white space.
$non_NULL =~ tr/ \t//d;
my $e2 = defined $free_opnd ? $free_opnd : $braced_free_opnd;
$e2 =~ tr/ \t//d;
if ($non_NULL eq $e2)
{
$found_match = 1;
$list
and (print "$file\0"), next FILE;
print "$file: $all\n";
}
}
}
}
continue
{
close FH;
}
$found_match && $err == EXIT_NO_MATCH
and $err = EXIT_MATCH;
exit $err;
}
my $foo = <<'EOF';
# The above is to *find* them.
# This adjusts them, removing the unnecessary "if (p)" part.
# FIXME: do something like this as an option (doesn't do braces):
free=xfree
git grep -l -z "$free *(" \
| xargs -0 useless-if-before-free -l --name="$free" \
| xargs -0 perl -0x3b -pi -e \
's/\bif\s*\(\s*(\S+?)(?:\s*!=\s*(?:0|NULL))?\s*\)\s+('"$free"'\s*\((?:\s*\([^)]+\))?\s*\1\s*\)\s*;)/$2/s'
# Use the following to remove redundant uses of kfree inside braces.
# Note that -0777 puts perl in slurp-whole-file mode;
# but we have plenty of memory, these days...
free=kfree
git grep -l -z "$free *(" \
| xargs -0 useless-if-before-free -l --name="$free" \
| xargs -0 perl -0777 -pi -e \
's/\bif\s*\(\s*(\S+?)(?:\s*!=\s*(?:0|NULL))?\s*\)\s*\{\s*('"$free"'\s*\((?:\s*\([^)]+\))?\s*\1\s*\);)\s*\}[^\n]*$/$2/gms'
Be careful that the result of the above transformation is valid.
If the matched string is followed by "else", then obviously, it won't be.
When modifying files, refuse to process anything other than a regular file.
EOF
## Local Variables:
## mode: perl
## indent-tabs-mode: nil
## eval: (add-hook 'write-file-hooks 'time-stamp)
## time-stamp-start: "my $VERSION = '"
## time-stamp-format: "%:y-%02m-%02d %02H:%02M"
## time-stamp-time-zone: "UTC0"
## time-stamp-end: "'; # UTC"
## End:

113
build-aux/vc-list-files Executable file
View File

@ -0,0 +1,113 @@
#!/bin/sh
# List version-controlled file names.
# Print a version string.
scriptversion=2017-09-13.06; # UTC
# Copyright (C) 2006-2018 Free Software Foundation, Inc.
# 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 <https://www.gnu.org/licenses/>.
# List the specified version-controlled files.
# With no argument, list them all. With a single DIRECTORY argument,
# list the version-controlled files in that directory.
# If there's an argument, it must be a single, "."-relative directory name.
# cvsu is part of the cvsutils package: http://www.red-bean.com/cvsutils/
postprocess=
case $1 in
--help) cat <<EOF
Usage: $0 [-C SRCDIR] [DIR...]
Output a list of version-controlled files in DIR (default .), relative to
SRCDIR (default .). SRCDIR must be the top directory of a checkout.
Options:
--help print this help, then exit
--version print version number, then exit
-C SRCDIR change directory to SRCDIR before generating list
Report bugs and patches to <bug-gnulib@gnu.org>.
EOF
exit ;;
--version)
year=`echo "$scriptversion" | sed 's/[^0-9].*//'`
cat <<EOF
vc-list-files $scriptversion
Copyright (C) $year Free Software Foundation, Inc,
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
EOF
exit ;;
-C)
test "$2" = . || postprocess="| sed 's|^|$2/|'"
cd "$2" || exit 1
shift; shift ;;
esac
test $# = 0 && set .
for dir
do
if test -d .git || test -f .git; then
test "x$dir" = x. \
&& dir= sed_esc= \
|| { dir="$dir/"; sed_esc=`echo "$dir"|env sed 's,\([\\/]\),\\\\\1,g'`; }
# Ignore git symlinks - either they point into the tree, in which case
# we don't need to visit the target twice, or they point somewhere
# else (often into a submodule), in which case the content does not
# belong to this package.
eval exec git ls-tree -r 'HEAD:"$dir"' \
\| sed -n '"s/^100[^ ]*./$sed_esc/p"' $postprocess
elif test -d .hg; then
eval exec hg locate '"$dir/*"' $postprocess
elif test -d .bzr; then
test "$postprocess" = '' && postprocess="| sed 's|^\./||'"
eval exec bzr ls -R --versioned '"$dir"' $postprocess
elif test -d CVS; then
test "$postprocess" = '' && postprocess="| sed 's|^\./||'"
if test -x build-aux/cvsu; then
eval build-aux/cvsu --find --types=AFGM '"$dir"' $postprocess
elif (cvsu --help) >/dev/null 2>&1; then
eval cvsu --find --types=AFGM '"$dir"' $postprocess
else
eval awk -F/ \''{ \
if (!$1 && $3 !~ /^-/) { \
f=FILENAME; \
if (f ~ /CVS\/Entries$/) \
f = substr(f, 1, length(f)-11); \
print f $2; \
}}'\'' \
`find "$dir" -name Entries -print` /dev/null' $postprocess
fi
elif test -d .svn; then
eval exec svn list -R '"$dir"' $postprocess
else
echo "$0: Failed to determine type of version control used in `pwd`" 1>&2
exit 1
fi
done
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC0"
# time-stamp-end: "; # UTC"
# End:

247
build-aux/ylwrap Executable file
View File

@ -0,0 +1,247 @@
#! /bin/sh
# ylwrap - wrapper for lex/yacc invocations.
scriptversion=2016-01-11.22; # UTC
# Copyright (C) 1996-2017 Free Software Foundation, Inc.
#
# Written by Tom Tromey <tromey@cygnus.com>.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, 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 <http://www.gnu.org/licenses/>.
# 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 file is maintained in Automake, please report
# bugs to <bug-automake@gnu.org> or send patches to
# <automake-patches@gnu.org>.
get_dirname ()
{
case $1 in
*/*|*\\*) printf '%s\n' "$1" | sed -e 's|\([\\/]\)[^\\/]*$|\1|';;
# Otherwise, we want the empty string (not ".").
esac
}
# guard FILE
# ----------
# The CPP macro used to guard inclusion of FILE.
guard ()
{
printf '%s\n' "$1" \
| sed \
-e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/' \
-e 's/[^ABCDEFGHIJKLMNOPQRSTUVWXYZ]/_/g' \
-e 's/__*/_/g'
}
# quote_for_sed [STRING]
# ----------------------
# Return STRING (or stdin) quoted to be used as a sed pattern.
quote_for_sed ()
{
case $# in
0) cat;;
1) printf '%s\n' "$1";;
esac \
| sed -e 's|[][\\.*]|\\&|g'
}
case "$1" in
'')
echo "$0: No files given. Try '$0 --help' for more information." 1>&2
exit 1
;;
--basedir)
basedir=$2
shift 2
;;
-h|--h*)
cat <<\EOF
Usage: ylwrap [--help|--version] INPUT [OUTPUT DESIRED]... -- PROGRAM [ARGS]...
Wrapper for lex/yacc invocations, renaming files as desired.
INPUT is the input file
OUTPUT is one file PROG generates
DESIRED is the file we actually want instead of OUTPUT
PROGRAM is program to run
ARGS are passed to PROG
Any number of OUTPUT,DESIRED pairs may be used.
Report bugs to <bug-automake@gnu.org>.
EOF
exit $?
;;
-v|--v*)
echo "ylwrap $scriptversion"
exit $?
;;
esac
# The input.
input=$1
shift
# We'll later need for a correct munging of "#line" directives.
input_sub_rx=`get_dirname "$input" | quote_for_sed`
case $input in
[\\/]* | ?:[\\/]*)
# Absolute path; do nothing.
;;
*)
# Relative path. Make it absolute.
input=`pwd`/$input
;;
esac
input_rx=`get_dirname "$input" | quote_for_sed`
# Since DOS filename conventions don't allow two dots,
# the DOS version of Bison writes out y_tab.c instead of y.tab.c
# and y_tab.h instead of y.tab.h. Test to see if this is the case.
y_tab_nodot=false
if test -f y_tab.c || test -f y_tab.h; then
y_tab_nodot=true
fi
# The parser itself, the first file, is the destination of the .y.c
# rule in the Makefile.
parser=$1
# A sed program to s/FROM/TO/g for all the FROM/TO so that, for
# instance, we rename #include "y.tab.h" into #include "parse.h"
# during the conversion from y.tab.c to parse.c.
sed_fix_filenames=
# Also rename header guards, as Bison 2.7 for instance uses its header
# guard in its implementation file.
sed_fix_header_guards=
while test $# -ne 0; do
if test x"$1" = x"--"; then
shift
break
fi
from=$1
# Handle y_tab.c and y_tab.h output by DOS
if $y_tab_nodot; then
case $from in
"y.tab.c") from=y_tab.c;;
"y.tab.h") from=y_tab.h;;
esac
fi
shift
to=$1
shift
sed_fix_filenames="${sed_fix_filenames}s|"`quote_for_sed "$from"`"|$to|g;"
sed_fix_header_guards="${sed_fix_header_guards}s|"`guard "$from"`"|"`guard "$to"`"|g;"
done
# The program to run.
prog=$1
shift
# Make any relative path in $prog absolute.
case $prog in
[\\/]* | ?:[\\/]*) ;;
*[\\/]*) prog=`pwd`/$prog ;;
esac
dirname=ylwrap$$
do_exit="cd '`pwd`' && rm -rf $dirname > /dev/null 2>&1;"' (exit $ret); exit $ret'
trap "ret=129; $do_exit" 1
trap "ret=130; $do_exit" 2
trap "ret=141; $do_exit" 13
trap "ret=143; $do_exit" 15
mkdir $dirname || exit 1
cd $dirname
case $# in
0) "$prog" "$input" ;;
*) "$prog" "$@" "$input" ;;
esac
ret=$?
if test $ret -eq 0; then
for from in *
do
to=`printf '%s\n' "$from" | sed "$sed_fix_filenames"`
if test -f "$from"; then
# If $2 is an absolute path name, then just use that,
# otherwise prepend '../'.
case $to in
[\\/]* | ?:[\\/]*) target=$to;;
*) target=../$to;;
esac
# Do not overwrite unchanged header files to avoid useless
# recompilations. Always update the parser itself: it is the
# destination of the .y.c rule in the Makefile. Divert the
# output of all other files to a temporary file so we can
# compare them to existing versions.
if test $from != $parser; then
realtarget=$target
target=tmp-`printf '%s\n' "$target" | sed 's|.*[\\/]||g'`
fi
# Munge "#line" or "#" directives. Don't let the resulting
# debug information point at an absolute srcdir. Use the real
# output file name, not yy.lex.c for instance. Adjust the
# include guards too.
sed -e "/^#/!b" \
-e "s|$input_rx|$input_sub_rx|" \
-e "$sed_fix_filenames" \
-e "$sed_fix_header_guards" \
"$from" >"$target" || ret=$?
# Check whether files must be updated.
if test "$from" != "$parser"; then
if test -f "$realtarget" && cmp -s "$realtarget" "$target"; then
echo "$to is unchanged"
rm -f "$target"
else
echo "updating $to"
mv -f "$target" "$realtarget"
fi
fi
else
# A missing file is only an error for the parser. This is a
# blatant hack to let us support using "yacc -d". If -d is not
# specified, don't fail when the header file is "missing".
if test "$from" = "$parser"; then
ret=1
fi
fi
done
fi
# Remove the directory.
cd ..
rm -rf $dirname
exit $ret
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC0"
# time-stamp-end: "; # UTC"
# End:

36
cfg.mk Normal file
View File

@ -0,0 +1,36 @@
# Customize maint.mk -*- makefile -*-
# Copyright (C) 2011-2012 Free Software Foundation, Inc.
# 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 <http://www.gnu.org/licenses/>.
config_h_header = <(common|config)\.h>
update-copyright-env = \
UPDATE_COPYRIGHT_USE_INTERVALS=1 \
UPDATE_COPYRIGHT_MAX_LINE_LENGTH=79
local-checks-to-skip = \
sc_GPL_version \
sc_bindtextdomain \
sc_file_system \
sc_immutable_NEWS \
sc_obsolete_symbols \
sc_prohibit_always_true_header_tests \
sc_prohibit_magic_number_exit \
sc_prohibit_strcmp \
sc_prohibit_test_minus_ao \
sc_require_test_exit_idiom
exclude_file_name_regexp--sc_prohibit_doubled_word = ^src/util\.c$$
exclude_file_name_regexp--sc_unmarked_diagnostics = ^src/util\.c$$

2055
config.hin Normal file

File diff suppressed because it is too large Load Diff

28917
configure vendored Executable file

File diff suppressed because it is too large Load Diff

158
configure.ac Normal file
View File

@ -0,0 +1,158 @@
# Copyright (C) 1993, 1997-1999, 2002-2003, 2006, 2009, 2011-2013, 2015, 2018
# Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.
AC_PREREQ([2.65])
AC_INIT([GNU patch],
m4_esyscmd([build-aux/git-version-gen .tarball-version]),
[bug-patch@gnu.org])
AC_CONFIG_SRCDIR([src/patch.c])
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_MACRO_DIR([m4])
AC_ARG_ENABLE([merge],
[AS_HELP_STRING([--disable-merge],
[disable support for merging])])
AM_CONDITIONAL([ENABLE_MERGE], [test "$enableval" != no])
AM_CONDITIONAL([ALPHA_VERSION],
[[echo "$PACKAGE_VERSION" | grep -- "-[0-9a-f][0-9a-f]*\\(-dirty\\)\\?$" >/dev/null]])
AM_INIT_AUTOMAKE([1.11.2 -Wall gnu dist-bzip2 dist-xz color-tests parallel-tests])
AM_SILENT_RULES([yes])
AC_CONFIG_HEADERS([config.h:config.hin])
AC_PROG_CC
AC_PROG_CC_STDC
gl_EARLY
gl_USE_SYSTEM_EXTENSIONS
AC_HEADER_STDC
gl_INIT
AM_PROG_AR
AC_ARG_ENABLE([gcc-warnings],
[AS_HELP_STRING([--enable-gcc-warnings],
[turn on lots of GCC warnings (for developers)])],
[case $enableval in
yes|no) ;;
*) AC_MSG_ERROR([bad value $enableval for gcc-warnings option]) ;;
esac
gl_gcc_warnings=$enableval],
[gl_gcc_warnings=no]
)
if test "$gl_gcc_warnings" = yes; then
gl_WARN_ADD([-Werror], [WERROR_CFLAGS])
AC_SUBST([WERROR_CFLAGS])
nw=
# This, $nw, is the list of warnings we disable.
nw="$nw -Wdeclaration-after-statement" # too useful to forbid
nw="$nw -Waggregate-return" # anachronistic
nw="$nw -Wlong-long" # C90 is anachronistic (lib/gethrxtime.h)
nw="$nw -Wc++-compat" # We don't care about C++ compilers
nw="$nw -Wundef" # Warns on '#if GNULIB_FOO' etc in gnulib
nw="$nw -Wtraditional" # Warns on #elif which we use often
nw="$nw -Wcast-qual" # Too many warnings for now
nw="$nw -Wconversion" # Too many warnings for now
nw="$nw -Wsystem-headers" # Don't let system headers trigger warnings
nw="$nw -Wsign-conversion" # Too many warnings for now
nw="$nw -Wtraditional-conversion" # Too many warnings for now
nw="$nw -Wunreachable-code" # Too many warnings for now
nw="$nw -Wpadded" # Our structs are not padded
nw="$nw -Wredundant-decls" # openat.h declares e.g., mkdirat
nw="$nw -Wlogical-op" # any use of fwrite provokes this
nw="$nw -Wformat-nonliteral" # who.c and pinky.c strftime uses
nw="$nw -Wvla" # warnings in gettext.h
nw="$nw -Wnested-externs" # use of XARGMATCH/verify_function__
nw="$nw -Wswitch-enum" # Too many warnings for now
nw="$nw -Wswitch-default" # Too many warnings for now
nw="$nw -Wstack-protector" # not worth working around
nw="$nw -Wmissing-format-attribute" # not worth working around in patch
nw="$nw -Wsuggest-attribute=format" # warns about util.c
# things to fix soon:
nw="$nw -Wshadow"
nw="$nw -Wstrict-overflow"
nw="$nw -Wunsafe-loop-optimizations"
# nw="$nw -Wfloat-equal" # sort.c, seq.c
# nw="$nw -Wmissing-format-attribute" # copy.c
# nw="$nw -Winline" # system.h's readdir_ignoring_dot_and_dotdot
# ?? -Wstrict-overflow
gl_MANYWARN_ALL_GCC([ws])
gl_MANYWARN_COMPLEMENT([ws], [$ws], [$nw])
for w in $ws; do
gl_WARN_ADD([$w])
done
gl_WARN_ADD([-Wno-missing-field-initializers]) # We need this one
gl_WARN_ADD([-Wno-sign-compare]) # Too many warnings for now
gl_WARN_ADD([-Wno-unused-parameter]) # Too many warnings for now
# In spite of excluding -Wlogical-op above, it is enabled, as of
# gcc 4.5.0 20090517, and it provokes warnings in cat.c, dd.c, truncate.c
gl_WARN_ADD([-Wno-logical-op])
gl_WARN_ADD([-fdiagnostics-show-option])
gl_WARN_ADD([-funit-at-a-time])
gl_WARN_ADD([-Wno-format-nonliteral])
AC_SUBST([WARN_CFLAGS])
AC_DEFINE([lint], [1], [Define to 1 if the compiler is checking for lint.])
AC_DEFINE([_FORTIFY_SOURCE], [2],
[enable compile-time and run-time bounds-checking, and some warnings])
AC_DEFINE([GNULIB_PORTCHECK], [1], [enable some gnulib portability checks])
# We use a slightly smaller set of warning options for lib/.
# Remove the following and save the result in GNULIB_WARN_CFLAGS.
nw=
nw="$nw -Wuninitialized"
nw="$nw -Wunused-macros"
nw="$nw -Wmissing-prototypes"
nw="$nw -Wold-style-definition"
gl_MANYWARN_COMPLEMENT([GNULIB_WARN_CFLAGS], [$WARN_CFLAGS], [$nw])
AC_SUBST([GNULIB_WARN_CFLAGS])
# For gnulib-tests, the set is slightly smaller still.
nw=
nw="$nw -Wstrict-prototypes"
gl_MANYWARN_COMPLEMENT([GNULIB_TEST_WARN_CFLAGS],
[$GNULIB_WARN_CFLAGS], [$nw])
AC_SUBST([GNULIB_TEST_WARN_CFLAGS])
fi
AC_TYPE_MODE_T
AC_TYPE_OFF_T
gl_SIZE_MAX
gl_FUNC_XATTR
AC_CHECK_FUNCS(geteuid getuid raise sigaction sigprocmask sigsetmask)
AC_FUNC_SETMODE_DOS
AC_PATH_PROG([ED], [ed], [ed])
AC_DEFINE_UNQUOTED([EDITOR_PROGRAM], ["$ED"], [Name of editor program.])
AC_CONFIG_FILES([
Makefile
lib/Makefile
src/Makefile
tests/Makefile
])
AC_OUTPUT

14
lib/Makefile.am Normal file
View File

@ -0,0 +1,14 @@
## Process this file with automake to produce Makefile.in.
AM_CFLAGS =
AM_CPPFLAGS =
BUILT_SOURCES =
CLEANFILES =
EXTRA_DIST =
MAINTAINERCLEANFILES =
MOSTLYCLEANDIRS =
MOSTLYCLEANFILES =
SUFFIXES =
noinst_LIBRARIES =
include gnulib.mk

2933
lib/Makefile.in Normal file

File diff suppressed because it is too large Load Diff

10
lib/_Noreturn.h Normal file
View File

@ -0,0 +1,10 @@
#if !defined _Noreturn && __STDC_VERSION__ < 201112
# if (3 <= __GNUC__ || (__GNUC__ == 2 && 8 <= __GNUC_MINOR__) \
|| 0x5110 <= __SUNPRO_C)
# define _Noreturn __attribute__ ((__noreturn__))
# elif 1200 <= _MSC_VER
# define _Noreturn __declspec (noreturn)
# else
# define _Noreturn
# endif
#endif

65
lib/alloca.in.h Normal file
View File

@ -0,0 +1,65 @@
/* Memory allocation on the stack.
Copyright (C) 1995, 1999, 2001-2004, 2006-2018 Free Software Foundation,
Inc.
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, 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
<https://www.gnu.org/licenses/>.
*/
/* Avoid using the symbol _ALLOCA_H here, as Bison assumes _ALLOCA_H
means there is a real alloca function. */
#ifndef _GL_ALLOCA_H
#define _GL_ALLOCA_H
/* alloca (N) returns a pointer to N bytes of memory
allocated on the stack, which will last until the function returns.
Use of alloca should be avoided:
- inside arguments of function calls - undefined behaviour,
- in inline functions - the allocation may actually last until the
calling function returns,
- for huge N (say, N >= 65536) - you never know how large (or small)
the stack is, and when the stack cannot fulfill the memory allocation
request, the program just crashes.
*/
#ifndef alloca
# ifdef __GNUC__
# define alloca __builtin_alloca
# elif defined _AIX
# define alloca __alloca
# elif defined _MSC_VER
# include <malloc.h>
# define alloca _alloca
# elif defined __DECC && defined __VMS
# define alloca __ALLOCA
# elif defined __TANDEM && defined _TNS_E_TARGET
# ifdef __cplusplus
extern "C"
# endif
void *_alloca (unsigned short);
# pragma intrinsic (_alloca)
# define alloca _alloca
# elif defined __MVS__
# include <stdlib.h>
# else
# include <stddef.h>
# ifdef __cplusplus
extern "C"
# endif
void *alloca (size_t);
# endif
#endif
#endif /* _GL_ALLOCA_H */

26
lib/arg-nonnull.h Normal file
View File

@ -0,0 +1,26 @@
/* A C macro for declaring that specific arguments must not be NULL.
Copyright (C) 2009-2018 Free Software Foundation, Inc.
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 <https://www.gnu.org/licenses/>. */
/* _GL_ARG_NONNULL((n,...,m)) tells the compiler and static analyzer tools
that the values passed as arguments n, ..., m must be non-NULL pointers.
n = 1 stands for the first argument, n = 2 for the second argument etc. */
#ifndef _GL_ARG_NONNULL
# if (__GNUC__ == 3 && __GNUC_MINOR__ >= 3) || __GNUC__ > 3
# define _GL_ARG_NONNULL(params) __attribute__ ((__nonnull__ params))
# else
# define _GL_ARG_NONNULL(params)
# endif
#endif

275
lib/argmatch.c Normal file
View File

@ -0,0 +1,275 @@
/* argmatch.c -- find a match for a string in an array
Copyright (C) 1990, 1998-1999, 2001-2007, 2009-2018 Free Software
Foundation, Inc.
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 <https://www.gnu.org/licenses/>. */
/* Written by David MacKenzie <djm@ai.mit.edu>
Modified by Akim Demaille <demaille@inf.enst.fr> */
#include <config.h>
/* Specification. */
#include "argmatch.h"
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "gettext.h"
#define _(msgid) gettext (msgid)
#include "error.h"
#include "quotearg.h"
#include "quote.h"
#include "getprogname.h"
#if USE_UNLOCKED_IO
# include "unlocked-io.h"
#endif
/* When reporting an invalid argument, show nonprinting characters
by using the quoting style ARGMATCH_QUOTING_STYLE. Do not use
literal_quoting_style. */
#ifndef ARGMATCH_QUOTING_STYLE
# define ARGMATCH_QUOTING_STYLE locale_quoting_style
#endif
/* Non failing version of argmatch call this function after failing. */
#ifndef ARGMATCH_DIE
# include "exitfail.h"
# define ARGMATCH_DIE exit (exit_failure)
#endif
#ifdef ARGMATCH_DIE_DECL
ARGMATCH_DIE_DECL;
#endif
static void
__argmatch_die (void)
{
ARGMATCH_DIE;
}
/* Used by XARGMATCH and XARGCASEMATCH. See description in argmatch.h.
Default to __argmatch_die, but allow caller to change this at run-time. */
argmatch_exit_fn argmatch_die = __argmatch_die;
/* If ARG is an unambiguous match for an element of the
NULL-terminated array ARGLIST, return the index in ARGLIST
of the matched element, else -1 if it does not match any element
or -2 if it is ambiguous (is a prefix of more than one element).
If VALLIST is none null, use it to resolve ambiguities limited to
synonyms, i.e., for
"yes", "yop" -> 0
"no", "nope" -> 1
"y" is a valid argument, for 0, and "n" for 1. */
ptrdiff_t
argmatch (const char *arg, const char *const *arglist,
const char *vallist, size_t valsize)
{
size_t i; /* Temporary index in ARGLIST. */
size_t arglen; /* Length of ARG. */
ptrdiff_t matchind = -1; /* Index of first nonexact match. */
bool ambiguous = false; /* If true, multiple nonexact match(es). */
arglen = strlen (arg);
/* Test all elements for either exact match or abbreviated matches. */
for (i = 0; arglist[i]; i++)
{
if (!strncmp (arglist[i], arg, arglen))
{
if (strlen (arglist[i]) == arglen)
/* Exact match found. */
return i;
else if (matchind == -1)
/* First nonexact match found. */
matchind = i;
else
{
/* Second nonexact match found. */
if (vallist == NULL
|| memcmp (vallist + valsize * matchind,
vallist + valsize * i, valsize))
{
/* There is a real ambiguity, or we could not
disambiguate. */
ambiguous = true;
}
}
}
}
if (ambiguous)
return -2;
else
return matchind;
}
/* Error reporting for argmatch.
CONTEXT is a description of the type of entity that was being matched.
VALUE is the invalid value that was given.
PROBLEM is the return value from argmatch. */
void
argmatch_invalid (const char *context, const char *value, ptrdiff_t problem)
{
char const *format = (problem == -1
? _("invalid argument %s for %s")
: _("ambiguous argument %s for %s"));
error (0, 0, format, quotearg_n_style (0, ARGMATCH_QUOTING_STYLE, value),
quote_n (1, context));
}
/* List the valid arguments for argmatch.
ARGLIST is the same as in argmatch.
VALLIST is a pointer to an array of values.
VALSIZE is the size of the elements of VALLIST */
void
argmatch_valid (const char *const *arglist,
const char *vallist, size_t valsize)
{
size_t i;
const char *last_val = NULL;
/* We try to put synonyms on the same line. The assumption is that
synonyms follow each other */
fputs (_("Valid arguments are:"), stderr);
for (i = 0; arglist[i]; i++)
if ((i == 0)
|| memcmp (last_val, vallist + valsize * i, valsize))
{
fprintf (stderr, "\n - %s", quote (arglist[i]));
last_val = vallist + valsize * i;
}
else
{
fprintf (stderr, ", %s", quote (arglist[i]));
}
putc ('\n', stderr);
}
/* Never failing versions of the previous functions.
CONTEXT is the context for which argmatch is called (e.g.,
"--version-control", or "$VERSION_CONTROL" etc.). Upon failure,
calls the (supposed never to return) function EXIT_FN. */
ptrdiff_t
__xargmatch_internal (const char *context,
const char *arg, const char *const *arglist,
const char *vallist, size_t valsize,
argmatch_exit_fn exit_fn)
{
ptrdiff_t res = argmatch (arg, arglist, vallist, valsize);
if (res >= 0)
/* Success. */
return res;
/* We failed. Explain why. */
argmatch_invalid (context, arg, res);
argmatch_valid (arglist, vallist, valsize);
(*exit_fn) ();
return -1; /* To please the compilers. */
}
/* Look for VALUE in VALLIST, an array of objects of size VALSIZE and
return the first corresponding argument in ARGLIST */
const char *
argmatch_to_argument (const char *value,
const char *const *arglist,
const char *vallist, size_t valsize)
{
size_t i;
for (i = 0; arglist[i]; i++)
if (!memcmp (value, vallist + valsize * i, valsize))
return arglist[i];
return NULL;
}
#ifdef TEST
/*
* Based on "getversion.c" by David MacKenzie <djm@gnu.ai.mit.edu>
*/
/* When to make backup files. */
enum backup_type
{
/* Never make backups. */
no_backups,
/* Make simple backups of every file. */
simple_backups,
/* Make numbered backups of files that already have numbered backups,
and simple backups of the others. */
numbered_existing_backups,
/* Make numbered backups of every file. */
numbered_backups
};
/* Two tables describing arguments (keys) and their corresponding
values */
static const char *const backup_args[] =
{
"no", "none", "off",
"simple", "never",
"existing", "nil",
"numbered", "t",
0
};
static const enum backup_type backup_vals[] =
{
no_backups, no_backups, no_backups,
simple_backups, simple_backups,
numbered_existing_backups, numbered_existing_backups,
numbered_backups, numbered_backups
};
int
main (int argc, const char *const *argv)
{
const char *cp;
enum backup_type backup_type = no_backups;
if (argc > 2)
{
fprintf (stderr, "Usage: %s [VERSION_CONTROL]\n", getprogname ());
exit (1);
}
if ((cp = getenv ("VERSION_CONTROL")))
backup_type = XARGMATCH ("$VERSION_CONTROL", cp,
backup_args, backup_vals);
if (argc == 2)
backup_type = XARGMATCH (getprogname (), argv[1],
backup_args, backup_vals);
printf ("The version control is '%s'\n",
ARGMATCH_TO_ARGUMENT (backup_type, backup_args, backup_vals));
return 0;
}
#endif

111
lib/argmatch.h Normal file
View File

@ -0,0 +1,111 @@
/* argmatch.h -- definitions and prototypes for argmatch.c
Copyright (C) 1990, 1998-1999, 2001-2002, 2004-2005, 2009-2018 Free Software
Foundation, Inc.
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 <https://www.gnu.org/licenses/>. */
/* Written by David MacKenzie <djm@ai.mit.edu>
Modified by Akim Demaille <demaille@inf.enst.fr> */
#ifndef ARGMATCH_H_
# define ARGMATCH_H_ 1
# include <stddef.h>
# include "verify.h"
#ifdef __cplusplus
extern "C" {
#endif
# define ARRAY_CARDINALITY(Array) (sizeof (Array) / sizeof *(Array))
/* Assert there are as many real arguments as there are values
(argument list ends with a NULL guard). */
# define ARGMATCH_VERIFY(Arglist, Vallist) \
verify (ARRAY_CARDINALITY (Arglist) == ARRAY_CARDINALITY (Vallist) + 1)
/* Return the index of the element of ARGLIST (NULL terminated) that
matches with ARG. If VALLIST is not NULL, then use it to resolve
false ambiguities (i.e., different matches of ARG but corresponding
to the same values in VALLIST). */
ptrdiff_t argmatch (char const *arg, char const *const *arglist,
char const *vallist, size_t valsize) _GL_ATTRIBUTE_PURE;
# define ARGMATCH(Arg, Arglist, Vallist) \
argmatch (Arg, Arglist, (char const *) (Vallist), sizeof *(Vallist))
/* xargmatch calls this function when it fails. This function should not
return. By default, this is a function that calls ARGMATCH_DIE which
in turn defaults to 'exit (exit_failure)'. */
typedef void (*argmatch_exit_fn) (void);
extern argmatch_exit_fn argmatch_die;
/* Report on stderr why argmatch failed. Report correct values. */
void argmatch_invalid (char const *context, char const *value,
ptrdiff_t problem);
/* Left for compatibility with the old name invalid_arg */
# define invalid_arg(Context, Value, Problem) \
argmatch_invalid (Context, Value, Problem)
/* Report on stderr the list of possible arguments. */
void argmatch_valid (char const *const *arglist,
char const *vallist, size_t valsize);
# define ARGMATCH_VALID(Arglist, Vallist) \
argmatch_valid (Arglist, (char const *) (Vallist), sizeof *(Vallist))
/* Same as argmatch, but upon failure, report an explanation of the
failure, and exit using the function EXIT_FN. */
ptrdiff_t __xargmatch_internal (char const *context,
char const *arg, char const *const *arglist,
char const *vallist, size_t valsize,
argmatch_exit_fn exit_fn);
/* Programmer friendly interface to __xargmatch_internal. */
# define XARGMATCH(Context, Arg, Arglist, Vallist) \
((Vallist) [__xargmatch_internal (Context, Arg, Arglist, \
(char const *) (Vallist), \
sizeof *(Vallist), \
argmatch_die)])
/* Convert a value into a corresponding argument. */
char const *argmatch_to_argument (char const *value,
char const *const *arglist,
char const *vallist, size_t valsize)
_GL_ATTRIBUTE_PURE;
# define ARGMATCH_TO_ARGUMENT(Value, Arglist, Vallist) \
argmatch_to_argument (Value, Arglist, \
(char const *) (Vallist), sizeof *(Vallist))
#ifdef __cplusplus
}
#endif
#endif /* ARGMATCH_H_ */

34
lib/asnprintf.c Normal file
View File

@ -0,0 +1,34 @@
/* Formatted output to strings.
Copyright (C) 1999, 2002, 2006, 2009-2018 Free Software Foundation, Inc.
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, 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 <https://www.gnu.org/licenses/>. */
#include <config.h>
/* Specification. */
#include "vasnprintf.h"
#include <stdarg.h>
char *
asnprintf (char *resultbuf, size_t *lengthp, const char *format, ...)
{
va_list args;
char *result;
va_start (args, format);
result = vasnprintf (resultbuf, lengthp, format, args);
va_end (args);
return result;
}

39
lib/asprintf.c Normal file
View File

@ -0,0 +1,39 @@
/* Formatted output to strings.
Copyright (C) 1999, 2002, 2006-2007, 2009-2018 Free Software Foundation,
Inc.
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, 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 <https://www.gnu.org/licenses/>. */
#include <config.h>
/* Specification. */
#ifdef IN_LIBASPRINTF
# include "vasprintf.h"
#else
# include <stdio.h>
#endif
#include <stdarg.h>
int
asprintf (char **resultp, const char *format, ...)
{
va_list args;
int result;
va_start (args, format);
result = vasprintf (resultp, format, args);
va_end (args);
return result;
}

37
lib/assure.h Normal file
View File

@ -0,0 +1,37 @@
/* Run-time assert-like macros.
Copyright (C) 2014-2018 Free Software Foundation, Inc.
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 <https://www.gnu.org/licenses/>. */
/* Written by Paul Eggert. */
#ifndef _GL_ASSURE_H
#define _GL_ASSURE_H
#include <assert.h>
/* Check E's value at runtime, and report an error and abort if not.
However, do nothng if NDEBUG is defined.
Unlike standard 'assert', this macro always compiles E even when NDEBUG
is defined, so as to catch typos and avoid some GCC warnings. */
#ifdef NDEBUG
# define assure(E) ((void) (0 && (E)))
#else
# define assure(E) assert (E)
#endif
#endif

146
lib/at-func.c Normal file
View File

@ -0,0 +1,146 @@
/* Define at-style functions like fstatat, unlinkat, fchownat, etc.
Copyright (C) 2006, 2009-2018 Free Software Foundation, Inc.
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 <https://www.gnu.org/licenses/>. */
/* written by Jim Meyering */
#include "dosname.h" /* solely for definition of IS_ABSOLUTE_FILE_NAME */
#ifdef GNULIB_SUPPORT_ONLY_AT_FDCWD
# include <errno.h>
# ifndef ENOTSUP
# define ENOTSUP EINVAL
# endif
#else
# include "openat.h"
# include "openat-priv.h"
# include "save-cwd.h"
#endif
#ifdef AT_FUNC_USE_F1_COND
# define CALL_FUNC(F) \
(flag == AT_FUNC_USE_F1_COND \
? AT_FUNC_F1 (F AT_FUNC_POST_FILE_ARGS) \
: AT_FUNC_F2 (F AT_FUNC_POST_FILE_ARGS))
# define VALIDATE_FLAG(F) \
if (flag & ~AT_FUNC_USE_F1_COND) \
{ \
errno = EINVAL; \
return FUNC_FAIL; \
}
#else
# define CALL_FUNC(F) (AT_FUNC_F1 (F AT_FUNC_POST_FILE_ARGS))
# define VALIDATE_FLAG(F) /* empty */
#endif
#ifdef AT_FUNC_RESULT
# define FUNC_RESULT AT_FUNC_RESULT
#else
# define FUNC_RESULT int
#endif
#ifdef AT_FUNC_FAIL
# define FUNC_FAIL AT_FUNC_FAIL
#else
# define FUNC_FAIL -1
#endif
/* Call AT_FUNC_F1 to operate on FILE, which is in the directory
open on descriptor FD. If AT_FUNC_USE_F1_COND is defined to a value,
AT_FUNC_POST_FILE_PARAM_DECLS must include a parameter named flag;
call AT_FUNC_F2 if FLAG is 0 or fail if FLAG contains more bits than
AT_FUNC_USE_F1_COND. Return int and fail with -1 unless AT_FUNC_RESULT
or AT_FUNC_FAIL are defined. If possible, do it without changing the
working directory. Otherwise, resort to using save_cwd/fchdir,
then AT_FUNC_F?/restore_cwd. If either the save_cwd or the restore_cwd
fails, then give a diagnostic and exit nonzero. */
FUNC_RESULT
AT_FUNC_NAME (int fd, char const *file AT_FUNC_POST_FILE_PARAM_DECLS)
{
VALIDATE_FLAG (flag);
if (fd == AT_FDCWD || IS_ABSOLUTE_FILE_NAME (file))
return CALL_FUNC (file);
#ifdef GNULIB_SUPPORT_ONLY_AT_FDCWD
errno = ENOTSUP;
return FUNC_FAIL;
#else
{
/* Be careful to choose names unlikely to conflict with
AT_FUNC_POST_FILE_PARAM_DECLS. */
struct saved_cwd saved_cwd;
int saved_errno;
FUNC_RESULT err;
{
char proc_buf[OPENAT_BUFFER_SIZE];
char *proc_file = openat_proc_name (proc_buf, fd, file);
if (proc_file)
{
FUNC_RESULT proc_result = CALL_FUNC (proc_file);
int proc_errno = errno;
if (proc_file != proc_buf)
free (proc_file);
/* If the syscall succeeds, or if it fails with an unexpected
errno value, then return right away. Otherwise, fall through
and resort to using save_cwd/restore_cwd. */
if (FUNC_FAIL != proc_result)
return proc_result;
if (! EXPECTED_ERRNO (proc_errno))
{
errno = proc_errno;
return proc_result;
}
}
}
if (save_cwd (&saved_cwd) != 0)
openat_save_fail (errno);
if (0 <= fd && fd == saved_cwd.desc)
{
/* If saving the working directory collides with the user's
requested fd, then the user's fd must have been closed to
begin with. */
free_cwd (&saved_cwd);
errno = EBADF;
return FUNC_FAIL;
}
if (fchdir (fd) != 0)
{
saved_errno = errno;
free_cwd (&saved_cwd);
errno = saved_errno;
return FUNC_FAIL;
}
err = CALL_FUNC (file);
saved_errno = (err == FUNC_FAIL ? errno : 0);
if (restore_cwd (&saved_cwd) != 0)
openat_restore_fail (errno);
free_cwd (&saved_cwd);
if (saved_errno)
errno = saved_errno;
return err;
}
#endif
}
#undef CALL_FUNC
#undef FUNC_RESULT
#undef FUNC_FAIL

282
lib/at-func2.c Normal file
View File

@ -0,0 +1,282 @@
/* Define 2-FD at-style functions like linkat or renameat.
Copyright (C) 2006, 2009-2018 Free Software Foundation, Inc.
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 <https://www.gnu.org/licenses/>. */
/* written by Jim Meyering and Eric Blake */
#include <config.h>
#include "openat-priv.h"
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "dosname.h" /* solely for definition of IS_ABSOLUTE_FILE_NAME */
#include "filenamecat.h"
#include "openat.h"
#include "same-inode.h"
#include "save-cwd.h"
/* Call FUNC to operate on a pair of files, where FILE1 is relative to FD1,
and FILE2 is relative to FD2. If possible, do it without changing the
working directory. Otherwise, resort to using save_cwd/fchdir,
FUNC, restore_cwd (up to two times). If either the save_cwd or the
restore_cwd fails, then give a diagnostic and exit nonzero. */
int
at_func2 (int fd1, char const *file1,
int fd2, char const *file2,
int (*func) (char const *file1, char const *file2))
{
struct saved_cwd saved_cwd;
int saved_errno;
int err;
char *file1_alt;
char *file2_alt;
struct stat st1;
struct stat st2;
/* There are 16 possible scenarios, based on whether an fd is
AT_FDCWD or real, and whether a file is absolute or relative:
fd1 file1 fd2 file2 action
0 cwd abs cwd abs direct call
1 cwd abs cwd rel direct call
2 cwd abs fd abs direct call
3 cwd abs fd rel chdir to fd2
4 cwd rel cwd abs direct call
5 cwd rel cwd rel direct call
6 cwd rel fd abs direct call
7 cwd rel fd rel convert file1 to abs, then case 3
8 fd abs cwd abs direct call
9 fd abs cwd rel direct call
10 fd abs fd abs direct call
11 fd abs fd rel chdir to fd2
12 fd rel cwd abs chdir to fd1
13 fd rel cwd rel convert file2 to abs, then case 12
14 fd rel fd abs chdir to fd1
15a fd1 rel fd1 rel chdir to fd1
15b fd1 rel fd2 rel chdir to fd1, then case 7
Try some optimizations to reduce fd to AT_FDCWD, or to at least
avoid converting an absolute name or doing a double chdir. */
if ((fd1 == AT_FDCWD || IS_ABSOLUTE_FILE_NAME (file1))
&& (fd2 == AT_FDCWD || IS_ABSOLUTE_FILE_NAME (file2)))
return func (file1, file2); /* Case 0-2, 4-6, 8-10. */
/* If /proc/self/fd works, we don't need any stat or chdir. */
{
char proc_buf1[OPENAT_BUFFER_SIZE];
char *proc_file1 = ((fd1 == AT_FDCWD || IS_ABSOLUTE_FILE_NAME (file1))
? (char *) file1
: openat_proc_name (proc_buf1, fd1, file1));
if (proc_file1)
{
char proc_buf2[OPENAT_BUFFER_SIZE];
char *proc_file2 = ((fd2 == AT_FDCWD || IS_ABSOLUTE_FILE_NAME (file2))
? (char *) file2
: openat_proc_name (proc_buf2, fd2, file2));
if (proc_file2)
{
int proc_result = func (proc_file1, proc_file2);
int proc_errno = errno;
if (proc_file1 != proc_buf1 && proc_file1 != file1)
free (proc_file1);
if (proc_file2 != proc_buf2 && proc_file2 != file2)
free (proc_file2);
/* If the syscall succeeds, or if it fails with an unexpected
errno value, then return right away. Otherwise, fall through
and resort to using save_cwd/restore_cwd. */
if (0 <= proc_result)
return proc_result;
if (! EXPECTED_ERRNO (proc_errno))
{
errno = proc_errno;
return proc_result;
}
}
else if (proc_file1 != proc_buf1 && proc_file1 != file1)
free (proc_file1);
}
}
/* Cases 3, 7, 11-15 remain. Time to normalize directory fds, if
possible. */
if (IS_ABSOLUTE_FILE_NAME (file1))
fd1 = AT_FDCWD; /* Case 11 reduced to 3. */
else if (IS_ABSOLUTE_FILE_NAME (file2))
fd2 = AT_FDCWD; /* Case 14 reduced to 12. */
/* Cases 3, 7, 12, 13, 15 remain. */
if (fd1 == AT_FDCWD) /* Cases 3, 7. */
{
if (stat (".", &st1) == -1 || fstat (fd2, &st2) == -1)
return -1;
if (!S_ISDIR (st2.st_mode))
{
errno = ENOTDIR;
return -1;
}
if (SAME_INODE (st1, st2)) /* Reduced to cases 1, 5. */
return func (file1, file2);
}
else if (fd2 == AT_FDCWD) /* Cases 12, 13. */
{
if (stat (".", &st2) == -1 || fstat (fd1, &st1) == -1)
return -1;
if (!S_ISDIR (st1.st_mode))
{
errno = ENOTDIR;
return -1;
}
if (SAME_INODE (st1, st2)) /* Reduced to cases 4, 5. */
return func (file1, file2);
}
else if (fd1 != fd2) /* Case 15b. */
{
if (fstat (fd1, &st1) == -1 || fstat (fd2, &st2) == -1)
return -1;
if (!S_ISDIR (st1.st_mode) || !S_ISDIR (st2.st_mode))
{
errno = ENOTDIR;
return -1;
}
if (SAME_INODE (st1, st2)) /* Reduced to case 15a. */
{
fd2 = fd1;
if (stat (".", &st1) == 0 && SAME_INODE (st1, st2))
return func (file1, file2); /* Further reduced to case 5. */
}
}
else /* Case 15a. */
{
if (fstat (fd1, &st1) == -1)
return -1;
if (!S_ISDIR (st1.st_mode))
{
errno = ENOTDIR;
return -1;
}
if (stat (".", &st2) == 0 && SAME_INODE (st1, st2))
return func (file1, file2); /* Reduced to case 5. */
}
/* Cases 3, 7, 12, 13, 15a, 15b remain. With all reductions in
place, it is time to start changing directories. */
if (save_cwd (&saved_cwd) != 0)
openat_save_fail (errno);
if (fd1 != AT_FDCWD && fd2 != AT_FDCWD && fd1 != fd2) /* Case 15b. */
{
if (fchdir (fd1) != 0)
{
saved_errno = errno;
free_cwd (&saved_cwd);
errno = saved_errno;
return -1;
}
fd1 = AT_FDCWD; /* Reduced to case 7. */
}
/* Cases 3, 7, 12, 13, 15a remain. Convert one relative name to
absolute, if necessary. */
file1_alt = (char *) file1;
file2_alt = (char *) file2;
if (fd1 == AT_FDCWD && !IS_ABSOLUTE_FILE_NAME (file1)) /* Case 7. */
{
/* It would be nicer to use:
file1_alt = file_name_concat (xgetcwd (), file1, NULL);
but libraries should not call xalloc_die. */
char *cwd = getcwd (NULL, 0);
if (!cwd)
{
saved_errno = errno;
free_cwd (&saved_cwd);
errno = saved_errno;
return -1;
}
file1_alt = mfile_name_concat (cwd, file1, NULL);
if (!file1_alt)
{
saved_errno = errno;
free (cwd);
free_cwd (&saved_cwd);
errno = saved_errno;
return -1;
}
free (cwd); /* Reduced to case 3. */
}
else if (fd2 == AT_FDCWD && !IS_ABSOLUTE_FILE_NAME (file2)) /* Case 13. */
{
char *cwd = getcwd (NULL, 0);
if (!cwd)
{
saved_errno = errno;
free_cwd (&saved_cwd);
errno = saved_errno;
return -1;
}
file2_alt = mfile_name_concat (cwd, file2, NULL);
if (!file2_alt)
{
saved_errno = errno;
free (cwd);
free_cwd (&saved_cwd);
errno = saved_errno;
return -1;
}
free (cwd); /* Reduced to case 12. */
}
/* Cases 3, 12, 15a remain. Change to the correct directory. */
if (fchdir (fd1 == AT_FDCWD ? fd2 : fd1) != 0)
{
saved_errno = errno;
free_cwd (&saved_cwd);
if (file1 != file1_alt)
free (file1_alt);
else if (file2 != file2_alt)
free (file2_alt);
errno = saved_errno;
return -1;
}
/* Finally safe to perform the user's function, then clean up. */
err = func (file1_alt, file2_alt);
saved_errno = (err < 0 ? errno : 0);
if (file1 != file1_alt)
free (file1_alt);
else if (file2 != file2_alt)
free (file2_alt);
if (restore_cwd (&saved_cwd) != 0)
openat_restore_fail (errno);
free_cwd (&saved_cwd);
if (saved_errno)
errno = saved_errno;
return err;
}
#undef CALL_FUNC
#undef FUNC_RESULT

91
lib/backup-find.c Normal file
View File

@ -0,0 +1,91 @@
/* backupfile.c -- make Emacs style backup file names
Copyright 2017-2018 Free Software Foundation, Inc.
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 <https://www.gnu.org/licenses/>. */
#include <config.h>
#include "backup-internal.h"
#include "argmatch.h"
#include "xalloc.h"
#include <stdlib.h>
/* Return the name of a backup file for the existing file FILE,
allocated with malloc. Report an error and exit if out of memory.
Do not call this function if backup_type == no_backups. */
char *
find_backup_file_name (char const *file, enum backup_type backup_type)
{
char *result = backupfile_internal (file, backup_type, false);
if (!result)
xalloc_die ();
return result;
}
static char const *const backup_args[] =
{
/* In a series of synonyms, present the most meaningful first, so
that argmatch_valid be more readable. */
"none", "off",
"simple", "never",
"existing", "nil",
"numbered", "t",
NULL
};
static const enum backup_type backup_types[] =
{
no_backups, no_backups,
simple_backups, simple_backups,
numbered_existing_backups, numbered_existing_backups,
numbered_backups, numbered_backups
};
/* Ensure that these two vectors have the same number of elements,
not counting the final NULL in the first one. */
ARGMATCH_VERIFY (backup_args, backup_types);
/* Return the type of backup specified by VERSION.
If VERSION is NULL or the empty string, return numbered_existing_backups.
If VERSION is invalid or ambiguous, fail with a diagnostic appropriate
for the specified CONTEXT. Unambiguous abbreviations are accepted. */
enum backup_type
get_version (char const *context, char const *version)
{
if (version == 0 || *version == 0)
return numbered_existing_backups;
else
return XARGMATCH (context, version, backup_args, backup_types);
}
/* Return the type of backup specified by VERSION.
If VERSION is NULL, use the value of the envvar VERSION_CONTROL.
If the specified string is invalid or ambiguous, fail with a diagnostic
appropriate for the specified CONTEXT.
Unambiguous abbreviations are accepted. */
enum backup_type
xget_version (char const *context, char const *version)
{
if (version && *version)
return get_version (context, version);
else
return get_version ("$VERSION_CONTROL", getenv ("VERSION_CONTROL"));
}

3
lib/backup-internal.h Normal file
View File

@ -0,0 +1,3 @@
#include "backupfile.h"
#include <stdbool.h>
extern char *backupfile_internal (char const *, enum backup_type, bool);

372
lib/backupfile.c Normal file
View File

@ -0,0 +1,372 @@
/* backupfile.c -- make Emacs style backup file names
Copyright (C) 1990-2006, 2009-2018 Free Software Foundation, Inc.
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 <https://www.gnu.org/licenses/>. */
/* Written by Paul Eggert and David MacKenzie.
Some algorithms adapted from GNU Emacs. */
#include <config.h>
#include "backup-internal.h"
#include "dirname.h"
#include "renameat2.h"
#include "xalloc-oversized.h"
#include <fcntl.h>
#include <errno.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <unistd.h>
#include "dirent--.h"
#ifndef _D_EXACT_NAMLEN
# define _D_EXACT_NAMLEN(dp) strlen ((dp)->d_name)
#endif
#if ! (HAVE_PATHCONF && defined _PC_NAME_MAX)
# define pathconf(file, option) (errno = -1)
#endif
#ifndef _POSIX_NAME_MAX
# define _POSIX_NAME_MAX 14
#endif
#ifndef SIZE_MAX
# define SIZE_MAX ((size_t) -1)
#endif
#if defined _XOPEN_NAME_MAX
# define NAME_MAX_MINIMUM _XOPEN_NAME_MAX
#else
# define NAME_MAX_MINIMUM _POSIX_NAME_MAX
#endif
#ifndef HAVE_DOS_FILE_NAMES
# define HAVE_DOS_FILE_NAMES 0
#endif
#ifndef HAVE_LONG_FILE_NAMES
# define HAVE_LONG_FILE_NAMES 0
#endif
/* ISDIGIT differs from isdigit, as follows:
- Its arg may be any int or unsigned int; it need not be an unsigned char
or EOF.
- It's typically faster.
POSIX says that only '0' through '9' are digits. Prefer ISDIGIT to
ISDIGIT unless it's important to use the locale's definition
of "digit" even when the host does not conform to POSIX. */
#define ISDIGIT(c) ((unsigned int) (c) - '0' <= 9)
/* The extension added to file names to produce a simple (as opposed
to numbered) backup file name. */
char const *simple_backup_suffix = NULL;
/* Set SIMPLE_BACKUP_SUFFIX to S, or to a default specified by the
environment if S is null. If S or the environment does not specify
a valid backup suffix, use "~". */
void
set_simple_backup_suffix (char const *s)
{
if (!s)
s = getenv ("SIMPLE_BACKUP_SUFFIX");
simple_backup_suffix = s && *s && s == last_component (s) ? s : "~";
}
/* If FILE (which was of length FILELEN before an extension was
appended to it) is too long, replace the extension with the single
char E. If the result is still too long, remove the char just
before E. */
static void
check_extension (char *file, size_t filelen, char e)
{
char *base = last_component (file);
size_t baselen = base_len (base);
size_t baselen_max = HAVE_LONG_FILE_NAMES ? 255 : NAME_MAX_MINIMUM;
if (HAVE_DOS_FILE_NAMES || NAME_MAX_MINIMUM < baselen)
{
/* The new base name is long enough to require a pathconf check. */
long name_max;
/* Temporarily modify the buffer into its parent directory name,
invoke pathconf on the directory, and then restore the buffer. */
char tmp[sizeof "."];
memcpy (tmp, base, sizeof ".");
strcpy (base, ".");
errno = 0;
name_max = pathconf (file, _PC_NAME_MAX);
if (0 <= name_max || errno == 0)
{
long size = baselen_max = name_max;
if (name_max != size)
baselen_max = SIZE_MAX;
}
memcpy (base, tmp, sizeof ".");
}
if (HAVE_DOS_FILE_NAMES && baselen_max <= 12)
{
/* Live within DOS's 8.3 limit. */
char *dot = strchr (base, '.');
if (!dot)
baselen_max = 8;
else
{
char const *second_dot = strchr (dot + 1, '.');
baselen_max = (second_dot
? second_dot - base
: dot + 1 - base + 3);
}
}
if (baselen_max < baselen)
{
baselen = file + filelen - base;
if (baselen_max <= baselen)
baselen = baselen_max - 1;
base[baselen] = e;
base[baselen + 1] = '\0';
}
}
/* Returned values for NUMBERED_BACKUP. */
enum numbered_backup_result
{
/* The new backup name is the same length as an existing backup
name, so it's valid for that directory. */
BACKUP_IS_SAME_LENGTH,
/* Some backup names already exist, but the returned name is longer
than any of them, and its length should be checked. */
BACKUP_IS_LONGER,
/* There are no existing backup names. The new name's length
should be checked. */
BACKUP_IS_NEW,
/* Memory allocation failure. */
BACKUP_NOMEM
};
/* *BUFFER contains a file name. Store into *BUFFER the next backup
name for the named file, with a version number greater than all the
existing numbered backups. Reallocate *BUFFER as necessary; its
initial allocated size is BUFFER_SIZE, which must be at least 4
bytes longer than the file name to make room for the initially
appended ".~1". FILELEN is the length of the original file name.
BASE_OFFSET is the offset of the basename in *BUFFER.
The returned value indicates what kind of backup was found. If an
I/O or other read error occurs, use the highest backup number that
was found.
*DIRPP is the destination directory. If *DIRPP is null, open the
destination directory and store the resulting stream into *DIRPP
without closing the stream. */
static enum numbered_backup_result
numbered_backup (char **buffer, size_t buffer_size, size_t filelen,
ptrdiff_t base_offset, DIR **dirpp)
{
enum numbered_backup_result result = BACKUP_IS_NEW;
DIR *dirp = *dirpp;
struct dirent *dp;
char *buf = *buffer;
size_t versionlenmax = 1;
char *base = buf + base_offset;
size_t baselen = base_len (base);
if (dirp)
rewinddir (dirp);
else
{
/* Temporarily modify the buffer into its parent directory name,
open the directory, and then restore the buffer. */
char tmp[sizeof "."];
memcpy (tmp, base, sizeof ".");
strcpy (base, ".");
dirp = opendir (buf);
if (!dirp && errno == ENOMEM)
result = BACKUP_NOMEM;
memcpy (base, tmp, sizeof ".");
strcpy (base + baselen, ".~1~");
if (!dirp)
return result;
*dirpp = dirp;
}
while ((dp = readdir (dirp)) != NULL)
{
char const *p;
char *q;
bool all_9s;
size_t versionlen;
if (_D_EXACT_NAMLEN (dp) < baselen + 4)
continue;
if (memcmp (buf + base_offset, dp->d_name, baselen + 2) != 0)
continue;
p = dp->d_name + baselen + 2;
/* Check whether this file has a version number and if so,
whether it is larger. Use string operations rather than
integer arithmetic, to avoid problems with integer overflow. */
if (! ('1' <= *p && *p <= '9'))
continue;
all_9s = (*p == '9');
for (versionlen = 1; ISDIGIT (p[versionlen]); versionlen++)
all_9s &= (p[versionlen] == '9');
if (! (p[versionlen] == '~' && !p[versionlen + 1]
&& (versionlenmax < versionlen
|| (versionlenmax == versionlen
&& memcmp (buf + filelen + 2, p, versionlen) <= 0))))
continue;
/* This entry has the largest version number seen so far.
Append this highest numbered extension to the file name,
prepending '0' to the number if it is all 9s. */
versionlenmax = all_9s + versionlen;
result = (all_9s ? BACKUP_IS_LONGER : BACKUP_IS_SAME_LENGTH);
size_t new_buffer_size = filelen + 2 + versionlenmax + 2;
if (buffer_size < new_buffer_size)
{
if (! xalloc_oversized (new_buffer_size, 2))
new_buffer_size *= 2;
char *new_buf = realloc (buf, new_buffer_size);
if (!new_buf)
{
*buffer = buf;
return BACKUP_NOMEM;
}
buf = new_buf;
buffer_size = new_buffer_size;
}
q = buf + filelen;
*q++ = '.';
*q++ = '~';
*q = '0';
q += all_9s;
memcpy (q, p, versionlen + 2);
/* Add 1 to the version number. */
q += versionlen;
while (*--q == '9')
*q = '0';
++*q;
}
*buffer = buf;
return result;
}
/* Return the name of the new backup file for the existing file FILE,
allocated with malloc. If RENAME, also rename FILE to the new name.
On failure, return NULL and set errno.
Do not call this function if backup_type == no_backups. */
char *
backupfile_internal (char const *file, enum backup_type backup_type, bool rename)
{
ptrdiff_t base_offset = last_component (file) - file;
size_t filelen = base_offset + strlen (file + base_offset);
if (! simple_backup_suffix)
set_simple_backup_suffix (NULL);
/* Allow room for simple or ".~N~" backups. The guess must be at
least sizeof ".~1~", but otherwise will be adjusted as needed. */
size_t simple_backup_suffix_size = strlen (simple_backup_suffix) + 1;
size_t backup_suffix_size_guess = simple_backup_suffix_size;
enum { GUESS = sizeof ".~12345~" };
if (backup_suffix_size_guess < GUESS)
backup_suffix_size_guess = GUESS;
ssize_t ssize = filelen + backup_suffix_size_guess + 1;
char *s = malloc (ssize);
if (!s)
return s;
DIR *dirp = NULL;
while (true)
{
memcpy (s, file, filelen + 1);
if (backup_type == simple_backups)
memcpy (s + filelen, simple_backup_suffix, simple_backup_suffix_size);
else
switch (numbered_backup (&s, ssize, filelen, base_offset, &dirp))
{
case BACKUP_IS_SAME_LENGTH:
break;
case BACKUP_IS_NEW:
if (backup_type == numbered_existing_backups)
{
backup_type = simple_backups;
memcpy (s + filelen, simple_backup_suffix,
simple_backup_suffix_size);
}
check_extension (s, filelen, '~');
break;
case BACKUP_IS_LONGER:
check_extension (s, filelen, '~');
break;
case BACKUP_NOMEM:
free (s);
errno = ENOMEM;
return NULL;
}
if (! rename)
break;
int sdir = dirp ? dirfd (dirp) : -1;
if (sdir < 0)
{
sdir = AT_FDCWD;
base_offset = 0;
}
unsigned flags = backup_type == simple_backups ? 0 : RENAME_NOREPLACE;
if (renameat2 (AT_FDCWD, file, sdir, s + base_offset, flags) == 0)
break;
int e = errno;
if (e != EEXIST)
{
if (dirp)
closedir (dirp);
free (s);
errno = e;
return NULL;
}
}
if (dirp)
closedir (dirp);
return s;
}

61
lib/backupfile.h Normal file
View File

@ -0,0 +1,61 @@
/* backupfile.h -- declarations for making Emacs style backup file names
Copyright (C) 1990-1992, 1997-1999, 2003-2004, 2009-2018 Free Software
Foundation, Inc.
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 <https://www.gnu.org/licenses/>. */
#ifndef BACKUPFILE_H_
# define BACKUPFILE_H_
# ifdef __cplusplus
extern "C" {
# endif
/* When to make backup files. */
enum backup_type
{
/* Never make backups. */
no_backups,
/* Make simple backups of every file. */
simple_backups,
/* Make numbered backups of files that already have numbered backups,
and simple backups of the others. */
numbered_existing_backups,
/* Make numbered backups of every file. */
numbered_backups
};
# define VALID_BACKUP_TYPE(Type) \
((unsigned int) (Type) <= numbered_backups)
extern char const *simple_backup_suffix;
void set_simple_backup_suffix (char const *);
char *backup_file_rename (char const *, enum backup_type);
char *find_backup_file_name (char const *, enum backup_type);
enum backup_type get_version (char const *context, char const *arg);
enum backup_type xget_version (char const *context, char const *arg);
void addext (char *, char const *, int);
# ifdef __cplusplus
}
# endif
#endif /* ! BACKUPFILE_H_ */

75
lib/basename-lgpl.c Normal file
View File

@ -0,0 +1,75 @@
/* basename.c -- return the last element in a file name
Copyright (C) 1990, 1998-2001, 2003-2006, 2009-2018 Free Software
Foundation, Inc.
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 <https://www.gnu.org/licenses/>. */
#include <config.h>
#include "dirname.h"
#include <string.h>
/* Return the address of the last file name component of NAME. If
NAME has no relative file name components because it is a file
system root, return the empty string. */
char *
last_component (char const *name)
{
char const *base = name + FILE_SYSTEM_PREFIX_LEN (name);
char const *p;
bool saw_slash = false;
while (ISSLASH (*base))
base++;
for (p = base; *p; p++)
{
if (ISSLASH (*p))
saw_slash = true;
else if (saw_slash)
{
base = p;
saw_slash = false;
}
}
return (char *) base;
}
/* Return the length of the basename NAME. Typically NAME is the
value returned by base_name or last_component. Act like strlen
(NAME), except omit all trailing slashes. */
size_t
base_len (char const *name)
{
size_t len;
size_t prefix_len = FILE_SYSTEM_PREFIX_LEN (name);
for (len = strlen (name); 1 < len && ISSLASH (name[len - 1]); len--)
continue;
if (DOUBLE_SLASH_IS_DISTINCT_ROOT && len == 1
&& ISSLASH (name[0]) && ISSLASH (name[1]) && ! name[2])
return 2;
if (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE && prefix_len
&& len == prefix_len && ISSLASH (name[prefix_len]))
return prefix_len + 1;
return len;
}

58
lib/basename.c Normal file
View File

@ -0,0 +1,58 @@
/* basename.c -- return the last element in a file name
Copyright (C) 1990, 1998-2001, 2003-2006, 2009-2018 Free Software
Foundation, Inc.
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 <https://www.gnu.org/licenses/>. */
#include <config.h>
#include "dirname.h"
#include <string.h>
#include "xalloc.h"
#include "xstrndup.h"
char *
base_name (char const *name)
{
char const *base = last_component (name);
size_t length;
/* If there is no last component, then name is a file system root or the
empty string. */
if (! *base)
return xstrndup (name, base_len (name));
/* Collapse a sequence of trailing slashes into one. */
length = base_len (base);
if (ISSLASH (base[length]))
length++;
/* On systems with drive letters, "a/b:c" must return "./b:c" rather
than "b:c" to avoid confusion with a drive letter. On systems
with pure POSIX semantics, this is not an issue. */
if (FILE_SYSTEM_PREFIX_LEN (base))
{
char *p = xmalloc (length + 3);
p[0] = '.';
p[1] = '/';
memcpy (p + 2, base, length);
p[length + 2] = '\0';
return p;
}
/* Finally, copy the basename. */
return xstrndup (base, length);
}

3
lib/bitrotate.c Normal file
View File

@ -0,0 +1,3 @@
#include <config.h>
#define BITROTATE_INLINE _GL_EXTERN_INLINE
#include "bitrotate.h"

136
lib/bitrotate.h Normal file
View File

@ -0,0 +1,136 @@
/* bitrotate.h - Rotate bits in integers
Copyright (C) 2008-2018 Free Software Foundation, Inc.
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 <https://www.gnu.org/licenses/>. */
/* Written by Simon Josefsson <simon@josefsson.org>, 2008. */
#ifndef _GL_BITROTATE_H
#define _GL_BITROTATE_H
#include <limits.h>
#include <stdint.h>
#include <sys/types.h>
#ifndef _GL_INLINE_HEADER_BEGIN
#error "Please include config.h first."
#endif
_GL_INLINE_HEADER_BEGIN
#ifndef BITROTATE_INLINE
# define BITROTATE_INLINE _GL_INLINE
#endif
#ifdef UINT64_MAX
/* Given an unsigned 64-bit argument X, return the value corresponding
to rotating the bits N steps to the left. N must be between 1 and
63 inclusive. */
BITROTATE_INLINE uint64_t
rotl64 (uint64_t x, int n)
{
return ((x << n) | (x >> (64 - n))) & UINT64_MAX;
}
/* Given an unsigned 64-bit argument X, return the value corresponding
to rotating the bits N steps to the right. N must be between 1 to
63 inclusive.*/
BITROTATE_INLINE uint64_t
rotr64 (uint64_t x, int n)
{
return ((x >> n) | (x << (64 - n))) & UINT64_MAX;
}
#endif
/* Given an unsigned 32-bit argument X, return the value corresponding
to rotating the bits N steps to the left. N must be between 1 and
31 inclusive. */
BITROTATE_INLINE uint32_t
rotl32 (uint32_t x, int n)
{
return ((x << n) | (x >> (32 - n))) & UINT32_MAX;
}
/* Given an unsigned 32-bit argument X, return the value corresponding
to rotating the bits N steps to the right. N must be between 1 to
31 inclusive.*/
BITROTATE_INLINE uint32_t
rotr32 (uint32_t x, int n)
{
return ((x >> n) | (x << (32 - n))) & UINT32_MAX;
}
/* Given a size_t argument X, return the value corresponding
to rotating the bits N steps to the left. N must be between 1 and
(CHAR_BIT * sizeof (size_t) - 1) inclusive. */
BITROTATE_INLINE size_t
rotl_sz (size_t x, int n)
{
return ((x << n) | (x >> ((CHAR_BIT * sizeof x) - n))) & SIZE_MAX;
}
/* Given a size_t argument X, return the value corresponding
to rotating the bits N steps to the right. N must be between 1 to
(CHAR_BIT * sizeof (size_t) - 1) inclusive. */
BITROTATE_INLINE size_t
rotr_sz (size_t x, int n)
{
return ((x >> n) | (x << ((CHAR_BIT * sizeof x) - n))) & SIZE_MAX;
}
/* Given an unsigned 16-bit argument X, return the value corresponding
to rotating the bits N steps to the left. N must be between 1 to
15 inclusive, but on most relevant targets N can also be 0 and 16
because 'int' is at least 32 bits and the arguments must widen
before shifting. */
BITROTATE_INLINE uint16_t
rotl16 (uint16_t x, int n)
{
return ((x << n) | (x >> (16 - n))) & UINT16_MAX;
}
/* Given an unsigned 16-bit argument X, return the value corresponding
to rotating the bits N steps to the right. N must be in 1 to 15
inclusive, but on most relevant targets N can also be 0 and 16
because 'int' is at least 32 bits and the arguments must widen
before shifting. */
BITROTATE_INLINE uint16_t
rotr16 (uint16_t x, int n)
{
return ((x >> n) | (x << (16 - n))) & UINT16_MAX;
}
/* Given an unsigned 8-bit argument X, return the value corresponding
to rotating the bits N steps to the left. N must be between 1 to 7
inclusive, but on most relevant targets N can also be 0 and 8
because 'int' is at least 32 bits and the arguments must widen
before shifting. */
BITROTATE_INLINE uint8_t
rotl8 (uint8_t x, int n)
{
return ((x << n) | (x >> (8 - n))) & UINT8_MAX;
}
/* Given an unsigned 8-bit argument X, return the value corresponding
to rotating the bits N steps to the right. N must be in 1 to 7
inclusive, but on most relevant targets N can also be 0 and 8
because 'int' is at least 32 bits and the arguments must widen
before shifting. */
BITROTATE_INLINE uint8_t
rotr8 (uint8_t x, int n)
{
return ((x >> n) | (x << (8 - n))) & UINT8_MAX;
}
_GL_INLINE_HEADER_END
#endif /* _GL_BITROTATE_H */

316
lib/c++defs.h Normal file
View File

@ -0,0 +1,316 @@
/* C++ compatible function declaration macros.
Copyright (C) 2010-2018 Free Software Foundation, Inc.
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 <https://www.gnu.org/licenses/>. */
#ifndef _GL_CXXDEFS_H
#define _GL_CXXDEFS_H
/* Begin/end the GNULIB_NAMESPACE namespace. */
#if defined __cplusplus && defined GNULIB_NAMESPACE
# define _GL_BEGIN_NAMESPACE namespace GNULIB_NAMESPACE {
# define _GL_END_NAMESPACE }
#else
# define _GL_BEGIN_NAMESPACE
# define _GL_END_NAMESPACE
#endif
/* The three most frequent use cases of these macros are:
* For providing a substitute for a function that is missing on some
platforms, but is declared and works fine on the platforms on which
it exists:
#if @GNULIB_FOO@
# if !@HAVE_FOO@
_GL_FUNCDECL_SYS (foo, ...);
# endif
_GL_CXXALIAS_SYS (foo, ...);
_GL_CXXALIASWARN (foo);
#elif defined GNULIB_POSIXCHECK
...
#endif
* For providing a replacement for a function that exists on all platforms,
but is broken/insufficient and needs to be replaced on some platforms:
#if @GNULIB_FOO@
# if @REPLACE_FOO@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# undef foo
# define foo rpl_foo
# endif
_GL_FUNCDECL_RPL (foo, ...);
_GL_CXXALIAS_RPL (foo, ...);
# else
_GL_CXXALIAS_SYS (foo, ...);
# endif
_GL_CXXALIASWARN (foo);
#elif defined GNULIB_POSIXCHECK
...
#endif
* For providing a replacement for a function that exists on some platforms
but is broken/insufficient and needs to be replaced on some of them and
is additionally either missing or undeclared on some other platforms:
#if @GNULIB_FOO@
# if @REPLACE_FOO@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# undef foo
# define foo rpl_foo
# endif
_GL_FUNCDECL_RPL (foo, ...);
_GL_CXXALIAS_RPL (foo, ...);
# else
# if !@HAVE_FOO@ or if !@HAVE_DECL_FOO@
_GL_FUNCDECL_SYS (foo, ...);
# endif
_GL_CXXALIAS_SYS (foo, ...);
# endif
_GL_CXXALIASWARN (foo);
#elif defined GNULIB_POSIXCHECK
...
#endif
*/
/* _GL_EXTERN_C declaration;
performs the declaration with C linkage. */
#if defined __cplusplus
# define _GL_EXTERN_C extern "C"
#else
# define _GL_EXTERN_C extern
#endif
/* _GL_FUNCDECL_RPL (func, rettype, parameters_and_attributes);
declares a replacement function, named rpl_func, with the given prototype,
consisting of return type, parameters, and attributes.
Example:
_GL_FUNCDECL_RPL (open, int, (const char *filename, int flags, ...)
_GL_ARG_NONNULL ((1)));
*/
#define _GL_FUNCDECL_RPL(func,rettype,parameters_and_attributes) \
_GL_FUNCDECL_RPL_1 (rpl_##func, rettype, parameters_and_attributes)
#define _GL_FUNCDECL_RPL_1(rpl_func,rettype,parameters_and_attributes) \
_GL_EXTERN_C rettype rpl_func parameters_and_attributes
/* _GL_FUNCDECL_SYS (func, rettype, parameters_and_attributes);
declares the system function, named func, with the given prototype,
consisting of return type, parameters, and attributes.
Example:
_GL_FUNCDECL_SYS (open, int, (const char *filename, int flags, ...)
_GL_ARG_NONNULL ((1)));
*/
#define _GL_FUNCDECL_SYS(func,rettype,parameters_and_attributes) \
_GL_EXTERN_C rettype func parameters_and_attributes
/* _GL_CXXALIAS_RPL (func, rettype, parameters);
declares a C++ alias called GNULIB_NAMESPACE::func
that redirects to rpl_func, if GNULIB_NAMESPACE is defined.
Example:
_GL_CXXALIAS_RPL (open, int, (const char *filename, int flags, ...));
Wrapping rpl_func in an object with an inline conversion operator
avoids a reference to rpl_func unless GNULIB_NAMESPACE::func is
actually used in the program. */
#define _GL_CXXALIAS_RPL(func,rettype,parameters) \
_GL_CXXALIAS_RPL_1 (func, rpl_##func, rettype, parameters)
#if defined __cplusplus && defined GNULIB_NAMESPACE
# define _GL_CXXALIAS_RPL_1(func,rpl_func,rettype,parameters) \
namespace GNULIB_NAMESPACE \
{ \
static const struct _gl_ ## func ## _wrapper \
{ \
typedef rettype (*type) parameters; \
\
inline operator type () const \
{ \
return ::rpl_func; \
} \
} func = {}; \
} \
_GL_EXTERN_C int _gl_cxxalias_dummy
#else
# define _GL_CXXALIAS_RPL_1(func,rpl_func,rettype,parameters) \
_GL_EXTERN_C int _gl_cxxalias_dummy
#endif
/* _GL_CXXALIAS_RPL_CAST_1 (func, rpl_func, rettype, parameters);
is like _GL_CXXALIAS_RPL_1 (func, rpl_func, rettype, parameters);
except that the C function rpl_func may have a slightly different
declaration. A cast is used to silence the "invalid conversion" error
that would otherwise occur. */
#if defined __cplusplus && defined GNULIB_NAMESPACE
# define _GL_CXXALIAS_RPL_CAST_1(func,rpl_func,rettype,parameters) \
namespace GNULIB_NAMESPACE \
{ \
static const struct _gl_ ## func ## _wrapper \
{ \
typedef rettype (*type) parameters; \
\
inline operator type () const \
{ \
return reinterpret_cast<type>(::rpl_func); \
} \
} func = {}; \
} \
_GL_EXTERN_C int _gl_cxxalias_dummy
#else
# define _GL_CXXALIAS_RPL_CAST_1(func,rpl_func,rettype,parameters) \
_GL_EXTERN_C int _gl_cxxalias_dummy
#endif
/* _GL_CXXALIAS_SYS (func, rettype, parameters);
declares a C++ alias called GNULIB_NAMESPACE::func
that redirects to the system provided function func, if GNULIB_NAMESPACE
is defined.
Example:
_GL_CXXALIAS_SYS (open, int, (const char *filename, int flags, ...));
Wrapping func in an object with an inline conversion operator
avoids a reference to func unless GNULIB_NAMESPACE::func is
actually used in the program. */
#if defined __cplusplus && defined GNULIB_NAMESPACE
# define _GL_CXXALIAS_SYS(func,rettype,parameters) \
namespace GNULIB_NAMESPACE \
{ \
static const struct _gl_ ## func ## _wrapper \
{ \
typedef rettype (*type) parameters; \
\
inline operator type () const \
{ \
return ::func; \
} \
} func = {}; \
} \
_GL_EXTERN_C int _gl_cxxalias_dummy
#else
# define _GL_CXXALIAS_SYS(func,rettype,parameters) \
_GL_EXTERN_C int _gl_cxxalias_dummy
#endif
/* _GL_CXXALIAS_SYS_CAST (func, rettype, parameters);
is like _GL_CXXALIAS_SYS (func, rettype, parameters);
except that the C function func may have a slightly different declaration.
A cast is used to silence the "invalid conversion" error that would
otherwise occur. */
#if defined __cplusplus && defined GNULIB_NAMESPACE
# define _GL_CXXALIAS_SYS_CAST(func,rettype,parameters) \
namespace GNULIB_NAMESPACE \
{ \
static const struct _gl_ ## func ## _wrapper \
{ \
typedef rettype (*type) parameters; \
\
inline operator type () const \
{ \
return reinterpret_cast<type>(::func); \
} \
} func = {}; \
} \
_GL_EXTERN_C int _gl_cxxalias_dummy
#else
# define _GL_CXXALIAS_SYS_CAST(func,rettype,parameters) \
_GL_EXTERN_C int _gl_cxxalias_dummy
#endif
/* _GL_CXXALIAS_SYS_CAST2 (func, rettype, parameters, rettype2, parameters2);
is like _GL_CXXALIAS_SYS (func, rettype, parameters);
except that the C function is picked among a set of overloaded functions,
namely the one with rettype2 and parameters2. Two consecutive casts
are used to silence the "cannot find a match" and "invalid conversion"
errors that would otherwise occur. */
#if defined __cplusplus && defined GNULIB_NAMESPACE
/* The outer cast must be a reinterpret_cast.
The inner cast: When the function is defined as a set of overloaded
functions, it works as a static_cast<>, choosing the designated variant.
When the function is defined as a single variant, it works as a
reinterpret_cast<>. The parenthesized cast syntax works both ways. */
# define _GL_CXXALIAS_SYS_CAST2(func,rettype,parameters,rettype2,parameters2) \
namespace GNULIB_NAMESPACE \
{ \
static const struct _gl_ ## func ## _wrapper \
{ \
typedef rettype (*type) parameters; \
\
inline operator type () const \
{ \
return reinterpret_cast<type>((rettype2 (*) parameters2)(::func)); \
} \
} func = {}; \
} \
_GL_EXTERN_C int _gl_cxxalias_dummy
#else
# define _GL_CXXALIAS_SYS_CAST2(func,rettype,parameters,rettype2,parameters2) \
_GL_EXTERN_C int _gl_cxxalias_dummy
#endif
/* _GL_CXXALIASWARN (func);
causes a warning to be emitted when ::func is used but not when
GNULIB_NAMESPACE::func is used. func must be defined without overloaded
variants. */
#if defined __cplusplus && defined GNULIB_NAMESPACE
# define _GL_CXXALIASWARN(func) \
_GL_CXXALIASWARN_1 (func, GNULIB_NAMESPACE)
# define _GL_CXXALIASWARN_1(func,namespace) \
_GL_CXXALIASWARN_2 (func, namespace)
/* To work around GCC bug <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=43881>,
we enable the warning only when not optimizing. */
# if !__OPTIMIZE__
# define _GL_CXXALIASWARN_2(func,namespace) \
_GL_WARN_ON_USE (func, \
"The symbol ::" #func " refers to the system function. " \
"Use " #namespace "::" #func " instead.")
# elif __GNUC__ >= 3 && GNULIB_STRICT_CHECKING
# define _GL_CXXALIASWARN_2(func,namespace) \
extern __typeof__ (func) func
# else
# define _GL_CXXALIASWARN_2(func,namespace) \
_GL_EXTERN_C int _gl_cxxalias_dummy
# endif
#else
# define _GL_CXXALIASWARN(func) \
_GL_EXTERN_C int _gl_cxxalias_dummy
#endif
/* _GL_CXXALIASWARN1 (func, rettype, parameters_and_attributes);
causes a warning to be emitted when the given overloaded variant of ::func
is used but not when GNULIB_NAMESPACE::func is used. */
#if defined __cplusplus && defined GNULIB_NAMESPACE
# define _GL_CXXALIASWARN1(func,rettype,parameters_and_attributes) \
_GL_CXXALIASWARN1_1 (func, rettype, parameters_and_attributes, \
GNULIB_NAMESPACE)
# define _GL_CXXALIASWARN1_1(func,rettype,parameters_and_attributes,namespace) \
_GL_CXXALIASWARN1_2 (func, rettype, parameters_and_attributes, namespace)
/* To work around GCC bug <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=43881>,
we enable the warning only when not optimizing. */
# if !__OPTIMIZE__
# define _GL_CXXALIASWARN1_2(func,rettype,parameters_and_attributes,namespace) \
_GL_WARN_ON_USE_CXX (func, rettype, parameters_and_attributes, \
"The symbol ::" #func " refers to the system function. " \
"Use " #namespace "::" #func " instead.")
# elif __GNUC__ >= 3 && GNULIB_STRICT_CHECKING
# define _GL_CXXALIASWARN1_2(func,rettype,parameters_and_attributes,namespace) \
extern __typeof__ (func) func
# else
# define _GL_CXXALIASWARN1_2(func,rettype,parameters_and_attributes,namespace) \
_GL_EXTERN_C int _gl_cxxalias_dummy
# endif
#else
# define _GL_CXXALIASWARN1(func,rettype,parameters_and_attributes) \
_GL_EXTERN_C int _gl_cxxalias_dummy
#endif
#endif /* _GL_CXXDEFS_H */

3
lib/c-ctype.c Normal file
View File

@ -0,0 +1,3 @@
#include <config.h>
#define C_CTYPE_INLINE _GL_EXTERN_INLINE
#include "c-ctype.h"

366
lib/c-ctype.h Normal file
View File

@ -0,0 +1,366 @@
/* Character handling in C locale.
These functions work like the corresponding functions in <ctype.h>,
except that they have the C (POSIX) locale hardwired, whereas the
<ctype.h> functions' behaviour depends on the current locale set via
setlocale.
Copyright (C) 2000-2003, 2006, 2008-2018 Free Software Foundation, Inc.
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 <https://www.gnu.org/licenses/>. */
#ifndef C_CTYPE_H
#define C_CTYPE_H
#include <stdbool.h>
#ifndef _GL_INLINE_HEADER_BEGIN
#error "Please include config.h first."
#endif
_GL_INLINE_HEADER_BEGIN
#ifndef C_CTYPE_INLINE
# define C_CTYPE_INLINE _GL_INLINE
#endif
#ifdef __cplusplus
extern "C" {
#endif
/* The functions defined in this file assume the "C" locale and a character
set without diacritics (ASCII-US or EBCDIC-US or something like that).
Even if the "C" locale on a particular system is an extension of the ASCII
character set (like on BeOS, where it is UTF-8, or on AmigaOS, where it
is ISO-8859-1), the functions in this file recognize only the ASCII
characters. */
#if (' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
&& ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
&& (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \
&& ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \
&& ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \
&& ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \
&& ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \
&& ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \
&& ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \
&& ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \
&& ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \
&& ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \
&& ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \
&& ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \
&& ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \
&& ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \
&& ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \
&& ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \
&& ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \
&& ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \
&& ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \
&& ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
&& ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126)
/* The character set is ASCII or one of its variants or extensions, not EBCDIC.
Testing the value of '\n' and '\r' is not relevant. */
# define C_CTYPE_ASCII 1
#elif ! (' ' == '\x40' && '0' == '\xf0' \
&& 'A' == '\xc1' && 'J' == '\xd1' && 'S' == '\xe2' \
&& 'a' == '\x81' && 'j' == '\x91' && 's' == '\xa2')
# error "Only ASCII and EBCDIC are supported"
#endif
#if 'A' < 0
# error "EBCDIC and char is signed -- not supported"
#endif
/* Cases for control characters. */
#define _C_CTYPE_CNTRL \
case '\a': case '\b': case '\f': case '\n': \
case '\r': case '\t': case '\v': \
_C_CTYPE_OTHER_CNTRL
/* ASCII control characters other than those with \-letter escapes. */
#if C_CTYPE_ASCII
# define _C_CTYPE_OTHER_CNTRL \
case '\x00': case '\x01': case '\x02': case '\x03': \
case '\x04': case '\x05': case '\x06': case '\x0e': \
case '\x0f': case '\x10': case '\x11': case '\x12': \
case '\x13': case '\x14': case '\x15': case '\x16': \
case '\x17': case '\x18': case '\x19': case '\x1a': \
case '\x1b': case '\x1c': case '\x1d': case '\x1e': \
case '\x1f': case '\x7f'
#else
/* Use EBCDIC code page 1047's assignments for ASCII control chars;
assume all EBCDIC code pages agree about these assignments. */
# define _C_CTYPE_OTHER_CNTRL \
case '\x00': case '\x01': case '\x02': case '\x03': \
case '\x07': case '\x0e': case '\x0f': case '\x10': \
case '\x11': case '\x12': case '\x13': case '\x18': \
case '\x19': case '\x1c': case '\x1d': case '\x1e': \
case '\x1f': case '\x26': case '\x27': case '\x2d': \
case '\x2e': case '\x32': case '\x37': case '\x3c': \
case '\x3d': case '\x3f'
#endif
/* Cases for lowercase hex letters, and lowercase letters, all offset by N. */
#define _C_CTYPE_LOWER_A_THRU_F_N(N) \
case 'a' + (N): case 'b' + (N): case 'c' + (N): case 'd' + (N): \
case 'e' + (N): case 'f' + (N)
#define _C_CTYPE_LOWER_N(N) \
_C_CTYPE_LOWER_A_THRU_F_N(N): \
case 'g' + (N): case 'h' + (N): case 'i' + (N): case 'j' + (N): \
case 'k' + (N): case 'l' + (N): case 'm' + (N): case 'n' + (N): \
case 'o' + (N): case 'p' + (N): case 'q' + (N): case 'r' + (N): \
case 's' + (N): case 't' + (N): case 'u' + (N): case 'v' + (N): \
case 'w' + (N): case 'x' + (N): case 'y' + (N): case 'z' + (N)
/* Cases for hex letters, digits, lower, punct, and upper. */
#define _C_CTYPE_A_THRU_F \
_C_CTYPE_LOWER_A_THRU_F_N (0): \
_C_CTYPE_LOWER_A_THRU_F_N ('A' - 'a')
#define _C_CTYPE_DIGIT \
case '0': case '1': case '2': case '3': \
case '4': case '5': case '6': case '7': \
case '8': case '9'
#define _C_CTYPE_LOWER _C_CTYPE_LOWER_N (0)
#define _C_CTYPE_PUNCT \
case '!': case '"': case '#': case '$': \
case '%': case '&': case '\'': case '(': \
case ')': case '*': case '+': case ',': \
case '-': case '.': case '/': case ':': \
case ';': case '<': case '=': case '>': \
case '?': case '@': case '[': case '\\': \
case ']': case '^': case '_': case '`': \
case '{': case '|': case '}': case '~'
#define _C_CTYPE_UPPER _C_CTYPE_LOWER_N ('A' - 'a')
/* Function definitions. */
/* Unlike the functions in <ctype.h>, which require an argument in the range
of the 'unsigned char' type, the functions here operate on values that are
in the 'unsigned char' range or in the 'char' range. In other words,
when you have a 'char' value, you need to cast it before using it as
argument to a <ctype.h> function:
const char *s = ...;
if (isalpha ((unsigned char) *s)) ...
but you don't need to cast it for the functions defined in this file:
const char *s = ...;
if (c_isalpha (*s)) ...
*/
C_CTYPE_INLINE bool
c_isalnum (int c)
{
switch (c)
{
_C_CTYPE_DIGIT:
_C_CTYPE_LOWER:
_C_CTYPE_UPPER:
return true;
default:
return false;
}
}
C_CTYPE_INLINE bool
c_isalpha (int c)
{
switch (c)
{
_C_CTYPE_LOWER:
_C_CTYPE_UPPER:
return true;
default:
return false;
}
}
/* The function isascii is not locale dependent.
Its use in EBCDIC is questionable. */
C_CTYPE_INLINE bool
c_isascii (int c)
{
switch (c)
{
case ' ':
_C_CTYPE_CNTRL:
_C_CTYPE_DIGIT:
_C_CTYPE_LOWER:
_C_CTYPE_PUNCT:
_C_CTYPE_UPPER:
return true;
default:
return false;
}
}
C_CTYPE_INLINE bool
c_isblank (int c)
{
return c == ' ' || c == '\t';
}
C_CTYPE_INLINE bool
c_iscntrl (int c)
{
switch (c)
{
_C_CTYPE_CNTRL:
return true;
default:
return false;
}
}
C_CTYPE_INLINE bool
c_isdigit (int c)
{
switch (c)
{
_C_CTYPE_DIGIT:
return true;
default:
return false;
}
}
C_CTYPE_INLINE bool
c_isgraph (int c)
{
switch (c)
{
_C_CTYPE_DIGIT:
_C_CTYPE_LOWER:
_C_CTYPE_PUNCT:
_C_CTYPE_UPPER:
return true;
default:
return false;
}
}
C_CTYPE_INLINE bool
c_islower (int c)
{
switch (c)
{
_C_CTYPE_LOWER:
return true;
default:
return false;
}
}
C_CTYPE_INLINE bool
c_isprint (int c)
{
switch (c)
{
case ' ':
_C_CTYPE_DIGIT:
_C_CTYPE_LOWER:
_C_CTYPE_PUNCT:
_C_CTYPE_UPPER:
return true;
default:
return false;
}
}
C_CTYPE_INLINE bool
c_ispunct (int c)
{
switch (c)
{
_C_CTYPE_PUNCT:
return true;
default:
return false;
}
}
C_CTYPE_INLINE bool
c_isspace (int c)
{
switch (c)
{
case ' ': case '\t': case '\n': case '\v': case '\f': case '\r':
return true;
default:
return false;
}
}
C_CTYPE_INLINE bool
c_isupper (int c)
{
switch (c)
{
_C_CTYPE_UPPER:
return true;
default:
return false;
}
}
C_CTYPE_INLINE bool
c_isxdigit (int c)
{
switch (c)
{
_C_CTYPE_DIGIT:
_C_CTYPE_A_THRU_F:
return true;
default:
return false;
}
}
C_CTYPE_INLINE int
c_tolower (int c)
{
switch (c)
{
_C_CTYPE_UPPER:
return c - 'A' + 'a';
default:
return c;
}
}
C_CTYPE_INLINE int
c_toupper (int c)
{
switch (c)
{
_C_CTYPE_LOWER:
return c - 'a' + 'A';
default:
return c;
}
}
#ifdef __cplusplus
}
#endif
_GL_INLINE_HEADER_END
#endif /* C_CTYPE_H */

56
lib/c-strcase.h Normal file
View File

@ -0,0 +1,56 @@
/* Case-insensitive string comparison functions in C locale.
Copyright (C) 1995-1996, 2001, 2003, 2005, 2009-2018 Free Software
Foundation, Inc.
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, 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 <https://www.gnu.org/licenses/>. */
#ifndef C_STRCASE_H
#define C_STRCASE_H
#include <stddef.h>
/* The functions defined in this file assume the "C" locale and a character
set without diacritics (ASCII-US or EBCDIC-US or something like that).
Even if the "C" locale on a particular system is an extension of the ASCII
character set (like on BeOS, where it is UTF-8, or on AmigaOS, where it
is ISO-8859-1), the functions in this file recognize only the ASCII
characters. More precisely, one of the string arguments must be an ASCII
string; the other one can also contain non-ASCII characters (but then
the comparison result will be nonzero). */
#ifdef __cplusplus
extern "C" {
#endif
/* Compare strings S1 and S2, ignoring case, returning less than, equal to or
greater than zero if S1 is lexicographically less than, equal to or greater
than S2. */
extern int c_strcasecmp (const char *s1, const char *s2) _GL_ATTRIBUTE_PURE;
/* Compare no more than N characters of strings S1 and S2, ignoring case,
returning less than, equal to or greater than zero if S1 is
lexicographically less than, equal to or greater than S2. */
extern int c_strncasecmp (const char *s1, const char *s2, size_t n)
_GL_ATTRIBUTE_PURE;
#ifdef __cplusplus
}
#endif
#endif /* C_STRCASE_H */

56
lib/c-strcasecmp.c Normal file
View File

@ -0,0 +1,56 @@
/* c-strcasecmp.c -- case insensitive string comparator in C locale
Copyright (C) 1998-1999, 2005-2006, 2009-2018 Free Software Foundation, Inc.
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, 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 <https://www.gnu.org/licenses/>. */
#include <config.h>
/* Specification. */
#include "c-strcase.h"
#include <limits.h>
#include "c-ctype.h"
int
c_strcasecmp (const char *s1, const char *s2)
{
register const unsigned char *p1 = (const unsigned char *) s1;
register const unsigned char *p2 = (const unsigned char *) s2;
unsigned char c1, c2;
if (p1 == p2)
return 0;
do
{
c1 = c_tolower (*p1);
c2 = c_tolower (*p2);
if (c1 == '\0')
break;
++p1;
++p2;
}
while (c1 == c2);
if (UCHAR_MAX <= INT_MAX)
return c1 - c2;
else
/* On machines where 'char' and 'int' are types of the same size, the
difference of two 'unsigned char' values - including the sign bit -
doesn't fit in an 'int'. */
return (c1 > c2 ? 1 : c1 < c2 ? -1 : 0);
}

181
lib/c-strcaseeq.h Normal file
View File

@ -0,0 +1,181 @@
/* Optimized case-insensitive string comparison in C locale.
Copyright (C) 2001-2002, 2007, 2009-2018 Free Software Foundation, Inc.
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 <https://www.gnu.org/licenses/>. */
/* Written by Bruno Haible <bruno@clisp.org>. */
#include "c-strcase.h"
#include "c-ctype.h"
/* STRCASEEQ allows to optimize string comparison with a small literal string.
STRCASEEQ (s, "UTF-8", 'U','T','F','-','8',0,0,0,0)
is semantically equivalent to
c_strcasecmp (s, "UTF-8") == 0
just faster. */
/* Help GCC to generate good code for string comparisons with
immediate strings. */
#if defined (__GNUC__) && defined (__OPTIMIZE__)
/* Case insensitive comparison of ASCII characters. */
# if C_CTYPE_ASCII
# define CASEEQ(other,upper) \
(c_isupper (upper) ? ((other) & ~0x20) == (upper) : (other) == (upper))
# else
# define CASEEQ(other,upper) \
(c_toupper (other) == (upper))
# endif
static inline int
strcaseeq9 (const char *s1, const char *s2)
{
return c_strcasecmp (s1 + 9, s2 + 9) == 0;
}
static inline int
strcaseeq8 (const char *s1, const char *s2, char s28)
{
if (CASEEQ (s1[8], s28))
{
if (s28 == 0)
return 1;
else
return strcaseeq9 (s1, s2);
}
else
return 0;
}
static inline int
strcaseeq7 (const char *s1, const char *s2, char s27, char s28)
{
if (CASEEQ (s1[7], s27))
{
if (s27 == 0)
return 1;
else
return strcaseeq8 (s1, s2, s28);
}
else
return 0;
}
static inline int
strcaseeq6 (const char *s1, const char *s2, char s26, char s27, char s28)
{
if (CASEEQ (s1[6], s26))
{
if (s26 == 0)
return 1;
else
return strcaseeq7 (s1, s2, s27, s28);
}
else
return 0;
}
static inline int
strcaseeq5 (const char *s1, const char *s2, char s25, char s26, char s27, char s28)
{
if (CASEEQ (s1[5], s25))
{
if (s25 == 0)
return 1;
else
return strcaseeq6 (s1, s2, s26, s27, s28);
}
else
return 0;
}
static inline int
strcaseeq4 (const char *s1, const char *s2, char s24, char s25, char s26, char s27, char s28)
{
if (CASEEQ (s1[4], s24))
{
if (s24 == 0)
return 1;
else
return strcaseeq5 (s1, s2, s25, s26, s27, s28);
}
else
return 0;
}
static inline int
strcaseeq3 (const char *s1, const char *s2, char s23, char s24, char s25, char s26, char s27, char s28)
{
if (CASEEQ (s1[3], s23))
{
if (s23 == 0)
return 1;
else
return strcaseeq4 (s1, s2, s24, s25, s26, s27, s28);
}
else
return 0;
}
static inline int
strcaseeq2 (const char *s1, const char *s2, char s22, char s23, char s24, char s25, char s26, char s27, char s28)
{
if (CASEEQ (s1[2], s22))
{
if (s22 == 0)
return 1;
else
return strcaseeq3 (s1, s2, s23, s24, s25, s26, s27, s28);
}
else
return 0;
}
static inline int
strcaseeq1 (const char *s1, const char *s2, char s21, char s22, char s23, char s24, char s25, char s26, char s27, char s28)
{
if (CASEEQ (s1[1], s21))
{
if (s21 == 0)
return 1;
else
return strcaseeq2 (s1, s2, s22, s23, s24, s25, s26, s27, s28);
}
else
return 0;
}
static inline int
strcaseeq0 (const char *s1, const char *s2, char s20, char s21, char s22, char s23, char s24, char s25, char s26, char s27, char s28)
{
if (CASEEQ (s1[0], s20))
{
if (s20 == 0)
return 1;
else
return strcaseeq1 (s1, s2, s21, s22, s23, s24, s25, s26, s27, s28);
}
else
return 0;
}
#define STRCASEEQ(s1,s2,s20,s21,s22,s23,s24,s25,s26,s27,s28) \
strcaseeq0 (s1, s2, s20, s21, s22, s23, s24, s25, s26, s27, s28)
#else
#define STRCASEEQ(s1,s2,s20,s21,s22,s23,s24,s25,s26,s27,s28) \
(c_strcasecmp (s1, s2) == 0)
#endif

56
lib/c-strncasecmp.c Normal file
View File

@ -0,0 +1,56 @@
/* c-strncasecmp.c -- case insensitive string comparator in C locale
Copyright (C) 1998-1999, 2005-2006, 2009-2018 Free Software Foundation, Inc.
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, 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 <https://www.gnu.org/licenses/>. */
#include <config.h>
/* Specification. */
#include "c-strcase.h"
#include <limits.h>
#include "c-ctype.h"
int
c_strncasecmp (const char *s1, const char *s2, size_t n)
{
register const unsigned char *p1 = (const unsigned char *) s1;
register const unsigned char *p2 = (const unsigned char *) s2;
unsigned char c1, c2;
if (p1 == p2 || n == 0)
return 0;
do
{
c1 = c_tolower (*p1);
c2 = c_tolower (*p2);
if (--n == 0 || c1 == '\0')
break;
++p1;
++p2;
}
while (c1 == c2);
if (UCHAR_MAX <= INT_MAX)
return c1 - c2;
else
/* On machines where 'char' and 'int' are types of the same size, the
difference of two 'unsigned char' values - including the sign bit -
doesn't fit in an 'int'. */
return (c1 > c2 ? 1 : c1 < c2 ? -1 : 0);
}

428
lib/canonicalize-lgpl.c Normal file
View File

@ -0,0 +1,428 @@
/* Return the canonical absolute name of a given file.
Copyright (C) 1996-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
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 <https://www.gnu.org/licenses/>. */
#ifndef _LIBC
/* Don't use __attribute__ __nonnull__ in this compilation unit. Otherwise gcc
optimizes away the name == NULL test below. */
# define _GL_ARG_NONNULL(params)
# define _GL_USE_STDLIB_ALLOC 1
# include <config.h>
#endif
#if !HAVE_CANONICALIZE_FILE_NAME || !FUNC_REALPATH_WORKS || defined _LIBC
/* Specification. */
#include <stdlib.h>
#include <alloca.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>
#if HAVE_SYS_PARAM_H || defined _LIBC
# include <sys/param.h>
#endif
#include <sys/stat.h>
#include <errno.h>
#include <stddef.h>
#ifdef _LIBC
# include <shlib-compat.h>
#else
# define SHLIB_COMPAT(lib, introduced, obsoleted) 0
# define versioned_symbol(lib, local, symbol, version) extern int dummy
# define compat_symbol(lib, local, symbol, version)
# define weak_alias(local, symbol)
# define __canonicalize_file_name canonicalize_file_name
# define __realpath realpath
# include "pathmax.h"
# include "malloca.h"
# include "dosname.h"
# if HAVE_GETCWD
# if IN_RELOCWRAPPER
/* When building the relocatable program wrapper, use the system's getcwd
function, not the gnulib override, otherwise we would get a link error.
*/
# undef getcwd
# endif
# if defined VMS && !defined getcwd
/* We want the directory in Unix syntax, not in VMS syntax.
The gnulib override of 'getcwd' takes 2 arguments; the original VMS
'getcwd' takes 3 arguments. */
# define __getcwd(buf, max) getcwd (buf, max, 0)
# else
# define __getcwd getcwd
# endif
# else
# define __getcwd(buf, max) getwd (buf)
# endif
# define __readlink readlink
# define __set_errno(e) errno = (e)
# ifndef MAXSYMLINKS
# ifdef SYMLOOP_MAX
# define MAXSYMLINKS SYMLOOP_MAX
# else
# define MAXSYMLINKS 20
# endif
# endif
#endif
#ifndef DOUBLE_SLASH_IS_DISTINCT_ROOT
# define DOUBLE_SLASH_IS_DISTINCT_ROOT 0
#endif
/* Define this independently so that stdint.h is not a prerequisite. */
#ifndef SIZE_MAX
# define SIZE_MAX ((size_t) -1)
#endif
#if !FUNC_REALPATH_WORKS || defined _LIBC
static void
alloc_failed (void)
{
#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
/* Avoid errno problem without using the malloc or realloc modules; see:
https://lists.gnu.org/r/bug-gnulib/2016-08/msg00025.html */
errno = ENOMEM;
#endif
}
/* Return the canonical absolute name of file NAME. A canonical name
does not contain any ".", ".." components nor any repeated path
separators ('/') or symlinks. All path components must exist. If
RESOLVED is null, the result is malloc'd; otherwise, if the
canonical name is PATH_MAX chars or more, returns null with 'errno'
set to ENAMETOOLONG; if the name fits in fewer than PATH_MAX chars,
returns the name in RESOLVED. If the name cannot be resolved and
RESOLVED is non-NULL, it contains the path of the first component
that cannot be resolved. If the path can be resolved, RESOLVED
holds the same value as the value returned. */
char *
__realpath (const char *name, char *resolved)
{
char *rpath, *dest, *extra_buf = NULL;
const char *start, *end, *rpath_limit;
long int path_max;
int num_links = 0;
size_t prefix_len;
if (name == NULL)
{
/* As per Single Unix Specification V2 we must return an error if
either parameter is a null pointer. We extend this to allow
the RESOLVED parameter to be NULL in case the we are expected to
allocate the room for the return value. */
__set_errno (EINVAL);
return NULL;
}
if (name[0] == '\0')
{
/* As per Single Unix Specification V2 we must return an error if
the name argument points to an empty string. */
__set_errno (ENOENT);
return NULL;
}
#ifdef PATH_MAX
path_max = PATH_MAX;
#else
path_max = pathconf (name, _PC_PATH_MAX);
if (path_max <= 0)
path_max = 8192;
#endif
if (resolved == NULL)
{
rpath = malloc (path_max);
if (rpath == NULL)
{
alloc_failed ();
return NULL;
}
}
else
rpath = resolved;
rpath_limit = rpath + path_max;
/* This is always zero for Posix hosts, but can be 2 for MS-Windows
and MS-DOS X:/foo/bar file names. */
prefix_len = FILE_SYSTEM_PREFIX_LEN (name);
if (!IS_ABSOLUTE_FILE_NAME (name))
{
if (!__getcwd (rpath, path_max))
{
rpath[0] = '\0';
goto error;
}
dest = strchr (rpath, '\0');
start = name;
prefix_len = FILE_SYSTEM_PREFIX_LEN (rpath);
}
else
{
dest = rpath;
if (prefix_len)
{
memcpy (rpath, name, prefix_len);
dest += prefix_len;
}
*dest++ = '/';
if (DOUBLE_SLASH_IS_DISTINCT_ROOT)
{
if (ISSLASH (name[1]) && !ISSLASH (name[2]) && !prefix_len)
*dest++ = '/';
*dest = '\0';
}
start = name + prefix_len;
}
for (end = start; *start; start = end)
{
#ifdef _LIBC
struct stat64 st;
#else
struct stat st;
#endif
/* Skip sequence of multiple path-separators. */
while (ISSLASH (*start))
++start;
/* Find end of path component. */
for (end = start; *end && !ISSLASH (*end); ++end)
/* Nothing. */;
if (end - start == 0)
break;
else if (end - start == 1 && start[0] == '.')
/* nothing */;
else if (end - start == 2 && start[0] == '.' && start[1] == '.')
{
/* Back up to previous component, ignore if at root already. */
if (dest > rpath + prefix_len + 1)
for (--dest; dest > rpath && !ISSLASH (dest[-1]); --dest)
continue;
if (DOUBLE_SLASH_IS_DISTINCT_ROOT
&& dest == rpath + 1 && !prefix_len
&& ISSLASH (*dest) && !ISSLASH (dest[1]))
dest++;
}
else
{
size_t new_size;
if (!ISSLASH (dest[-1]))
*dest++ = '/';
if (dest + (end - start) >= rpath_limit)
{
ptrdiff_t dest_offset = dest - rpath;
char *new_rpath;
if (resolved)
{
__set_errno (ENAMETOOLONG);
if (dest > rpath + prefix_len + 1)
dest--;
*dest = '\0';
goto error;
}
new_size = rpath_limit - rpath;
if (end - start + 1 > path_max)
new_size += end - start + 1;
else
new_size += path_max;
new_rpath = (char *) realloc (rpath, new_size);
if (new_rpath == NULL)
{
alloc_failed ();
goto error;
}
rpath = new_rpath;
rpath_limit = rpath + new_size;
dest = rpath + dest_offset;
}
#ifdef _LIBC
dest = __mempcpy (dest, start, end - start);
#else
memcpy (dest, start, end - start);
dest += end - start;
#endif
*dest = '\0';
/* FIXME: if lstat fails with errno == EOVERFLOW,
the entry exists. */
#ifdef _LIBC
if (__lxstat64 (_STAT_VER, rpath, &st) < 0)
#else
if (lstat (rpath, &st) < 0)
#endif
goto error;
if (S_ISLNK (st.st_mode))
{
char *buf;
size_t len;
ssize_t n;
if (++num_links > MAXSYMLINKS)
{
__set_errno (ELOOP);
goto error;
}
buf = malloca (path_max);
if (!buf)
{
__set_errno (ENOMEM);
goto error;
}
n = __readlink (rpath, buf, path_max - 1);
if (n < 0)
{
int saved_errno = errno;
freea (buf);
__set_errno (saved_errno);
goto error;
}
buf[n] = '\0';
if (!extra_buf)
{
extra_buf = malloca (path_max);
if (!extra_buf)
{
freea (buf);
__set_errno (ENOMEM);
goto error;
}
}
len = strlen (end);
/* Check that n + len + 1 doesn't overflow and is <= path_max. */
if (n >= SIZE_MAX - len || n + len >= path_max)
{
freea (buf);
__set_errno (ENAMETOOLONG);
goto error;
}
/* Careful here, end may be a pointer into extra_buf... */
memmove (&extra_buf[n], end, len + 1);
name = end = memcpy (extra_buf, buf, n);
if (IS_ABSOLUTE_FILE_NAME (buf))
{
size_t pfxlen = FILE_SYSTEM_PREFIX_LEN (buf);
if (pfxlen)
memcpy (rpath, buf, pfxlen);
dest = rpath + pfxlen;
*dest++ = '/'; /* It's an absolute symlink */
if (DOUBLE_SLASH_IS_DISTINCT_ROOT)
{
if (ISSLASH (buf[1]) && !ISSLASH (buf[2]) && !pfxlen)
*dest++ = '/';
*dest = '\0';
}
/* Install the new prefix to be in effect hereafter. */
prefix_len = pfxlen;
}
else
{
/* Back up to previous component, ignore if at root
already: */
if (dest > rpath + prefix_len + 1)
for (--dest; dest > rpath && !ISSLASH (dest[-1]); --dest)
continue;
if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rpath + 1
&& ISSLASH (*dest) && !ISSLASH (dest[1]) && !prefix_len)
dest++;
}
}
else if (!S_ISDIR (st.st_mode) && *end != '\0')
{
__set_errno (ENOTDIR);
goto error;
}
}
}
if (dest > rpath + prefix_len + 1 && ISSLASH (dest[-1]))
--dest;
if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rpath + 1 && !prefix_len
&& ISSLASH (*dest) && !ISSLASH (dest[1]))
dest++;
*dest = '\0';
if (extra_buf)
freea (extra_buf);
return rpath;
error:
{
int saved_errno = errno;
if (extra_buf)
freea (extra_buf);
if (resolved == NULL)
free (rpath);
__set_errno (saved_errno);
}
return NULL;
}
versioned_symbol (libc, __realpath, realpath, GLIBC_2_3);
#endif /* !FUNC_REALPATH_WORKS || defined _LIBC */
#if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_3)
char *
attribute_compat_text_section
__old_realpath (const char *name, char *resolved)
{
if (resolved == NULL)
{
__set_errno (EINVAL);
return NULL;
}
return __realpath (name, resolved);
}
compat_symbol (libc, __old_realpath, realpath, GLIBC_2_0);
#endif
char *
__canonicalize_file_name (const char *name)
{
return __realpath (name, NULL);
}
weak_alias (__canonicalize_file_name, canonicalize_file_name)
#else
/* This declaration is solely to ensure that after preprocessing
this file is never empty. */
typedef int dummy;
#endif

264
lib/chdir-long.c Normal file
View File

@ -0,0 +1,264 @@
/* provide a chdir function that tries not to fail due to ENAMETOOLONG
Copyright (C) 2004-2018 Free Software Foundation, Inc.
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 <https://www.gnu.org/licenses/>. */
/* written by Jim Meyering */
#include <config.h>
#include "chdir-long.h"
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <stdio.h>
#include "assure.h"
#ifndef PATH_MAX
# error "compile this file only if your system defines PATH_MAX"
#endif
/* The results of openat() in this file are not leaked to any
single-threaded code that could use stdio.
FIXME - if the kernel ever adds support for multi-thread safety for
avoiding standard fds, then we should use openat_safer. */
struct cd_buf
{
int fd;
};
static void
cdb_init (struct cd_buf *cdb)
{
cdb->fd = AT_FDCWD;
}
static int
cdb_fchdir (struct cd_buf const *cdb)
{
return fchdir (cdb->fd);
}
static void
cdb_free (struct cd_buf const *cdb)
{
if (0 <= cdb->fd)
{
bool close_fail = close (cdb->fd);
assure (! close_fail);
}
}
/* Given a file descriptor of an open directory (or AT_FDCWD), CDB->fd,
try to open the CDB->fd-relative directory, DIR. If the open succeeds,
update CDB->fd with the resulting descriptor, close the incoming file
descriptor, and return zero. Upon failure, return -1 and set errno. */
static int
cdb_advance_fd (struct cd_buf *cdb, char const *dir)
{
int new_fd = openat (cdb->fd, dir,
O_SEARCH | O_DIRECTORY | O_NOCTTY | O_NONBLOCK);
if (new_fd < 0)
return -1;
cdb_free (cdb);
cdb->fd = new_fd;
return 0;
}
/* Return a pointer to the first non-slash in S. */
static char * _GL_ATTRIBUTE_PURE
find_non_slash (char const *s)
{
size_t n_slash = strspn (s, "/");
return (char *) s + n_slash;
}
/* This is a function much like chdir, but without the PATH_MAX limitation
on the length of the directory name. A significant difference is that
it must be able to modify (albeit only temporarily) the directory
name. It handles an arbitrarily long directory name by operating
on manageable portions of the name. On systems without the openat
syscall, this means changing the working directory to more and more
"distant" points along the long directory name and then restoring
the working directory. If any of those attempts to save or restore
the working directory fails, this function exits nonzero.
Note that this function may still fail with errno == ENAMETOOLONG, but
only if the specified directory name contains a component that is long
enough to provoke such a failure all by itself (e.g. if the component
has length PATH_MAX or greater on systems that define PATH_MAX). */
int
chdir_long (char *dir)
{
int e = chdir (dir);
if (e == 0 || errno != ENAMETOOLONG)
return e;
{
size_t len = strlen (dir);
char *dir_end = dir + len;
struct cd_buf cdb;
size_t n_leading_slash;
cdb_init (&cdb);
/* If DIR is the empty string, then the chdir above
must have failed and set errno to ENOENT. */
assure (0 < len);
assure (PATH_MAX <= len);
/* Count leading slashes. */
n_leading_slash = strspn (dir, "/");
/* Handle any leading slashes as well as any name that matches
the regular expression, m!^//hostname[/]*! . Handling this
prefix separately usually results in a single additional
cdb_advance_fd call, but it's worthwhile, since it makes the
code in the following loop cleaner. */
if (n_leading_slash == 2)
{
int err;
/* Find next slash.
We already know that dir[2] is neither a slash nor '\0'. */
char *slash = memchr (dir + 3, '/', dir_end - (dir + 3));
if (slash == NULL)
{
errno = ENAMETOOLONG;
return -1;
}
*slash = '\0';
err = cdb_advance_fd (&cdb, dir);
*slash = '/';
if (err != 0)
goto Fail;
dir = find_non_slash (slash + 1);
}
else if (n_leading_slash)
{
if (cdb_advance_fd (&cdb, "/") != 0)
goto Fail;
dir += n_leading_slash;
}
assure (*dir != '/');
assure (dir <= dir_end);
while (PATH_MAX <= dir_end - dir)
{
int err;
/* Find a slash that is PATH_MAX or fewer bytes away from dir.
I.e. see if there is a slash that will give us a name of
length PATH_MAX-1 or less. */
char *slash = memrchr (dir, '/', PATH_MAX);
if (slash == NULL)
{
errno = ENAMETOOLONG;
return -1;
}
*slash = '\0';
assure (slash - dir < PATH_MAX);
err = cdb_advance_fd (&cdb, dir);
*slash = '/';
if (err != 0)
goto Fail;
dir = find_non_slash (slash + 1);
}
if (dir < dir_end)
{
if (cdb_advance_fd (&cdb, dir) != 0)
goto Fail;
}
if (cdb_fchdir (&cdb) != 0)
goto Fail;
cdb_free (&cdb);
return 0;
Fail:
{
int saved_errno = errno;
cdb_free (&cdb);
errno = saved_errno;
return -1;
}
}
}
#if TEST_CHDIR
# include "closeout.h"
# include "error.h"
int
main (int argc, char *argv[])
{
char *line = NULL;
size_t n = 0;
int len;
atexit (close_stdout);
len = getline (&line, &n, stdin);
if (len < 0)
{
int saved_errno = errno;
if (feof (stdin))
exit (0);
error (EXIT_FAILURE, saved_errno,
"reading standard input");
}
else if (len == 0)
exit (0);
if (line[len-1] == '\n')
line[len-1] = '\0';
if (chdir_long (line) != 0)
error (EXIT_FAILURE, errno,
"chdir_long failed: %s", line);
if (argc <= 1)
{
/* Using 'pwd' here makes sense only if it is a robust implementation,
like the one in coreutils after the 2004-04-19 changes. */
char const *cmd = "pwd";
execlp (cmd, (char *) NULL);
error (EXIT_FAILURE, errno, "%s", cmd);
}
fclose (stdin);
fclose (stderr);
exit (EXIT_SUCCESS);
}
#endif
/*
Local Variables:
compile-command: "gcc -DTEST_CHDIR=1 -g -O -W -Wall chdir-long.c libcoreutils.a"
End:
*/

30
lib/chdir-long.h Normal file
View File

@ -0,0 +1,30 @@
/* provide a chdir function that tries not to fail due to ENAMETOOLONG
Copyright (C) 2004-2005, 2009-2018 Free Software Foundation, Inc.
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 <https://www.gnu.org/licenses/>. */
/* Written by Jim Meyering. */
#include <unistd.h>
#include <limits.h>
#include "pathmax.h"
/* On systems without PATH_MAX, presume that chdir accepts
arbitrarily long directory names. */
#ifndef PATH_MAX
# define chdir_long(Dir) chdir (Dir)
#else
int chdir_long (char *dir);
#endif

3
lib/chmodat.c Normal file
View File

@ -0,0 +1,3 @@
#include <config.h>
#define FCHMODAT_INLINE _GL_EXTERN_INLINE
#include "openat.h"

151
lib/chown.c Normal file
View File

@ -0,0 +1,151 @@
/* provide consistent interface to chown for systems that don't interpret
an ID of -1 as meaning "don't change the corresponding ID".
Copyright (C) 1997, 2004-2007, 2009-2018 Free Software Foundation, Inc.
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 <https://www.gnu.org/licenses/>. */
/* written by Jim Meyering */
#include <config.h>
/* Specification. */
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <stdbool.h>
#include <string.h>
#include <sys/stat.h>
#if !HAVE_CHOWN
/* Simple stub that always fails with ENOSYS, for mingw. */
int
chown (const char *file _GL_UNUSED, uid_t uid _GL_UNUSED,
gid_t gid _GL_UNUSED)
{
errno = ENOSYS;
return -1;
}
#else /* HAVE_CHOWN */
/* Below we refer to the system's chown(). */
# undef chown
/* Provide a more-closely POSIX-conforming version of chown on
systems with one or both of the following problems:
- chown doesn't treat an ID of -1 as meaning
"don't change the corresponding ID".
- chown doesn't dereference symlinks. */
int
rpl_chown (const char *file, uid_t uid, gid_t gid)
{
struct stat st;
bool stat_valid = false;
int result;
# if CHOWN_CHANGE_TIME_BUG
if (gid != (gid_t) -1 || uid != (uid_t) -1)
{
if (stat (file, &st))
return -1;
stat_valid = true;
}
# endif
# if CHOWN_FAILS_TO_HONOR_ID_OF_NEGATIVE_ONE
if (gid == (gid_t) -1 || uid == (uid_t) -1)
{
/* Stat file to get id(s) that should remain unchanged. */
if (!stat_valid && stat (file, &st))
return -1;
if (gid == (gid_t) -1)
gid = st.st_gid;
if (uid == (uid_t) -1)
uid = st.st_uid;
}
# endif
# if CHOWN_MODIFIES_SYMLINK
{
/* Handle the case in which the system-supplied chown function
does *not* follow symlinks. Instead, it changes permissions
on the symlink itself. To work around that, we open the
file (but this can fail due to lack of read or write permission) and
use fchown on the resulting descriptor. */
int open_flags = O_NONBLOCK | O_NOCTTY;
int fd = open (file, O_RDONLY | open_flags);
if (0 <= fd
|| (errno == EACCES
&& 0 <= (fd = open (file, O_WRONLY | open_flags))))
{
int saved_errno;
bool fchown_socket_failure;
result = fchown (fd, uid, gid);
saved_errno = errno;
/* POSIX says fchown can fail with errno == EINVAL on sockets
and pipes, so fall back on chown in that case. */
fchown_socket_failure =
(result != 0 && saved_errno == EINVAL
&& fstat (fd, &st) == 0
&& (S_ISFIFO (st.st_mode) || S_ISSOCK (st.st_mode)));
close (fd);
if (! fchown_socket_failure)
{
errno = saved_errno;
return result;
}
}
else if (errno != EACCES)
return -1;
}
# endif
# if CHOWN_TRAILING_SLASH_BUG
if (!stat_valid)
{
size_t len = strlen (file);
if (len && file[len - 1] == '/' && stat (file, &st))
return -1;
}
# endif
result = chown (file, uid, gid);
# if CHOWN_CHANGE_TIME_BUG
if (result == 0 && stat_valid
&& (uid == st.st_uid || uid == (uid_t) -1)
&& (gid == st.st_gid || gid == (gid_t) -1))
{
/* No change in ownership, but at least one argument was not -1,
so we are required to update ctime. Since chown succeeded,
we assume that chmod will do likewise. Fortunately, on all
known systems where a 'no-op' chown skips the ctime update, a
'no-op' chmod still does the trick. */
result = chmod (file, st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO
| S_ISUID | S_ISGID | S_ISVTX));
}
# endif
return result;
}
#endif /* HAVE_CHOWN */

3
lib/chownat.c Normal file
View File

@ -0,0 +1,3 @@
#include <config.h>
#define FCHOWNAT_INLINE _GL_EXTERN_INLINE
#include "openat.h"

83
lib/cloexec.c Normal file
View File

@ -0,0 +1,83 @@
/* cloexec.c - set or clear the close-on-exec descriptor flag
Copyright (C) 1991, 2004-2006, 2009-2018 Free Software Foundation, Inc.
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 <https://www.gnu.org/licenses/>.
The code is taken from glibc/manual/llio.texi */
#include <config.h>
#include "cloexec.h"
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
/* Set the 'FD_CLOEXEC' flag of DESC if VALUE is true,
or clear the flag if VALUE is false.
Return 0 on success, or -1 on error with 'errno' set.
Note that on MingW, this function does NOT protect DESC from being
inherited into spawned children. Instead, either use dup_cloexec
followed by closing the original DESC, or use interfaces such as
open or pipe2 that accept flags like O_CLOEXEC to create DESC
non-inheritable in the first place. */
int
set_cloexec_flag (int desc, bool value)
{
#ifdef F_SETFD
int flags = fcntl (desc, F_GETFD, 0);
if (0 <= flags)
{
int newflags = (value ? flags | FD_CLOEXEC : flags & ~FD_CLOEXEC);
if (flags == newflags
|| fcntl (desc, F_SETFD, newflags) != -1)
return 0;
}
return -1;
#else /* !F_SETFD */
/* Use dup2 to reject invalid file descriptors; the cloexec flag
will be unaffected. */
if (desc < 0)
{
errno = EBADF;
return -1;
}
if (dup2 (desc, desc) < 0)
/* errno is EBADF here. */
return -1;
/* There is nothing we can do on this kind of platform. Punt. */
return 0;
#endif /* !F_SETFD */
}
/* Duplicates a file handle FD, while marking the copy to be closed
prior to exec or spawn. Returns -1 and sets errno if FD could not
be duplicated. */
int
dup_cloexec (int fd)
{
return fcntl (fd, F_DUPFD_CLOEXEC, 0);
}

38
lib/cloexec.h Normal file
View File

@ -0,0 +1,38 @@
/* cloexec.c - set or clear the close-on-exec descriptor flag
Copyright (C) 2004, 2009-2018 Free Software Foundation, Inc.
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 <https://www.gnu.org/licenses/>.
*/
#include <stdbool.h>
/* Set the 'FD_CLOEXEC' flag of DESC if VALUE is true,
or clear the flag if VALUE is false.
Return 0 on success, or -1 on error with 'errno' set.
Note that on MingW, this function does NOT protect DESC from being
inherited into spawned children. Instead, either use dup_cloexec
followed by closing the original DESC, or use interfaces such as
open or pipe2 that accept flags like O_CLOEXEC to create DESC
non-inheritable in the first place. */
int set_cloexec_flag (int desc, bool value);
/* Duplicates a file handle FD, while marking the copy to be closed
prior to exec or spawn. Returns -1 and sets errno if FD could not
be duplicated. */
int dup_cloexec (int fd);

71
lib/close.c Normal file
View File

@ -0,0 +1,71 @@
/* close replacement.
Copyright (C) 2008-2018 Free Software Foundation, Inc.
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 <https://www.gnu.org/licenses/>. */
#include <config.h>
/* Specification. */
#include <unistd.h>
#include <errno.h>
#include "fd-hook.h"
#if HAVE_MSVC_INVALID_PARAMETER_HANDLER
# include "msvc-inval.h"
#endif
#undef close
#if HAVE_MSVC_INVALID_PARAMETER_HANDLER
static int
close_nothrow (int fd)
{
int result;
TRY_MSVC_INVAL
{
result = close (fd);
}
CATCH_MSVC_INVAL
{
result = -1;
errno = EBADF;
}
DONE_MSVC_INVAL;
return result;
}
#else
# define close_nothrow close
#endif
/* Override close() to call into other gnulib modules. */
int
rpl_close (int fd)
{
#if WINDOWS_SOCKETS
int retval = execute_all_close_hooks (close_nothrow, fd);
#else
int retval = close_nothrow (fd);
#endif
#if REPLACE_FCHDIR
if (retval >= 0)
_gl_unregister_fd (fd);
#endif
return retval;
}

71
lib/closedir.c Normal file
View File

@ -0,0 +1,71 @@
/* Stop reading the entries of a directory.
Copyright (C) 2006-2018 Free Software Foundation, Inc.
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 <https://www.gnu.org/licenses/>. */
#include <config.h>
/* Specification. */
#include <dirent.h>
#if REPLACE_FCHDIR
# include <unistd.h>
#endif
#if HAVE_CLOSEDIR
/* Override closedir(), to keep track of the open file descriptors.
Needed because there is a function dirfd(). */
#else
# include <stdlib.h>
# include "dirent-private.h"
#endif
int
closedir (DIR *dirp)
{
# if REPLACE_FCHDIR || REPLACE_DIRFD
int fd = dirfd (dirp);
# endif
int retval;
#if HAVE_CLOSEDIR
# undef closedir
retval = closedir (dirp);
# ifdef __KLIBC__
if (!retval)
_gl_unregister_dirp_fd (fd);
# endif
#else
if (dirp->current != INVALID_HANDLE_VALUE)
FindClose (dirp->current);
free (dirp);
retval = 0;
#endif
#if REPLACE_FCHDIR
if (retval >= 0)
_gl_unregister_fd (fd);
#endif
return retval;
}

682
lib/config.charset Normal file
View File

@ -0,0 +1,682 @@
#! /bin/sh
# Output a system dependent table of character encoding aliases.
#
# Copyright (C) 2000-2004, 2006-2018 Free Software Foundation, Inc.
#
# 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, 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 <https://www.gnu.org/licenses/>.
#
# The table consists of lines of the form
# ALIAS CANONICAL
#
# ALIAS is the (system dependent) result of "nl_langinfo (CODESET)".
# ALIAS is compared in a case sensitive way.
#
# CANONICAL is the GNU canonical name for this character encoding.
# It must be an encoding supported by libiconv. Support by GNU libc is
# also desirable. CANONICAL is case insensitive. Usually an upper case
# MIME charset name is preferred.
# The current list of GNU canonical charset names is as follows.
#
# name MIME? used by which systems
# (darwin = Mac OS X, woe32 = native Windows)
#
# ASCII, ANSI_X3.4-1968 glibc solaris freebsd netbsd darwin cygwin
# ISO-8859-1 Y glibc aix hpux irix osf solaris freebsd netbsd openbsd darwin cygwin
# ISO-8859-2 Y glibc aix hpux irix osf solaris freebsd netbsd openbsd darwin cygwin
# ISO-8859-3 Y glibc solaris cygwin
# ISO-8859-4 Y osf solaris freebsd netbsd openbsd darwin
# ISO-8859-5 Y glibc aix hpux irix osf solaris freebsd netbsd openbsd darwin cygwin
# ISO-8859-6 Y glibc aix hpux solaris cygwin
# ISO-8859-7 Y glibc aix hpux irix osf solaris netbsd openbsd darwin cygwin
# ISO-8859-8 Y glibc aix hpux osf solaris cygwin
# ISO-8859-9 Y glibc aix hpux irix osf solaris darwin cygwin
# ISO-8859-13 glibc netbsd openbsd darwin cygwin
# ISO-8859-14 glibc cygwin
# ISO-8859-15 glibc aix osf solaris freebsd netbsd openbsd darwin cygwin
# KOI8-R Y glibc solaris freebsd netbsd openbsd darwin
# KOI8-U Y glibc freebsd netbsd openbsd darwin cygwin
# KOI8-T glibc
# CP437 dos
# CP775 dos
# CP850 aix osf dos
# CP852 dos
# CP855 dos
# CP856 aix
# CP857 dos
# CP861 dos
# CP862 dos
# CP864 dos
# CP865 dos
# CP866 freebsd netbsd openbsd darwin dos
# CP869 dos
# CP874 woe32 dos
# CP922 aix
# CP932 aix cygwin woe32 dos
# CP943 aix
# CP949 osf darwin woe32 dos
# CP950 woe32 dos
# CP1046 aix
# CP1124 aix
# CP1125 dos
# CP1129 aix
# CP1131 darwin
# CP1250 woe32
# CP1251 glibc solaris netbsd openbsd darwin cygwin woe32
# CP1252 aix woe32
# CP1253 woe32
# CP1254 woe32
# CP1255 glibc woe32
# CP1256 woe32
# CP1257 woe32
# GB2312 Y glibc aix hpux irix solaris freebsd netbsd darwin
# EUC-JP Y glibc aix hpux irix osf solaris freebsd netbsd darwin
# EUC-KR Y glibc aix hpux irix osf solaris freebsd netbsd darwin cygwin
# EUC-TW glibc aix hpux irix osf solaris netbsd
# BIG5 Y glibc aix hpux osf solaris freebsd netbsd darwin cygwin
# BIG5-HKSCS glibc solaris darwin
# GBK glibc aix osf solaris darwin cygwin woe32 dos
# GB18030 glibc solaris netbsd darwin
# SHIFT_JIS Y hpux osf solaris freebsd netbsd darwin
# JOHAB glibc solaris woe32
# TIS-620 glibc aix hpux osf solaris cygwin
# VISCII Y glibc
# TCVN5712-1 glibc
# ARMSCII-8 glibc darwin
# GEORGIAN-PS glibc cygwin
# PT154 glibc
# HP-ROMAN8 hpux
# HP-ARABIC8 hpux
# HP-GREEK8 hpux
# HP-HEBREW8 hpux
# HP-TURKISH8 hpux
# HP-KANA8 hpux
# DEC-KANJI osf
# DEC-HANYU osf
# UTF-8 Y glibc aix hpux osf solaris netbsd darwin cygwin
#
# Note: Names which are not marked as being a MIME name should not be used in
# Internet protocols for information interchange (mail, news, etc.).
#
# Note: ASCII and ANSI_X3.4-1968 are synonymous canonical names. Applications
# must understand both names and treat them as equivalent.
#
# The first argument passed to this file is the canonical host specification,
# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
# or
# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
host="$1"
os=`echo "$host" | sed -e 's/^[^-]*-[^-]*-\(.*\)$/\1/'`
echo "# This file contains a table of character encoding aliases,"
echo "# suitable for operating system '${os}'."
echo "# It was automatically generated from config.charset."
# List of references, updated during installation:
echo "# Packages using this file: "
case "$os" in
linux-gnulibc1*)
# Linux libc5 doesn't have nl_langinfo(CODESET); therefore
# localcharset.c falls back to using the full locale name
# from the environment variables.
echo "C ASCII"
echo "POSIX ASCII"
for l in af af_ZA ca ca_ES da da_DK de de_AT de_BE de_CH de_DE de_LU \
en en_AU en_BW en_CA en_DK en_GB en_IE en_NZ en_US en_ZA \
en_ZW es es_AR es_BO es_CL es_CO es_DO es_EC es_ES es_GT \
es_HN es_MX es_PA es_PE es_PY es_SV es_US es_UY es_VE et \
et_EE eu eu_ES fi fi_FI fo fo_FO fr fr_BE fr_CA fr_CH fr_FR \
fr_LU ga ga_IE gl gl_ES id id_ID in in_ID is is_IS it it_CH \
it_IT kl kl_GL nl nl_BE nl_NL no no_NO pt pt_BR pt_PT sv \
sv_FI sv_SE; do
echo "$l ISO-8859-1"
echo "$l.iso-8859-1 ISO-8859-1"
echo "$l.iso-8859-15 ISO-8859-15"
echo "$l.iso-8859-15@euro ISO-8859-15"
echo "$l@euro ISO-8859-15"
echo "$l.cp-437 CP437"
echo "$l.cp-850 CP850"
echo "$l.cp-1252 CP1252"
echo "$l.cp-1252@euro CP1252"
#echo "$l.atari-st ATARI-ST" # not a commonly used encoding
echo "$l.utf-8 UTF-8"
echo "$l.utf-8@euro UTF-8"
done
for l in cs cs_CZ hr hr_HR hu hu_HU pl pl_PL ro ro_RO sk sk_SK sl \
sl_SI sr sr_CS sr_YU; do
echo "$l ISO-8859-2"
echo "$l.iso-8859-2 ISO-8859-2"
echo "$l.cp-852 CP852"
echo "$l.cp-1250 CP1250"
echo "$l.utf-8 UTF-8"
done
for l in mk mk_MK ru ru_RU; do
echo "$l ISO-8859-5"
echo "$l.iso-8859-5 ISO-8859-5"
echo "$l.koi8-r KOI8-R"
echo "$l.cp-866 CP866"
echo "$l.cp-1251 CP1251"
echo "$l.utf-8 UTF-8"
done
for l in ar ar_SA; do
echo "$l ISO-8859-6"
echo "$l.iso-8859-6 ISO-8859-6"
echo "$l.cp-864 CP864"
#echo "$l.cp-868 CP868" # not a commonly used encoding
echo "$l.cp-1256 CP1256"
echo "$l.utf-8 UTF-8"
done
for l in el el_GR gr gr_GR; do
echo "$l ISO-8859-7"
echo "$l.iso-8859-7 ISO-8859-7"
echo "$l.cp-869 CP869"
echo "$l.cp-1253 CP1253"
echo "$l.cp-1253@euro CP1253"
echo "$l.utf-8 UTF-8"
echo "$l.utf-8@euro UTF-8"
done
for l in he he_IL iw iw_IL; do
echo "$l ISO-8859-8"
echo "$l.iso-8859-8 ISO-8859-8"
echo "$l.cp-862 CP862"
echo "$l.cp-1255 CP1255"
echo "$l.utf-8 UTF-8"
done
for l in tr tr_TR; do
echo "$l ISO-8859-9"
echo "$l.iso-8859-9 ISO-8859-9"
echo "$l.cp-857 CP857"
echo "$l.cp-1254 CP1254"
echo "$l.utf-8 UTF-8"
done
for l in lt lt_LT lv lv_LV; do
#echo "$l BALTIC" # not a commonly used encoding, wrong encoding name
echo "$l ISO-8859-13"
done
for l in ru_UA uk uk_UA; do
echo "$l KOI8-U"
done
for l in zh zh_CN; do
#echo "$l GB_2312-80" # not a commonly used encoding, wrong encoding name
echo "$l GB2312"
done
for l in ja ja_JP ja_JP.EUC; do
echo "$l EUC-JP"
done
for l in ko ko_KR; do
echo "$l EUC-KR"
done
for l in th th_TH; do
echo "$l TIS-620"
done
for l in fa fa_IR; do
#echo "$l ISIRI-3342" # a broken encoding
echo "$l.utf-8 UTF-8"
done
;;
linux* | *-gnu*)
# With glibc-2.1 or newer, we don't need any canonicalization,
# because glibc has iconv and both glibc and libiconv support all
# GNU canonical names directly. Therefore, the Makefile does not
# need to install the alias file at all.
# The following applies only to glibc-2.0.x and older libcs.
echo "ISO_646.IRV:1983 ASCII"
;;
aix*)
echo "ISO8859-1 ISO-8859-1"
echo "ISO8859-2 ISO-8859-2"
echo "ISO8859-5 ISO-8859-5"
echo "ISO8859-6 ISO-8859-6"
echo "ISO8859-7 ISO-8859-7"
echo "ISO8859-8 ISO-8859-8"
echo "ISO8859-9 ISO-8859-9"
echo "ISO8859-15 ISO-8859-15"
echo "IBM-850 CP850"
echo "IBM-856 CP856"
echo "IBM-921 ISO-8859-13"
echo "IBM-922 CP922"
echo "IBM-932 CP932"
echo "IBM-943 CP943"
echo "IBM-1046 CP1046"
echo "IBM-1124 CP1124"
echo "IBM-1129 CP1129"
echo "IBM-1252 CP1252"
echo "IBM-eucCN GB2312"
echo "IBM-eucJP EUC-JP"
echo "IBM-eucKR EUC-KR"
echo "IBM-eucTW EUC-TW"
echo "big5 BIG5"
echo "GBK GBK"
echo "TIS-620 TIS-620"
echo "UTF-8 UTF-8"
;;
hpux*)
echo "iso88591 ISO-8859-1"
echo "iso88592 ISO-8859-2"
echo "iso88595 ISO-8859-5"
echo "iso88596 ISO-8859-6"
echo "iso88597 ISO-8859-7"
echo "iso88598 ISO-8859-8"
echo "iso88599 ISO-8859-9"
echo "iso885915 ISO-8859-15"
echo "roman8 HP-ROMAN8"
echo "arabic8 HP-ARABIC8"
echo "greek8 HP-GREEK8"
echo "hebrew8 HP-HEBREW8"
echo "turkish8 HP-TURKISH8"
echo "kana8 HP-KANA8"
echo "tis620 TIS-620"
echo "big5 BIG5"
echo "eucJP EUC-JP"
echo "eucKR EUC-KR"
echo "eucTW EUC-TW"
echo "hp15CN GB2312"
#echo "ccdc ?" # what is this?
echo "SJIS SHIFT_JIS"
echo "utf8 UTF-8"
;;
irix*)
echo "ISO8859-1 ISO-8859-1"
echo "ISO8859-2 ISO-8859-2"
echo "ISO8859-5 ISO-8859-5"
echo "ISO8859-7 ISO-8859-7"
echo "ISO8859-9 ISO-8859-9"
echo "eucCN GB2312"
echo "eucJP EUC-JP"
echo "eucKR EUC-KR"
echo "eucTW EUC-TW"
;;
osf*)
echo "ISO8859-1 ISO-8859-1"
echo "ISO8859-2 ISO-8859-2"
echo "ISO8859-4 ISO-8859-4"
echo "ISO8859-5 ISO-8859-5"
echo "ISO8859-7 ISO-8859-7"
echo "ISO8859-8 ISO-8859-8"
echo "ISO8859-9 ISO-8859-9"
echo "ISO8859-15 ISO-8859-15"
echo "cp850 CP850"
echo "big5 BIG5"
echo "dechanyu DEC-HANYU"
echo "dechanzi GB2312"
echo "deckanji DEC-KANJI"
echo "deckorean EUC-KR"
echo "eucJP EUC-JP"
echo "eucKR EUC-KR"
echo "eucTW EUC-TW"
echo "GBK GBK"
echo "KSC5601 CP949"
echo "sdeckanji EUC-JP"
echo "SJIS SHIFT_JIS"
echo "TACTIS TIS-620"
echo "UTF-8 UTF-8"
;;
solaris*)
echo "646 ASCII"
echo "ISO8859-1 ISO-8859-1"
echo "ISO8859-2 ISO-8859-2"
echo "ISO8859-3 ISO-8859-3"
echo "ISO8859-4 ISO-8859-4"
echo "ISO8859-5 ISO-8859-5"
echo "ISO8859-6 ISO-8859-6"
echo "ISO8859-7 ISO-8859-7"
echo "ISO8859-8 ISO-8859-8"
echo "ISO8859-9 ISO-8859-9"
echo "ISO8859-15 ISO-8859-15"
echo "koi8-r KOI8-R"
echo "ansi-1251 CP1251"
echo "BIG5 BIG5"
echo "Big5-HKSCS BIG5-HKSCS"
echo "gb2312 GB2312"
echo "GBK GBK"
echo "GB18030 GB18030"
echo "cns11643 EUC-TW"
echo "5601 EUC-KR"
echo "ko_KR.johap92 JOHAB"
echo "eucJP EUC-JP"
echo "PCK SHIFT_JIS"
echo "TIS620.2533 TIS-620"
#echo "sun_eu_greek ?" # what is this?
echo "UTF-8 UTF-8"
;;
freebsd*)
# FreeBSD 4.2 doesn't have nl_langinfo(CODESET); therefore
# localcharset.c falls back to using the full locale name
# from the environment variables.
echo "C ASCII"
echo "US-ASCII ASCII"
for l in la_LN lt_LN; do
echo "$l.ASCII ASCII"
done
for l in da_DK de_AT de_CH de_DE en_AU en_CA en_GB en_US es_ES \
fi_FI fr_BE fr_CA fr_CH fr_FR is_IS it_CH it_IT la_LN \
lt_LN nl_BE nl_NL no_NO pt_PT sv_SE; do
echo "$l.ISO_8859-1 ISO-8859-1"
echo "$l.DIS_8859-15 ISO-8859-15"
done
for l in cs_CZ hr_HR hu_HU la_LN lt_LN pl_PL sl_SI; do
echo "$l.ISO_8859-2 ISO-8859-2"
done
for l in la_LN lt_LT; do
echo "$l.ISO_8859-4 ISO-8859-4"
done
for l in ru_RU ru_SU; do
echo "$l.KOI8-R KOI8-R"
echo "$l.ISO_8859-5 ISO-8859-5"
echo "$l.CP866 CP866"
done
echo "uk_UA.KOI8-U KOI8-U"
echo "zh_TW.BIG5 BIG5"
echo "zh_TW.Big5 BIG5"
echo "zh_CN.EUC GB2312"
echo "ja_JP.EUC EUC-JP"
echo "ja_JP.SJIS SHIFT_JIS"
echo "ja_JP.Shift_JIS SHIFT_JIS"
echo "ko_KR.EUC EUC-KR"
;;
netbsd*)
echo "646 ASCII"
echo "ISO8859-1 ISO-8859-1"
echo "ISO8859-2 ISO-8859-2"
echo "ISO8859-4 ISO-8859-4"
echo "ISO8859-5 ISO-8859-5"
echo "ISO8859-7 ISO-8859-7"
echo "ISO8859-13 ISO-8859-13"
echo "ISO8859-15 ISO-8859-15"
echo "eucCN GB2312"
echo "eucJP EUC-JP"
echo "eucKR EUC-KR"
echo "eucTW EUC-TW"
echo "BIG5 BIG5"
echo "SJIS SHIFT_JIS"
;;
openbsd*)
echo "646 ASCII"
echo "ISO8859-1 ISO-8859-1"
echo "ISO8859-2 ISO-8859-2"
echo "ISO8859-4 ISO-8859-4"
echo "ISO8859-5 ISO-8859-5"
echo "ISO8859-7 ISO-8859-7"
echo "ISO8859-13 ISO-8859-13"
echo "ISO8859-15 ISO-8859-15"
;;
darwin[56]*)
# Darwin 6.8 doesn't have nl_langinfo(CODESET); therefore
# localcharset.c falls back to using the full locale name
# from the environment variables.
echo "C ASCII"
for l in en_AU en_CA en_GB en_US la_LN; do
echo "$l.US-ASCII ASCII"
done
for l in da_DK de_AT de_CH de_DE en_AU en_CA en_GB en_US es_ES \
fi_FI fr_BE fr_CA fr_CH fr_FR is_IS it_CH it_IT nl_BE \
nl_NL no_NO pt_PT sv_SE; do
echo "$l ISO-8859-1"
echo "$l.ISO8859-1 ISO-8859-1"
echo "$l.ISO8859-15 ISO-8859-15"
done
for l in la_LN; do
echo "$l.ISO8859-1 ISO-8859-1"
echo "$l.ISO8859-15 ISO-8859-15"
done
for l in cs_CZ hr_HR hu_HU la_LN pl_PL sl_SI; do
echo "$l.ISO8859-2 ISO-8859-2"
done
for l in la_LN lt_LT; do
echo "$l.ISO8859-4 ISO-8859-4"
done
for l in ru_RU; do
echo "$l.KOI8-R KOI8-R"
echo "$l.ISO8859-5 ISO-8859-5"
echo "$l.CP866 CP866"
done
for l in bg_BG; do
echo "$l.CP1251 CP1251"
done
echo "uk_UA.KOI8-U KOI8-U"
echo "zh_TW.BIG5 BIG5"
echo "zh_TW.Big5 BIG5"
echo "zh_CN.EUC GB2312"
echo "ja_JP.EUC EUC-JP"
echo "ja_JP.SJIS SHIFT_JIS"
echo "ko_KR.EUC EUC-KR"
;;
darwin*)
# Darwin 7.5 has nl_langinfo(CODESET), but sometimes its value is
# useless:
# - It returns the empty string when LANG is set to a locale of the
# form ll_CC, although ll_CC/LC_CTYPE is a symlink to an UTF-8
# LC_CTYPE file.
# - The environment variables LANG, LC_CTYPE, LC_ALL are not set by
# the system; nl_langinfo(CODESET) returns "US-ASCII" in this case.
# - The documentation says:
# "... all code that calls BSD system routines should ensure
# that the const *char parameters of these routines are in UTF-8
# encoding. All BSD system functions expect their string
# parameters to be in UTF-8 encoding and nothing else."
# It also says
# "An additional caveat is that string parameters for files,
# paths, and other file-system entities must be in canonical
# UTF-8. In a canonical UTF-8 Unicode string, all decomposable
# characters are decomposed ..."
# but this is not true: You can pass non-decomposed UTF-8 strings
# to file system functions, and it is the OS which will convert
# them to decomposed UTF-8 before accessing the file system.
# - The Apple Terminal application displays UTF-8 by default.
# - However, other applications are free to use different encodings:
# - xterm uses ISO-8859-1 by default.
# - TextEdit uses MacRoman by default.
# We prefer UTF-8 over decomposed UTF-8-MAC because one should
# minimize the use of decomposed Unicode. Unfortunately, through the
# Darwin file system, decomposed UTF-8 strings are leaked into user
# space nevertheless.
# Then there are also the locales with encodings other than US-ASCII
# and UTF-8. These locales can be occasionally useful to users (e.g.
# when grepping through ISO-8859-1 encoded text files), when all their
# file names are in US-ASCII.
echo "ISO8859-1 ISO-8859-1"
echo "ISO8859-2 ISO-8859-2"
echo "ISO8859-4 ISO-8859-4"
echo "ISO8859-5 ISO-8859-5"
echo "ISO8859-7 ISO-8859-7"
echo "ISO8859-9 ISO-8859-9"
echo "ISO8859-13 ISO-8859-13"
echo "ISO8859-15 ISO-8859-15"
echo "KOI8-R KOI8-R"
echo "KOI8-U KOI8-U"
echo "CP866 CP866"
echo "CP949 CP949"
echo "CP1131 CP1131"
echo "CP1251 CP1251"
echo "eucCN GB2312"
echo "GB2312 GB2312"
echo "eucJP EUC-JP"
echo "eucKR EUC-KR"
echo "Big5 BIG5"
echo "Big5HKSCS BIG5-HKSCS"
echo "GBK GBK"
echo "GB18030 GB18030"
echo "SJIS SHIFT_JIS"
echo "ARMSCII-8 ARMSCII-8"
echo "PT154 PT154"
#echo "ISCII-DEV ?"
echo "* UTF-8"
;;
beos* | haiku*)
# BeOS and Haiku have a single locale, and it has UTF-8 encoding.
echo "* UTF-8"
;;
msdosdjgpp*)
# DJGPP 2.03 doesn't have nl_langinfo(CODESET); therefore
# localcharset.c falls back to using the full locale name
# from the environment variables.
echo "#"
echo "# The encodings given here may not all be correct."
echo "# If you find that the encoding given for your language and"
echo "# country is not the one your DOS machine actually uses, just"
echo "# correct it in this file, and send a mail to"
echo "# Juan Manuel Guerrero <juan.guerrero@gmx.de>"
echo "# and Bruno Haible <bruno@clisp.org>."
echo "#"
echo "C ASCII"
# ISO-8859-1 languages
echo "ca CP850"
echo "ca_ES CP850"
echo "da CP865" # not CP850 ??
echo "da_DK CP865" # not CP850 ??
echo "de CP850"
echo "de_AT CP850"
echo "de_CH CP850"
echo "de_DE CP850"
echo "en CP850"
echo "en_AU CP850" # not CP437 ??
echo "en_CA CP850"
echo "en_GB CP850"
echo "en_NZ CP437"
echo "en_US CP437"
echo "en_ZA CP850" # not CP437 ??
echo "es CP850"
echo "es_AR CP850"
echo "es_BO CP850"
echo "es_CL CP850"
echo "es_CO CP850"
echo "es_CR CP850"
echo "es_CU CP850"
echo "es_DO CP850"
echo "es_EC CP850"
echo "es_ES CP850"
echo "es_GT CP850"
echo "es_HN CP850"
echo "es_MX CP850"
echo "es_NI CP850"
echo "es_PA CP850"
echo "es_PY CP850"
echo "es_PE CP850"
echo "es_SV CP850"
echo "es_UY CP850"
echo "es_VE CP850"
echo "et CP850"
echo "et_EE CP850"
echo "eu CP850"
echo "eu_ES CP850"
echo "fi CP850"
echo "fi_FI CP850"
echo "fr CP850"
echo "fr_BE CP850"
echo "fr_CA CP850"
echo "fr_CH CP850"
echo "fr_FR CP850"
echo "ga CP850"
echo "ga_IE CP850"
echo "gd CP850"
echo "gd_GB CP850"
echo "gl CP850"
echo "gl_ES CP850"
echo "id CP850" # not CP437 ??
echo "id_ID CP850" # not CP437 ??
echo "is CP861" # not CP850 ??
echo "is_IS CP861" # not CP850 ??
echo "it CP850"
echo "it_CH CP850"
echo "it_IT CP850"
echo "lt CP775"
echo "lt_LT CP775"
echo "lv CP775"
echo "lv_LV CP775"
echo "nb CP865" # not CP850 ??
echo "nb_NO CP865" # not CP850 ??
echo "nl CP850"
echo "nl_BE CP850"
echo "nl_NL CP850"
echo "nn CP865" # not CP850 ??
echo "nn_NO CP865" # not CP850 ??
echo "no CP865" # not CP850 ??
echo "no_NO CP865" # not CP850 ??
echo "pt CP850"
echo "pt_BR CP850"
echo "pt_PT CP850"
echo "sv CP850"
echo "sv_SE CP850"
# ISO-8859-2 languages
echo "cs CP852"
echo "cs_CZ CP852"
echo "hr CP852"
echo "hr_HR CP852"
echo "hu CP852"
echo "hu_HU CP852"
echo "pl CP852"
echo "pl_PL CP852"
echo "ro CP852"
echo "ro_RO CP852"
echo "sk CP852"
echo "sk_SK CP852"
echo "sl CP852"
echo "sl_SI CP852"
echo "sq CP852"
echo "sq_AL CP852"
echo "sr CP852" # CP852 or CP866 or CP855 ??
echo "sr_CS CP852" # CP852 or CP866 or CP855 ??
echo "sr_YU CP852" # CP852 or CP866 or CP855 ??
# ISO-8859-3 languages
echo "mt CP850"
echo "mt_MT CP850"
# ISO-8859-5 languages
echo "be CP866"
echo "be_BE CP866"
echo "bg CP866" # not CP855 ??
echo "bg_BG CP866" # not CP855 ??
echo "mk CP866" # not CP855 ??
echo "mk_MK CP866" # not CP855 ??
echo "ru CP866"
echo "ru_RU CP866"
echo "uk CP1125"
echo "uk_UA CP1125"
# ISO-8859-6 languages
echo "ar CP864"
echo "ar_AE CP864"
echo "ar_DZ CP864"
echo "ar_EG CP864"
echo "ar_IQ CP864"
echo "ar_IR CP864"
echo "ar_JO CP864"
echo "ar_KW CP864"
echo "ar_MA CP864"
echo "ar_OM CP864"
echo "ar_QA CP864"
echo "ar_SA CP864"
echo "ar_SY CP864"
# ISO-8859-7 languages
echo "el CP869"
echo "el_GR CP869"
# ISO-8859-8 languages
echo "he CP862"
echo "he_IL CP862"
# ISO-8859-9 languages
echo "tr CP857"
echo "tr_TR CP857"
# Japanese
echo "ja CP932"
echo "ja_JP CP932"
# Chinese
echo "zh_CN GBK"
echo "zh_TW CP950" # not CP938 ??
# Korean
echo "kr CP949" # not CP934 ??
echo "kr_KR CP949" # not CP934 ??
# Thai
echo "th CP874"
echo "th_TH CP874"
# Other
echo "eo CP850"
echo "eo_EO CP850"
;;
esac

529
lib/diffseq.h Normal file
View File

@ -0,0 +1,529 @@
/* Analyze differences between two vectors.
Copyright (C) 1988-1989, 1992-1995, 2001-2004, 2006-2018 Free Software
Foundation, Inc.
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 <https://www.gnu.org/licenses/>. */
/* The basic idea is to consider two vectors as similar if, when
transforming the first vector into the second vector through a
sequence of edits (inserts and deletes of one element each),
this sequence is short - or equivalently, if the ordered list
of elements that are untouched by these edits is long. For a
good introduction to the subject, read about the "Levenshtein
distance" in Wikipedia.
The basic algorithm is described in:
"An O(ND) Difference Algorithm and its Variations", Eugene W. Myers,
Algorithmica Vol. 1, 1986, pp. 251-266,
<http://dx.doi.org/10.1007/BF01840446>.
See especially section 4.2, which describes the variation used below.
The basic algorithm was independently discovered as described in:
"Algorithms for Approximate String Matching", Esko Ukkonen,
Information and Control Vol. 64, 1985, pp. 100-118,
<http://dx.doi.org/10.1016/S0019-9958(85)80046-2>.
Unless the 'find_minimal' flag is set, this code uses the TOO_EXPENSIVE
heuristic, by Paul Eggert, to limit the cost to O(N**1.5 log N)
at the price of producing suboptimal output for large inputs with
many differences. */
/* Before including this file, you need to define:
ELEMENT The element type of the vectors being compared.
EQUAL A two-argument macro that tests two elements for
equality.
OFFSET A signed integer type sufficient to hold the
difference between two indices. Usually
something like ptrdiff_t.
EXTRA_CONTEXT_FIELDS Declarations of fields for 'struct context'.
NOTE_DELETE(ctxt, xoff) Record the removal of the object xvec[xoff].
NOTE_INSERT(ctxt, yoff) Record the insertion of the object yvec[yoff].
EARLY_ABORT(ctxt) (Optional) A boolean expression that triggers an
early abort of the computation.
USE_HEURISTIC (Optional) Define if you want to support the
heuristic for large vectors.
It is also possible to use this file with abstract arrays. In this case,
xvec and yvec are not represented in memory. They only exist conceptually.
In this case, the list of defines above is amended as follows:
ELEMENT Undefined.
EQUAL Undefined.
XVECREF_YVECREF_EQUAL(ctxt, xoff, yoff)
A three-argument macro: References xvec[xoff] and
yvec[yoff] and tests these elements for equality.
Before including this file, you also need to include:
#include <limits.h>
#include <stdbool.h>
#include "minmax.h"
*/
/* Maximum value of type OFFSET. */
#define OFFSET_MAX \
((((OFFSET)1 << (sizeof (OFFSET) * CHAR_BIT - 2)) - 1) * 2 + 1)
/* Default to no early abort. */
#ifndef EARLY_ABORT
# define EARLY_ABORT(ctxt) false
#endif
/* Use this to suppress gcc's "...may be used before initialized" warnings.
Beware: The Code argument must not contain commas. */
#ifndef IF_LINT
# if defined GCC_LINT || defined lint
# define IF_LINT(Code) Code
# else
# define IF_LINT(Code) /* empty */
# endif
#endif
/* As above, but when Code must contain one comma. */
#ifndef IF_LINT2
# if defined GCC_LINT || defined lint
# define IF_LINT2(Code1, Code2) Code1, Code2
# else
# define IF_LINT2(Code1, Code2) /* empty */
# endif
#endif
/*
* Context of comparison operation.
*/
struct context
{
#ifdef ELEMENT
/* Vectors being compared. */
ELEMENT const *xvec;
ELEMENT const *yvec;
#endif
/* Extra fields. */
EXTRA_CONTEXT_FIELDS
/* Vector, indexed by diagonal, containing 1 + the X coordinate of the point
furthest along the given diagonal in the forward search of the edit
matrix. */
OFFSET *fdiag;
/* Vector, indexed by diagonal, containing the X coordinate of the point
furthest along the given diagonal in the backward search of the edit
matrix. */
OFFSET *bdiag;
#ifdef USE_HEURISTIC
/* This corresponds to the diff --speed-large-files flag. With this
heuristic, for vectors with a constant small density of changes,
the algorithm is linear in the vector size. */
bool heuristic;
#endif
/* Edit scripts longer than this are too expensive to compute. */
OFFSET too_expensive;
/* Snakes bigger than this are considered "big". */
#define SNAKE_LIMIT 20
};
struct partition
{
/* Midpoints of this partition. */
OFFSET xmid;
OFFSET ymid;
/* True if low half will be analyzed minimally. */
bool lo_minimal;
/* Likewise for high half. */
bool hi_minimal;
};
/* Find the midpoint of the shortest edit script for a specified portion
of the two vectors.
Scan from the beginnings of the vectors, and simultaneously from the ends,
doing a breadth-first search through the space of edit-sequence.
When the two searches meet, we have found the midpoint of the shortest
edit sequence.
If FIND_MINIMAL is true, find the minimal edit script regardless of
expense. Otherwise, if the search is too expensive, use heuristics to
stop the search and report a suboptimal answer.
Set PART->(xmid,ymid) to the midpoint (XMID,YMID). The diagonal number
XMID - YMID equals the number of inserted elements minus the number
of deleted elements (counting only elements before the midpoint).
Set PART->lo_minimal to true iff the minimal edit script for the
left half of the partition is known; similarly for PART->hi_minimal.
This function assumes that the first elements of the specified portions
of the two vectors do not match, and likewise that the last elements do not
match. The caller must trim matching elements from the beginning and end
of the portions it is going to specify.
If we return the "wrong" partitions, the worst this can do is cause
suboptimal diff output. It cannot cause incorrect diff output. */
static void
diag (OFFSET xoff, OFFSET xlim, OFFSET yoff, OFFSET ylim, bool find_minimal,
struct partition *part, struct context *ctxt)
{
OFFSET *const fd = ctxt->fdiag; /* Give the compiler a chance. */
OFFSET *const bd = ctxt->bdiag; /* Additional help for the compiler. */
#ifdef ELEMENT
ELEMENT const *const xv = ctxt->xvec; /* Still more help for the compiler. */
ELEMENT const *const yv = ctxt->yvec; /* And more and more . . . */
#define XREF_YREF_EQUAL(x,y) EQUAL (xv[x], yv[y])
#else
#define XREF_YREF_EQUAL(x,y) XVECREF_YVECREF_EQUAL (ctxt, x, y)
#endif
const OFFSET dmin = xoff - ylim; /* Minimum valid diagonal. */
const OFFSET dmax = xlim - yoff; /* Maximum valid diagonal. */
const OFFSET fmid = xoff - yoff; /* Center diagonal of top-down search. */
const OFFSET bmid = xlim - ylim; /* Center diagonal of bottom-up search. */
OFFSET fmin = fmid;
OFFSET fmax = fmid; /* Limits of top-down search. */
OFFSET bmin = bmid;
OFFSET bmax = bmid; /* Limits of bottom-up search. */
OFFSET c; /* Cost. */
bool odd = (fmid - bmid) & 1; /* True if southeast corner is on an odd
diagonal with respect to the northwest. */
fd[fmid] = xoff;
bd[bmid] = xlim;
for (c = 1;; ++c)
{
OFFSET d; /* Active diagonal. */
bool big_snake = false;
/* Extend the top-down search by an edit step in each diagonal. */
if (fmin > dmin)
fd[--fmin - 1] = -1;
else
++fmin;
if (fmax < dmax)
fd[++fmax + 1] = -1;
else
--fmax;
for (d = fmax; d >= fmin; d -= 2)
{
OFFSET x;
OFFSET y;
OFFSET tlo = fd[d - 1];
OFFSET thi = fd[d + 1];
OFFSET x0 = tlo < thi ? thi : tlo + 1;
for (x = x0, y = x0 - d;
x < xlim && y < ylim && XREF_YREF_EQUAL (x, y);
x++, y++)
continue;
if (x - x0 > SNAKE_LIMIT)
big_snake = true;
fd[d] = x;
if (odd && bmin <= d && d <= bmax && bd[d] <= x)
{
part->xmid = x;
part->ymid = y;
part->lo_minimal = part->hi_minimal = true;
return;
}
}
/* Similarly extend the bottom-up search. */
if (bmin > dmin)
bd[--bmin - 1] = OFFSET_MAX;
else
++bmin;
if (bmax < dmax)
bd[++bmax + 1] = OFFSET_MAX;
else
--bmax;
for (d = bmax; d >= bmin; d -= 2)
{
OFFSET x;
OFFSET y;
OFFSET tlo = bd[d - 1];
OFFSET thi = bd[d + 1];
OFFSET x0 = tlo < thi ? tlo : thi - 1;
for (x = x0, y = x0 - d;
xoff < x && yoff < y && XREF_YREF_EQUAL (x - 1, y - 1);
x--, y--)
continue;
if (x0 - x > SNAKE_LIMIT)
big_snake = true;
bd[d] = x;
if (!odd && fmin <= d && d <= fmax && x <= fd[d])
{
part->xmid = x;
part->ymid = y;
part->lo_minimal = part->hi_minimal = true;
return;
}
}
if (find_minimal)
continue;
#ifdef USE_HEURISTIC
bool heuristic = ctxt->heuristic;
#else
bool heuristic = false;
#endif
/* Heuristic: check occasionally for a diagonal that has made lots
of progress compared with the edit distance. If we have any
such, find the one that has made the most progress and return it
as if it had succeeded.
With this heuristic, for vectors with a constant small density
of changes, the algorithm is linear in the vector size. */
if (200 < c && big_snake && heuristic)
{
{
OFFSET best = 0;
for (d = fmax; d >= fmin; d -= 2)
{
OFFSET dd = d - fmid;
OFFSET x = fd[d];
OFFSET y = x - d;
OFFSET v = (x - xoff) * 2 - dd;
if (v > 12 * (c + (dd < 0 ? -dd : dd)))
{
if (v > best
&& xoff + SNAKE_LIMIT <= x && x < xlim
&& yoff + SNAKE_LIMIT <= y && y < ylim)
{
/* We have a good enough best diagonal; now insist
that it end with a significant snake. */
int k;
for (k = 1; XREF_YREF_EQUAL (x - k, y - k); k++)
if (k == SNAKE_LIMIT)
{
best = v;
part->xmid = x;
part->ymid = y;
break;
}
}
}
}
if (best > 0)
{
part->lo_minimal = true;
part->hi_minimal = false;
return;
}
}
{
OFFSET best = 0;
for (d = bmax; d >= bmin; d -= 2)
{
OFFSET dd = d - bmid;
OFFSET x = bd[d];
OFFSET y = x - d;
OFFSET v = (xlim - x) * 2 + dd;
if (v > 12 * (c + (dd < 0 ? -dd : dd)))
{
if (v > best
&& xoff < x && x <= xlim - SNAKE_LIMIT
&& yoff < y && y <= ylim - SNAKE_LIMIT)
{
/* We have a good enough best diagonal; now insist
that it end with a significant snake. */
int k;
for (k = 0; XREF_YREF_EQUAL (x + k, y + k); k++)
if (k == SNAKE_LIMIT - 1)
{
best = v;
part->xmid = x;
part->ymid = y;
break;
}
}
}
}
if (best > 0)
{
part->lo_minimal = false;
part->hi_minimal = true;
return;
}
}
}
/* Heuristic: if we've gone well beyond the call of duty, give up
and report halfway between our best results so far. */
if (c >= ctxt->too_expensive)
{
OFFSET fxybest;
OFFSET fxbest IF_LINT (= 0);
OFFSET bxybest;
OFFSET bxbest IF_LINT (= 0);
/* Find forward diagonal that maximizes X + Y. */
fxybest = -1;
for (d = fmax; d >= fmin; d -= 2)
{
OFFSET x = MIN (fd[d], xlim);
OFFSET y = x - d;
if (ylim < y)
{
x = ylim + d;
y = ylim;
}
if (fxybest < x + y)
{
fxybest = x + y;
fxbest = x;
}
}
/* Find backward diagonal that minimizes X + Y. */
bxybest = OFFSET_MAX;
for (d = bmax; d >= bmin; d -= 2)
{
OFFSET x = MAX (xoff, bd[d]);
OFFSET y = x - d;
if (y < yoff)
{
x = yoff + d;
y = yoff;
}
if (x + y < bxybest)
{
bxybest = x + y;
bxbest = x;
}
}
/* Use the better of the two diagonals. */
if ((xlim + ylim) - bxybest < fxybest - (xoff + yoff))
{
part->xmid = fxbest;
part->ymid = fxybest - fxbest;
part->lo_minimal = true;
part->hi_minimal = false;
}
else
{
part->xmid = bxbest;
part->ymid = bxybest - bxbest;
part->lo_minimal = false;
part->hi_minimal = true;
}
return;
}
}
#undef XREF_YREF_EQUAL
}
/* Compare in detail contiguous subsequences of the two vectors
which are known, as a whole, to match each other.
The subsequence of vector 0 is [XOFF, XLIM) and likewise for vector 1.
Note that XLIM, YLIM are exclusive bounds. All indices into the vectors
are origin-0.
If FIND_MINIMAL, find a minimal difference no matter how
expensive it is.
The results are recorded by invoking NOTE_DELETE and NOTE_INSERT.
Return false if terminated normally, or true if terminated through early
abort. */
static bool
compareseq (OFFSET xoff, OFFSET xlim, OFFSET yoff, OFFSET ylim,
bool find_minimal, struct context *ctxt)
{
#ifdef ELEMENT
ELEMENT const *xv = ctxt->xvec; /* Help the compiler. */
ELEMENT const *yv = ctxt->yvec;
#define XREF_YREF_EQUAL(x,y) EQUAL (xv[x], yv[y])
#else
#define XREF_YREF_EQUAL(x,y) XVECREF_YVECREF_EQUAL (ctxt, x, y)
#endif
/* Slide down the bottom initial diagonal. */
while (xoff < xlim && yoff < ylim && XREF_YREF_EQUAL (xoff, yoff))
{
xoff++;
yoff++;
}
/* Slide up the top initial diagonal. */
while (xoff < xlim && yoff < ylim && XREF_YREF_EQUAL (xlim - 1, ylim - 1))
{
xlim--;
ylim--;
}
/* Handle simple cases. */
if (xoff == xlim)
while (yoff < ylim)
{
NOTE_INSERT (ctxt, yoff);
if (EARLY_ABORT (ctxt))
return true;
yoff++;
}
else if (yoff == ylim)
while (xoff < xlim)
{
NOTE_DELETE (ctxt, xoff);
if (EARLY_ABORT (ctxt))
return true;
xoff++;
}
else
{
struct partition part IF_LINT2 (= { .xmid = 0, .ymid = 0 });
/* Find a point of correspondence in the middle of the vectors. */
diag (xoff, xlim, yoff, ylim, find_minimal, &part, ctxt);
/* Use the partitions to split this problem into subproblems. */
if (compareseq (xoff, part.xmid, yoff, part.ymid, part.lo_minimal, ctxt))
return true;
if (compareseq (part.xmid, xlim, part.ymid, ylim, part.hi_minimal, ctxt))
return true;
}
return false;
#undef XREF_YREF_EQUAL
}
#undef ELEMENT
#undef EQUAL
#undef OFFSET
#undef EXTRA_CONTEXT_FIELDS
#undef NOTE_DELETE
#undef NOTE_INSERT
#undef EARLY_ABORT
#undef USE_HEURISTIC
#undef XVECREF_YVECREF_EQUAL
#undef OFFSET_MAX

24
lib/dirent--.h Normal file
View File

@ -0,0 +1,24 @@
/* Like dirent.h, but redefine some names to avoid glitches.
Copyright (C) 2009-2018 Free Software Foundation, Inc.
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 <https://www.gnu.org/licenses/>. */
/* Written by Eric Blake. */
#include "dirent-safer.h"
#undef opendir
#define opendir opendir_safer
#define GNULIB_defined_opendir 1

40
lib/dirent-private.h Normal file
View File

@ -0,0 +1,40 @@
/* Private details of the DIR type.
Copyright (C) 2011-2018 Free Software Foundation, Inc.
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 <https://www.gnu.org/licenses/>. */
#ifndef _DIRENT_PRIVATE_H
#define _DIRENT_PRIVATE_H 1
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
struct gl_directory
{
/* Status, or error code to produce in next readdir() call.
-2 means the end of the directory is already reached,
-1 means the entry was already filled by FindFirstFile,
0 means the entry needs to be filled using FindNextFile.
A positive value is an error code. */
int status;
/* Handle, reading the directory, at current position. */
HANDLE current;
/* Found directory entry. */
WIN32_FIND_DATA entry;
/* Argument to pass to FindFirstFile. It consists of the absolutized
directory name, followed by a directory separator and the wildcards. */
char dir_name_mask[1];
};
#endif /* _DIRENT_PRIVATE_H */

22
lib/dirent-safer.h Normal file
View File

@ -0,0 +1,22 @@
/* Invoke dirent-like functions, but avoid some glitches.
Copyright (C) 2009-2018 Free Software Foundation, Inc.
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 <https://www.gnu.org/licenses/>. */
/* Written by Eric Blake. */
#include <dirent.h>
DIR *opendir_safer (const char *name);

267
lib/dirent.in.h Normal file
View File

@ -0,0 +1,267 @@
/* A GNU-like <dirent.h>.
Copyright (C) 2006-2018 Free Software Foundation, Inc.
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 <https://www.gnu.org/licenses/>. */
#ifndef _@GUARD_PREFIX@_DIRENT_H
#if __GNUC__ >= 3
@PRAGMA_SYSTEM_HEADER@
#endif
@PRAGMA_COLUMNS@
/* The include_next requires a split double-inclusion guard. */
#if @HAVE_DIRENT_H@
# @INCLUDE_NEXT@ @NEXT_DIRENT_H@
#endif
#ifndef _@GUARD_PREFIX@_DIRENT_H
#define _@GUARD_PREFIX@_DIRENT_H
/* Get ino_t. Needed on some systems, including glibc 2.8. */
#include <sys/types.h>
#if !@HAVE_DIRENT_H@
/* Define types DIR and 'struct dirent'. */
# if !GNULIB_defined_struct_dirent
struct dirent
{
char d_type;
char d_name[1];
};
/* Possible values for 'd_type'. */
# define DT_UNKNOWN 0
# define DT_FIFO 1 /* FIFO */
# define DT_CHR 2 /* character device */
# define DT_DIR 4 /* directory */
# define DT_BLK 6 /* block device */
# define DT_REG 8 /* regular file */
# define DT_LNK 10 /* symbolic link */
# define DT_SOCK 12 /* socket */
# define DT_WHT 14 /* whiteout */
typedef struct gl_directory DIR;
# define GNULIB_defined_struct_dirent 1
# endif
#endif
/* The __attribute__ feature is available in gcc versions 2.5 and later.
The attribute __pure__ was added in gcc 2.96. */
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96)
# define _GL_ATTRIBUTE_PURE __attribute__ ((__pure__))
#else
# define _GL_ATTRIBUTE_PURE /* empty */
#endif
/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */
/* The definition of _GL_ARG_NONNULL is copied here. */
/* The definition of _GL_WARN_ON_USE is copied here. */
/* Declare overridden functions. */
#if @GNULIB_OPENDIR@
# if @REPLACE_OPENDIR@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# undef opendir
# define opendir rpl_opendir
# define GNULIB_defined_opendir 1
# endif
_GL_FUNCDECL_RPL (opendir, DIR *, (const char *dir_name) _GL_ARG_NONNULL ((1)));
_GL_CXXALIAS_RPL (opendir, DIR *, (const char *dir_name));
# else
# if !@HAVE_OPENDIR@
_GL_FUNCDECL_SYS (opendir, DIR *, (const char *dir_name) _GL_ARG_NONNULL ((1)));
# endif
_GL_CXXALIAS_SYS (opendir, DIR *, (const char *dir_name));
# endif
_GL_CXXALIASWARN (opendir);
#elif defined GNULIB_POSIXCHECK
# undef opendir
# if HAVE_RAW_DECL_OPENDIR
_GL_WARN_ON_USE (opendir, "opendir is not portable - "
"use gnulib module opendir for portability");
# endif
#endif
#if @GNULIB_READDIR@
# if !@HAVE_READDIR@
_GL_FUNCDECL_SYS (readdir, struct dirent *, (DIR *dirp) _GL_ARG_NONNULL ((1)));
# endif
_GL_CXXALIAS_SYS (readdir, struct dirent *, (DIR *dirp));
_GL_CXXALIASWARN (readdir);
#elif defined GNULIB_POSIXCHECK
# undef readdir
# if HAVE_RAW_DECL_READDIR
_GL_WARN_ON_USE (readdir, "readdir is not portable - "
"use gnulib module readdir for portability");
# endif
#endif
#if @GNULIB_REWINDDIR@
# if !@HAVE_REWINDDIR@
_GL_FUNCDECL_SYS (rewinddir, void, (DIR *dirp) _GL_ARG_NONNULL ((1)));
# endif
_GL_CXXALIAS_SYS (rewinddir, void, (DIR *dirp));
_GL_CXXALIASWARN (rewinddir);
#elif defined GNULIB_POSIXCHECK
# undef rewinddir
# if HAVE_RAW_DECL_REWINDDIR
_GL_WARN_ON_USE (rewinddir, "rewinddir is not portable - "
"use gnulib module rewinddir for portability");
# endif
#endif
#if @GNULIB_CLOSEDIR@
# if @REPLACE_CLOSEDIR@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# undef closedir
# define closedir rpl_closedir
# define GNULIB_defined_closedir 1
# endif
_GL_FUNCDECL_RPL (closedir, int, (DIR *dirp) _GL_ARG_NONNULL ((1)));
_GL_CXXALIAS_RPL (closedir, int, (DIR *dirp));
# else
# if !@HAVE_CLOSEDIR@
_GL_FUNCDECL_SYS (closedir, int, (DIR *dirp) _GL_ARG_NONNULL ((1)));
# endif
_GL_CXXALIAS_SYS (closedir, int, (DIR *dirp));
# endif
_GL_CXXALIASWARN (closedir);
#elif defined GNULIB_POSIXCHECK
# undef closedir
# if HAVE_RAW_DECL_CLOSEDIR
_GL_WARN_ON_USE (closedir, "closedir is not portable - "
"use gnulib module closedir for portability");
# endif
#endif
#if @GNULIB_DIRFD@
/* Return the file descriptor associated with the given directory stream,
or -1 if none exists. */
# if @REPLACE_DIRFD@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# undef dirfd
# define dirfd rpl_dirfd
# endif
_GL_FUNCDECL_RPL (dirfd, int, (DIR *) _GL_ARG_NONNULL ((1)));
_GL_CXXALIAS_RPL (dirfd, int, (DIR *));
# ifdef __KLIBC__
/* Gnulib internal hooks needed to maintain the dirfd metadata. */
_GL_EXTERN_C int _gl_register_dirp_fd (int fd, DIR *dirp)
_GL_ARG_NONNULL ((2));
_GL_EXTERN_C void _gl_unregister_dirp_fd (int fd);
# endif
# else
# if defined __cplusplus && defined GNULIB_NAMESPACE && defined dirfd
/* dirfd is defined as a macro and not as a function.
Turn it into a function and get rid of the macro. */
static inline int (dirfd) (DIR *dp) { return dirfd (dp); }
# undef dirfd
# endif
# if !(@HAVE_DECL_DIRFD@ || defined dirfd)
_GL_FUNCDECL_SYS (dirfd, int, (DIR *) _GL_ARG_NONNULL ((1)));
# endif
_GL_CXXALIAS_SYS (dirfd, int, (DIR *));
# endif
_GL_CXXALIASWARN (dirfd);
#elif defined GNULIB_POSIXCHECK
# undef dirfd
# if HAVE_RAW_DECL_DIRFD
_GL_WARN_ON_USE (dirfd, "dirfd is unportable - "
"use gnulib module dirfd for portability");
# endif
#endif
#if @GNULIB_FDOPENDIR@
/* Open a directory stream visiting the given directory file
descriptor. Return NULL and set errno if fd is not visiting a
directory. On success, this function consumes fd (it will be
implicitly closed either by this function or by a subsequent
closedir). */
# if @REPLACE_FDOPENDIR@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# undef fdopendir
# define fdopendir rpl_fdopendir
# endif
_GL_FUNCDECL_RPL (fdopendir, DIR *, (int fd));
_GL_CXXALIAS_RPL (fdopendir, DIR *, (int fd));
# else
# if !@HAVE_FDOPENDIR@ || !@HAVE_DECL_FDOPENDIR@
_GL_FUNCDECL_SYS (fdopendir, DIR *, (int fd));
# endif
_GL_CXXALIAS_SYS (fdopendir, DIR *, (int fd));
# endif
_GL_CXXALIASWARN (fdopendir);
#elif defined GNULIB_POSIXCHECK
# undef fdopendir
# if HAVE_RAW_DECL_FDOPENDIR
_GL_WARN_ON_USE (fdopendir, "fdopendir is unportable - "
"use gnulib module fdopendir for portability");
# endif
#endif
#if @GNULIB_SCANDIR@
/* Scan the directory DIR, calling FILTER on each directory entry.
Entries for which FILTER returns nonzero are individually malloc'd,
sorted using qsort with CMP, and collected in a malloc'd array in
*NAMELIST. Returns the number of entries selected, or -1 on error. */
# if !@HAVE_SCANDIR@
_GL_FUNCDECL_SYS (scandir, int,
(const char *dir, struct dirent ***namelist,
int (*filter) (const struct dirent *),
int (*cmp) (const struct dirent **, const struct dirent **))
_GL_ARG_NONNULL ((1, 2, 4)));
# endif
/* Need to cast, because on glibc systems, the fourth parameter is
int (*cmp) (const void *, const void *). */
_GL_CXXALIAS_SYS_CAST (scandir, int,
(const char *dir, struct dirent ***namelist,
int (*filter) (const struct dirent *),
int (*cmp) (const struct dirent **, const struct dirent **)));
_GL_CXXALIASWARN (scandir);
#elif defined GNULIB_POSIXCHECK
# undef scandir
# if HAVE_RAW_DECL_SCANDIR
_GL_WARN_ON_USE (scandir, "scandir is unportable - "
"use gnulib module scandir for portability");
# endif
#endif
#if @GNULIB_ALPHASORT@
/* Compare two 'struct dirent' entries alphabetically. */
# if !@HAVE_ALPHASORT@
_GL_FUNCDECL_SYS (alphasort, int,
(const struct dirent **, const struct dirent **)
_GL_ATTRIBUTE_PURE
_GL_ARG_NONNULL ((1, 2)));
# endif
/* Need to cast, because on glibc systems, the parameters are
(const void *, const void *). */
_GL_CXXALIAS_SYS_CAST (alphasort, int,
(const struct dirent **, const struct dirent **));
_GL_CXXALIASWARN (alphasort);
#elif defined GNULIB_POSIXCHECK
# undef alphasort
# if HAVE_RAW_DECL_ALPHASORT
_GL_WARN_ON_USE (alphasort, "alphasort is unportable - "
"use gnulib module alphasort for portability");
# endif
#endif
#endif /* _@GUARD_PREFIX@_DIRENT_H */
#endif /* _@GUARD_PREFIX@_DIRENT_H */

98
lib/dirfd.c Normal file
View File

@ -0,0 +1,98 @@
/* dirfd.c -- return the file descriptor associated with an open DIR*
Copyright (C) 2001, 2006, 2008-2018 Free Software Foundation, Inc.
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 <https://www.gnu.org/licenses/>. */
/* Written by Jim Meyering. */
#include <config.h>
#include <dirent.h>
#include <errno.h>
#ifdef __KLIBC__
# include <stdlib.h>
# include <io.h>
static struct dirp_fd_list
{
DIR *dirp;
int fd;
struct dirp_fd_list *next;
} *dirp_fd_start = NULL;
/* Register fd associated with dirp to dirp_fd_list. */
int
_gl_register_dirp_fd (int fd, DIR *dirp)
{
struct dirp_fd_list *new_dirp_fd = malloc (sizeof *new_dirp_fd);
if (!new_dirp_fd)
return -1;
new_dirp_fd->dirp = dirp;
new_dirp_fd->fd = fd;
new_dirp_fd->next = dirp_fd_start;
dirp_fd_start = new_dirp_fd;
return 0;
}
/* Unregister fd from dirp_fd_list with closing it */
void
_gl_unregister_dirp_fd (int fd)
{
struct dirp_fd_list *dirp_fd;
struct dirp_fd_list *dirp_fd_prev;
for (dirp_fd_prev = NULL, dirp_fd = dirp_fd_start; dirp_fd;
dirp_fd_prev = dirp_fd, dirp_fd = dirp_fd->next)
{
if (dirp_fd->fd == fd)
{
if (dirp_fd_prev)
dirp_fd_prev->next = dirp_fd->next;
else /* dirp_fd == dirp_fd_start */
dirp_fd_start = dirp_fd_start->next;
close (fd);
free (dirp_fd);
break;
}
}
}
#endif
int
dirfd (DIR *dir_p)
{
int fd = DIR_TO_FD (dir_p);
if (fd == -1)
#ifndef __KLIBC__
errno = ENOTSUP;
#else
{
struct dirp_fd_list *dirp_fd;
for (dirp_fd = dirp_fd_start; dirp_fd; dirp_fd = dirp_fd->next)
if (dirp_fd->dirp == dir_p)
return dirp_fd->fd;
errno = EINVAL;
}
#endif
return fd;
}

86
lib/dirname-lgpl.c Normal file
View File

@ -0,0 +1,86 @@
/* dirname.c -- return all but the last element in a file name
Copyright (C) 1990, 1998, 2000-2001, 2003-2006, 2009-2018 Free Software
Foundation, Inc.
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 <https://www.gnu.org/licenses/>. */
#include <config.h>
#include "dirname.h"
#include <stdlib.h>
#include <string.h>
/* Return the length of the prefix of FILE that will be used by
dir_name. If FILE is in the working directory, this returns zero
even though 'dir_name (FILE)' will return ".". Works properly even
if there are trailing slashes (by effectively ignoring them). */
size_t
dir_len (char const *file)
{
size_t prefix_length = FILE_SYSTEM_PREFIX_LEN (file);
size_t length;
/* Advance prefix_length beyond important leading slashes. */
prefix_length += (prefix_length != 0
? (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
&& ISSLASH (file[prefix_length]))
: (ISSLASH (file[0])
? ((DOUBLE_SLASH_IS_DISTINCT_ROOT
&& ISSLASH (file[1]) && ! ISSLASH (file[2])
? 2 : 1))
: 0));
/* Strip the basename and any redundant slashes before it. */
for (length = last_component (file) - file;
prefix_length < length; length--)
if (! ISSLASH (file[length - 1]))
break;
return length;
}
/* In general, we can't use the builtin 'dirname' function if available,
since it has different meanings in different environments.
In some environments the builtin 'dirname' modifies its argument.
Return the leading directories part of FILE, allocated with malloc.
Works properly even if there are trailing slashes (by effectively
ignoring them). Return NULL on failure.
If lstat (FILE) would succeed, then { chdir (dir_name (FILE));
lstat (base_name (FILE)); } will access the same file. Likewise,
if the sequence { chdir (dir_name (FILE));
rename (base_name (FILE), "foo"); } succeeds, you have renamed FILE
to "foo" in the same directory FILE was in. */
char *
mdir_name (char const *file)
{
size_t length = dir_len (file);
bool append_dot = (length == 0
|| (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
&& length == FILE_SYSTEM_PREFIX_LEN (file)
&& file[2] != '\0' && ! ISSLASH (file[2])));
char *dir = malloc (length + append_dot + 1);
if (!dir)
return NULL;
memcpy (dir, file, length);
if (append_dot)
dir[length++] = '.';
dir[length] = '\0';
return dir;
}

38
lib/dirname.c Normal file
View File

@ -0,0 +1,38 @@
/* dirname.c -- return all but the last element in a file name
Copyright (C) 1990, 1998, 2000-2001, 2003-2006, 2009-2018 Free Software
Foundation, Inc.
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 <https://www.gnu.org/licenses/>. */
#include <config.h>
#include "dirname.h"
#include <stdlib.h>
#include <string.h>
#include "xalloc.h"
/* Just like mdir_name (dirname-lgpl.c), except, rather than
returning NULL upon malloc failure, here, we report the
"memory exhausted" condition and exit. */
char *
dir_name (char const *file)
{
char *result = mdir_name (file);
if (!result)
xalloc_die ();
return result;
}

54
lib/dirname.h Normal file
View File

@ -0,0 +1,54 @@
/* Take file names apart into directory and base names.
Copyright (C) 1998, 2001, 2003-2006, 2009-2018 Free Software Foundation,
Inc.
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 <https://www.gnu.org/licenses/>. */
#ifndef DIRNAME_H_
# define DIRNAME_H_ 1
# include <stdbool.h>
# include <stddef.h>
# include "dosname.h"
# ifndef DIRECTORY_SEPARATOR
# define DIRECTORY_SEPARATOR '/'
# endif
# ifndef DOUBLE_SLASH_IS_DISTINCT_ROOT
# define DOUBLE_SLASH_IS_DISTINCT_ROOT 0
# endif
#ifdef __cplusplus
extern "C" {
#endif
# if GNULIB_DIRNAME
char *base_name (char const *file);
char *dir_name (char const *file);
# endif
char *mdir_name (char const *file);
size_t base_len (char const *file) _GL_ATTRIBUTE_PURE;
size_t dir_len (char const *file) _GL_ATTRIBUTE_PURE;
char *last_component (char const *file) _GL_ATTRIBUTE_PURE;
bool strip_trailing_slashes (char *file);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* not DIRNAME_H_ */

53
lib/dosname.h Normal file
View File

@ -0,0 +1,53 @@
/* File names on MS-DOS/Windows systems.
Copyright (C) 2000-2001, 2004-2006, 2009-2018 Free Software Foundation, Inc.
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 <https://www.gnu.org/licenses/>.
From Paul Eggert and Jim Meyering. */
#ifndef _DOSNAME_H
#define _DOSNAME_H
#if (defined _WIN32 || defined __WIN32__ || \
defined __MSDOS__ || defined __CYGWIN__ || \
defined __EMX__ || defined __DJGPP__)
/* This internal macro assumes ASCII, but all hosts that support drive
letters use ASCII. */
# define _IS_DRIVE_LETTER(C) (((unsigned int) (C) | ('a' - 'A')) - 'a' \
<= 'z' - 'a')
# define FILE_SYSTEM_PREFIX_LEN(Filename) \
(_IS_DRIVE_LETTER ((Filename)[0]) && (Filename)[1] == ':' ? 2 : 0)
# ifndef __CYGWIN__
# define FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE 1
# endif
# define ISSLASH(C) ((C) == '/' || (C) == '\\')
#else
# define FILE_SYSTEM_PREFIX_LEN(Filename) 0
# define ISSLASH(C) ((C) == '/')
#endif
#ifndef FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
# define FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE 0
#endif
#if FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
# define IS_ABSOLUTE_FILE_NAME(F) ISSLASH ((F)[FILE_SYSTEM_PREFIX_LEN (F)])
# else
# define IS_ABSOLUTE_FILE_NAME(F) \
(ISSLASH ((F)[0]) || FILE_SYSTEM_PREFIX_LEN (F) != 0)
#endif
#define IS_RELATIVE_FILE_NAME(F) (! IS_ABSOLUTE_FILE_NAME (F))
#endif /* DOSNAME_H_ */

38
lib/dup-safer-flag.c Normal file
View File

@ -0,0 +1,38 @@
/* Duplicate a file descriptor result, avoiding clobbering
STD{IN,OUT,ERR}_FILENO, with specific flags.
Copyright (C) 2001, 2004-2006, 2009-2018 Free Software Foundation, Inc.
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 <https://www.gnu.org/licenses/>. */
/* Written by Paul Eggert and Eric Blake. */
#include <config.h>
/* Specification. */
#include "unistd-safer.h"
#include <fcntl.h>
#include <unistd.h>
/* Like dup, but do not return STDIN_FILENO, STDOUT_FILENO, or
STDERR_FILENO. If FLAG contains O_CLOEXEC, behave like
fcntl(F_DUPFD_CLOEXEC) rather than fcntl(F_DUPFD). */
int
dup_safer_flag (int fd, int flag)
{
return fcntl (fd, (flag & O_CLOEXEC) ? F_DUPFD_CLOEXEC : F_DUPFD,
STDERR_FILENO + 1);
}

34
lib/dup-safer.c Normal file
View File

@ -0,0 +1,34 @@
/* Invoke dup, but avoid some glitches.
Copyright (C) 2001, 2004-2006, 2009-2018 Free Software Foundation, Inc.
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 <https://www.gnu.org/licenses/>. */
/* Written by Paul Eggert. */
#include <config.h>
#include "unistd-safer.h"
#include <fcntl.h>
#include <unistd.h>
/* Like dup, but do not return STDIN_FILENO, STDOUT_FILENO, or
STDERR_FILENO. */
int
dup_safer (int fd)
{
return fcntl (fd, F_DUPFD, STDERR_FILENO + 1);
}

235
lib/dup2.c Normal file
View File

@ -0,0 +1,235 @@
/* Duplicate an open file descriptor to a specified file descriptor.
Copyright (C) 1999, 2004-2007, 2009-2018 Free Software Foundation, Inc.
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 <https://www.gnu.org/licenses/>. */
/* written by Paul Eggert */
#include <config.h>
/* Specification. */
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#if HAVE_DUP2
# undef dup2
# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
/* Get declarations of the native Windows API functions. */
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
# if HAVE_MSVC_INVALID_PARAMETER_HANDLER
# include "msvc-inval.h"
# endif
/* Get _get_osfhandle. */
# if GNULIB_MSVC_NOTHROW
# include "msvc-nothrow.h"
# else
# include <io.h>
# endif
# if HAVE_MSVC_INVALID_PARAMETER_HANDLER
static int
dup2_nothrow (int fd, int desired_fd)
{
int result;
TRY_MSVC_INVAL
{
result = dup2 (fd, desired_fd);
}
CATCH_MSVC_INVAL
{
errno = EBADF;
result = -1;
}
DONE_MSVC_INVAL;
return result;
}
# else
# define dup2_nothrow dup2
# endif
static int
ms_windows_dup2 (int fd, int desired_fd)
{
int result;
/* If fd is closed, mingw hangs on dup2 (fd, fd). If fd is open,
dup2 (fd, fd) returns 0, but all further attempts to use fd in
future dup2 calls will hang. */
if (fd == desired_fd)
{
if ((HANDLE) _get_osfhandle (fd) == INVALID_HANDLE_VALUE)
{
errno = EBADF;
return -1;
}
return fd;
}
/* Wine 1.0.1 return 0 when desired_fd is negative but not -1:
https://bugs.winehq.org/show_bug.cgi?id=21289 */
if (desired_fd < 0)
{
errno = EBADF;
return -1;
}
result = dup2_nothrow (fd, desired_fd);
if (result == 0)
result = desired_fd;
return result;
}
# define dup2 ms_windows_dup2
# elif defined __KLIBC__
# include <InnoTekLIBC/backend.h>
static int
klibc_dup2dirfd (int fd, int desired_fd)
{
int tempfd;
int dupfd;
tempfd = open ("NUL", O_RDONLY);
if (tempfd == -1)
return -1;
if (tempfd == desired_fd)
{
close (tempfd);
char path[_MAX_PATH];
if (__libc_Back_ioFHToPath (fd, path, sizeof (path)))
return -1;
return open(path, O_RDONLY);
}
dupfd = klibc_dup2dirfd (fd, desired_fd);
close (tempfd);
return dupfd;
}
static int
klibc_dup2 (int fd, int desired_fd)
{
int dupfd;
struct stat sbuf;
dupfd = dup2 (fd, desired_fd);
if (dupfd == -1 && errno == ENOTSUP \
&& !fstat (fd, &sbuf) && S_ISDIR (sbuf.st_mode))
{
close (desired_fd);
return klibc_dup2dirfd (fd, desired_fd);
}
return dupfd;
}
# define dup2 klibc_dup2
# endif
int
rpl_dup2 (int fd, int desired_fd)
{
int result;
# ifdef F_GETFL
/* On Linux kernels 2.6.26-2.6.29, dup2 (fd, fd) returns -EBADF.
On Cygwin 1.5.x, dup2 (1, 1) returns 0.
On Cygwin 1.7.17, dup2 (1, -1) dumps core.
On Cygwin 1.7.25, dup2 (1, 256) can dump core.
On Haiku, dup2 (fd, fd) mistakenly clears FD_CLOEXEC. */
# if HAVE_SETDTABLESIZE
setdtablesize (desired_fd + 1);
# endif
if (desired_fd < 0)
fd = desired_fd;
if (fd == desired_fd)
return fcntl (fd, F_GETFL) == -1 ? -1 : fd;
# endif
result = dup2 (fd, desired_fd);
/* Correct an errno value on FreeBSD 6.1 and Cygwin 1.5.x. */
if (result == -1 && errno == EMFILE)
errno = EBADF;
# if REPLACE_FCHDIR
if (fd != desired_fd && result != -1)
result = _gl_register_dup (fd, result);
# endif
return result;
}
#else /* !HAVE_DUP2 */
/* On older platforms, dup2 did not exist. */
# ifndef F_DUPFD
static int
dupfd (int fd, int desired_fd)
{
int duplicated_fd = dup (fd);
if (duplicated_fd < 0 || duplicated_fd == desired_fd)
return duplicated_fd;
else
{
int r = dupfd (fd, desired_fd);
int e = errno;
close (duplicated_fd);
errno = e;
return r;
}
}
# endif
int
dup2 (int fd, int desired_fd)
{
int result = fcntl (fd, F_GETFL) < 0 ? -1 : fd;
if (result == -1 || fd == desired_fd)
return result;
close (desired_fd);
# ifdef F_DUPFD
result = fcntl (fd, F_DUPFD, desired_fd);
# if REPLACE_FCHDIR
if (0 <= result)
result = _gl_register_dup (fd, result);
# endif
# else
result = dupfd (fd, desired_fd);
# endif
if (result == -1 && (errno == EMFILE || errno == EINVAL))
errno = EBADF;
return result;
}
#endif /* !HAVE_DUP2 */

279
lib/errno.in.h Normal file
View File

@ -0,0 +1,279 @@
/* A POSIX-like <errno.h>.
Copyright (C) 2008-2018 Free Software Foundation, Inc.
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, 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 <https://www.gnu.org/licenses/>. */
#ifndef _@GUARD_PREFIX@_ERRNO_H
#if __GNUC__ >= 3
@PRAGMA_SYSTEM_HEADER@
#endif
@PRAGMA_COLUMNS@
/* The include_next requires a split double-inclusion guard. */
#@INCLUDE_NEXT@ @NEXT_ERRNO_H@
#ifndef _@GUARD_PREFIX@_ERRNO_H
#define _@GUARD_PREFIX@_ERRNO_H
/* On native Windows platforms, many macros are not defined. */
# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
/* These are the same values as defined by MSVC 10, for interoperability. */
# ifndef ENOMSG
# define ENOMSG 122
# define GNULIB_defined_ENOMSG 1
# endif
# ifndef EIDRM
# define EIDRM 111
# define GNULIB_defined_EIDRM 1
# endif
# ifndef ENOLINK
# define ENOLINK 121
# define GNULIB_defined_ENOLINK 1
# endif
# ifndef EPROTO
# define EPROTO 134
# define GNULIB_defined_EPROTO 1
# endif
# ifndef EBADMSG
# define EBADMSG 104
# define GNULIB_defined_EBADMSG 1
# endif
# ifndef EOVERFLOW
# define EOVERFLOW 132
# define GNULIB_defined_EOVERFLOW 1
# endif
# ifndef ENOTSUP
# define ENOTSUP 129
# define GNULIB_defined_ENOTSUP 1
# endif
# ifndef ENETRESET
# define ENETRESET 117
# define GNULIB_defined_ENETRESET 1
# endif
# ifndef ECONNABORTED
# define ECONNABORTED 106
# define GNULIB_defined_ECONNABORTED 1
# endif
# ifndef ECANCELED
# define ECANCELED 105
# define GNULIB_defined_ECANCELED 1
# endif
# ifndef EOWNERDEAD
# define EOWNERDEAD 133
# define GNULIB_defined_EOWNERDEAD 1
# endif
# ifndef ENOTRECOVERABLE
# define ENOTRECOVERABLE 127
# define GNULIB_defined_ENOTRECOVERABLE 1
# endif
# ifndef EINPROGRESS
# define EINPROGRESS 112
# define EALREADY 103
# define ENOTSOCK 128
# define EDESTADDRREQ 109
# define EMSGSIZE 115
# define EPROTOTYPE 136
# define ENOPROTOOPT 123
# define EPROTONOSUPPORT 135
# define EOPNOTSUPP 130
# define EAFNOSUPPORT 102
# define EADDRINUSE 100
# define EADDRNOTAVAIL 101
# define ENETDOWN 116
# define ENETUNREACH 118
# define ECONNRESET 108
# define ENOBUFS 119
# define EISCONN 113
# define ENOTCONN 126
# define ETIMEDOUT 138
# define ECONNREFUSED 107
# define ELOOP 114
# define EHOSTUNREACH 110
# define EWOULDBLOCK 140
# define GNULIB_defined_ESOCK 1
# endif
# ifndef ETXTBSY
# define ETXTBSY 139
# define ENODATA 120 /* not required by POSIX */
# define ENOSR 124 /* not required by POSIX */
# define ENOSTR 125 /* not required by POSIX */
# define ETIME 137 /* not required by POSIX */
# define EOTHER 131 /* not required by POSIX */
# define GNULIB_defined_ESTREAMS 1
# endif
/* These are intentionally the same values as the WSA* error numbers, defined
in <winsock2.h>. */
# define ESOCKTNOSUPPORT 10044 /* not required by POSIX */
# define EPFNOSUPPORT 10046 /* not required by POSIX */
# define ESHUTDOWN 10058 /* not required by POSIX */
# define ETOOMANYREFS 10059 /* not required by POSIX */
# define EHOSTDOWN 10064 /* not required by POSIX */
# define EPROCLIM 10067 /* not required by POSIX */
# define EUSERS 10068 /* not required by POSIX */
# define EDQUOT 10069
# define ESTALE 10070
# define EREMOTE 10071 /* not required by POSIX */
# define GNULIB_defined_EWINSOCK 1
# endif
/* On OSF/1 5.1, when _XOPEN_SOURCE_EXTENDED is not defined, the macros
EMULTIHOP, ENOLINK, EOVERFLOW are not defined. */
# if @EMULTIHOP_HIDDEN@
# define EMULTIHOP @EMULTIHOP_VALUE@
# define GNULIB_defined_EMULTIHOP 1
# endif
# if @ENOLINK_HIDDEN@
# define ENOLINK @ENOLINK_VALUE@
# define GNULIB_defined_ENOLINK 1
# endif
# if @EOVERFLOW_HIDDEN@
# define EOVERFLOW @EOVERFLOW_VALUE@
# define GNULIB_defined_EOVERFLOW 1
# endif
/* On OpenBSD 4.0 and on native Windows, the macros ENOMSG, EIDRM, ENOLINK,
EPROTO, EMULTIHOP, EBADMSG, EOVERFLOW, ENOTSUP, ECANCELED are not defined.
Likewise, on NonStop Kernel, EDQUOT is not defined.
Define them here. Values >= 2000 seem safe to use: Solaris ESTALE = 151,
HP-UX EWOULDBLOCK = 246, IRIX EDQUOT = 1133.
Note: When one of these systems defines some of these macros some day,
binaries will have to be recompiled so that they recognizes the new
errno values from the system. */
# ifndef ENOMSG
# define ENOMSG 2000
# define GNULIB_defined_ENOMSG 1
# endif
# ifndef EIDRM
# define EIDRM 2001
# define GNULIB_defined_EIDRM 1
# endif
# ifndef ENOLINK
# define ENOLINK 2002
# define GNULIB_defined_ENOLINK 1
# endif
# ifndef EPROTO
# define EPROTO 2003
# define GNULIB_defined_EPROTO 1
# endif
# ifndef EMULTIHOP
# define EMULTIHOP 2004
# define GNULIB_defined_EMULTIHOP 1
# endif
# ifndef EBADMSG
# define EBADMSG 2005
# define GNULIB_defined_EBADMSG 1
# endif
# ifndef EOVERFLOW
# define EOVERFLOW 2006
# define GNULIB_defined_EOVERFLOW 1
# endif
# ifndef ENOTSUP
# define ENOTSUP 2007
# define GNULIB_defined_ENOTSUP 1
# endif
# ifndef ENETRESET
# define ENETRESET 2011
# define GNULIB_defined_ENETRESET 1
# endif
# ifndef ECONNABORTED
# define ECONNABORTED 2012
# define GNULIB_defined_ECONNABORTED 1
# endif
# ifndef ESTALE
# define ESTALE 2009
# define GNULIB_defined_ESTALE 1
# endif
# ifndef EDQUOT
# define EDQUOT 2010
# define GNULIB_defined_EDQUOT 1
# endif
# ifndef ECANCELED
# define ECANCELED 2008
# define GNULIB_defined_ECANCELED 1
# endif
/* On many platforms, the macros EOWNERDEAD and ENOTRECOVERABLE are not
defined. */
# ifndef EOWNERDEAD
# if defined __sun
/* Use the same values as defined for Solaris >= 8, for
interoperability. */
# define EOWNERDEAD 58
# define ENOTRECOVERABLE 59
# elif (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
/* We have a conflict here: pthreads-win32 defines these values
differently than MSVC 10. It's hairy to decide which one to use. */
# if defined __MINGW32__ && !defined USE_WINDOWS_THREADS
/* Use the same values as defined by pthreads-win32, for
interoperability. */
# define EOWNERDEAD 43
# define ENOTRECOVERABLE 44
# else
/* Use the same values as defined by MSVC 10, for
interoperability. */
# define EOWNERDEAD 133
# define ENOTRECOVERABLE 127
# endif
# else
# define EOWNERDEAD 2013
# define ENOTRECOVERABLE 2014
# endif
# define GNULIB_defined_EOWNERDEAD 1
# define GNULIB_defined_ENOTRECOVERABLE 1
# endif
# ifndef EILSEQ
# define EILSEQ 2015
# define GNULIB_defined_EILSEQ 1
# endif
#endif /* _@GUARD_PREFIX@_ERRNO_H */
#endif /* _@GUARD_PREFIX@_ERRNO_H */

411
lib/error.c Normal file
View File

@ -0,0 +1,411 @@
/* Error handler for noninteractive utilities
Copyright (C) 1990-1998, 2000-2007, 2009-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
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 <https://www.gnu.org/licenses/>. */
/* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */
#if !_LIBC
# include <config.h>
#endif
#include "error.h"
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if !_LIBC && ENABLE_NLS
# include "gettext.h"
# define _(msgid) gettext (msgid)
#endif
#ifdef _LIBC
# include <libintl.h>
# include <stdbool.h>
# include <stdint.h>
# include <wchar.h>
# define mbsrtowcs __mbsrtowcs
# define USE_UNLOCKED_IO 0
# define _GL_ATTRIBUTE_FORMAT_PRINTF(a, b)
# define _GL_ARG_NONNULL(a)
#else
# include "getprogname.h"
#endif
#if USE_UNLOCKED_IO
# include "unlocked-io.h"
#endif
#ifndef _
# define _(String) String
#endif
/* If NULL, error will flush stdout, then print on stderr the program
name, a colon and a space. Otherwise, error will call this
function without parameters instead. */
void (*error_print_progname) (void);
/* This variable is incremented each time 'error' is called. */
unsigned int error_message_count;
#ifdef _LIBC
/* In the GNU C library, there is a predefined variable for this. */
# define program_name program_invocation_name
# include <errno.h>
# include <limits.h>
# include <libio/libioP.h>
/* In GNU libc we want do not want to use the common name 'error' directly.
Instead make it a weak alias. */
extern void __error (int status, int errnum, const char *message, ...)
__attribute__ ((__format__ (__printf__, 3, 4)));
extern void __error_at_line (int status, int errnum, const char *file_name,
unsigned int line_number, const char *message,
...)
__attribute__ ((__format__ (__printf__, 5, 6)));
# define error __error
# define error_at_line __error_at_line
# include <libio/iolibio.h>
# define fflush(s) _IO_fflush (s)
# undef putc
# define putc(c, fp) _IO_putc (c, fp)
# include <bits/libc-lock.h>
#else /* not _LIBC */
# include <fcntl.h>
# include <unistd.h>
# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
/* Get declarations of the native Windows API functions. */
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
/* Get _get_osfhandle. */
# if GNULIB_MSVC_NOTHROW
# include "msvc-nothrow.h"
# else
# include <io.h>
# endif
# endif
/* The gnulib override of fcntl is not needed in this file. */
# undef fcntl
# if !(GNULIB_STRERROR_R_POSIX || HAVE_DECL_STRERROR_R)
# ifndef HAVE_DECL_STRERROR_R
"this configure-time declaration test was not run"
# endif
# if STRERROR_R_CHAR_P
char *strerror_r (int errnum, char *buf, size_t buflen);
# else
int strerror_r (int errnum, char *buf, size_t buflen);
# endif
# endif
#define program_name getprogname ()
# if GNULIB_STRERROR_R_POSIX || HAVE_STRERROR_R || defined strerror_r
# define __strerror_r strerror_r
# endif /* GNULIB_STRERROR_R_POSIX || HAVE_STRERROR_R || defined strerror_r */
#endif /* not _LIBC */
#if !_LIBC
/* Return non-zero if FD is open. */
static int
is_open (int fd)
{
# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
/* On native Windows: The initial state of unassigned standard file
descriptors is that they are open but point to an INVALID_HANDLE_VALUE.
There is no fcntl, and the gnulib replacement fcntl does not support
F_GETFL. */
return (HANDLE) _get_osfhandle (fd) != INVALID_HANDLE_VALUE;
# else
# ifndef F_GETFL
# error Please port fcntl to your platform
# endif
return 0 <= fcntl (fd, F_GETFL);
# endif
}
#endif
static void
flush_stdout (void)
{
#if !_LIBC
int stdout_fd;
# if GNULIB_FREOPEN_SAFER
/* Use of gnulib's freopen-safer module normally ensures that
fileno (stdout) == 1
whenever stdout is open. */
stdout_fd = STDOUT_FILENO;
# else
/* POSIX states that fileno (stdout) after fclose is unspecified. But in
practice it is not a problem, because stdout is statically allocated and
the fd of a FILE stream is stored as a field in its allocated memory. */
stdout_fd = fileno (stdout);
# endif
/* POSIX states that fflush (stdout) after fclose is unspecified; it
is safe in glibc, but not on all other platforms. fflush (NULL)
is always defined, but too draconian. */
if (0 <= stdout_fd && is_open (stdout_fd))
#endif
fflush (stdout);
}
static void
print_errno_message (int errnum)
{
char const *s;
#if _LIBC || GNULIB_STRERROR_R_POSIX || defined HAVE_STRERROR_R
char errbuf[1024];
# if _LIBC || (!GNULIB_STRERROR_R_POSIX && STRERROR_R_CHAR_P)
s = __strerror_r (errnum, errbuf, sizeof errbuf);
# else
if (__strerror_r (errnum, errbuf, sizeof errbuf) == 0)
s = errbuf;
else
s = 0;
# endif
#else
s = strerror (errnum);
#endif
#if !_LIBC
if (! s)
s = _("Unknown system error");
#endif
#if _LIBC
__fxprintf (NULL, ": %s", s);
#else
fprintf (stderr, ": %s", s);
#endif
}
static void _GL_ATTRIBUTE_FORMAT_PRINTF (3, 0) _GL_ARG_NONNULL ((3))
error_tail (int status, int errnum, const char *message, va_list args)
{
#if _LIBC
if (_IO_fwide (stderr, 0) > 0)
{
size_t len = strlen (message) + 1;
wchar_t *wmessage = NULL;
mbstate_t st;
size_t res;
const char *tmp;
bool use_malloc = false;
while (1)
{
if (__libc_use_alloca (len * sizeof (wchar_t)))
wmessage = (wchar_t *) alloca (len * sizeof (wchar_t));
else
{
if (!use_malloc)
wmessage = NULL;
wchar_t *p = (wchar_t *) realloc (wmessage,
len * sizeof (wchar_t));
if (p == NULL)
{
free (wmessage);
fputws_unlocked (L"out of memory\n", stderr);
return;
}
wmessage = p;
use_malloc = true;
}
memset (&st, '\0', sizeof (st));
tmp = message;
res = mbsrtowcs (wmessage, &tmp, len, &st);
if (res != len)
break;
if (__builtin_expect (len >= SIZE_MAX / sizeof (wchar_t) / 2, 0))
{
/* This really should not happen if everything is fine. */
res = (size_t) -1;
break;
}
len *= 2;
}
if (res == (size_t) -1)
{
/* The string cannot be converted. */
if (use_malloc)
{
free (wmessage);
use_malloc = false;
}
wmessage = (wchar_t *) L"???";
}
__vfwprintf (stderr, wmessage, args);
if (use_malloc)
free (wmessage);
}
else
#endif
vfprintf (stderr, message, args);
++error_message_count;
if (errnum)
print_errno_message (errnum);
#if _LIBC
__fxprintf (NULL, "\n");
#else
putc ('\n', stderr);
#endif
fflush (stderr);
if (status)
exit (status);
}
/* Print the program name and error message MESSAGE, which is a printf-style
format string with optional args.
If ERRNUM is nonzero, print its corresponding system error message.
Exit with status STATUS if it is nonzero. */
void
error (int status, int errnum, const char *message, ...)
{
va_list args;
#if defined _LIBC && defined __libc_ptf_call
/* We do not want this call to be cut short by a thread
cancellation. Therefore disable cancellation for now. */
int state = PTHREAD_CANCEL_ENABLE;
__libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state),
0);
#endif
flush_stdout ();
#ifdef _LIBC
_IO_flockfile (stderr);
#endif
if (error_print_progname)
(*error_print_progname) ();
else
{
#if _LIBC
__fxprintf (NULL, "%s: ", program_name);
#else
fprintf (stderr, "%s: ", program_name);
#endif
}
va_start (args, message);
error_tail (status, errnum, message, args);
va_end (args);
#ifdef _LIBC
_IO_funlockfile (stderr);
# ifdef __libc_ptf_call
__libc_ptf_call (pthread_setcancelstate, (state, NULL), 0);
# endif
#endif
}
/* Sometimes we want to have at most one error per line. This
variable controls whether this mode is selected or not. */
int error_one_per_line;
void
error_at_line (int status, int errnum, const char *file_name,
unsigned int line_number, const char *message, ...)
{
va_list args;
if (error_one_per_line)
{
static const char *old_file_name;
static unsigned int old_line_number;
if (old_line_number == line_number
&& (file_name == old_file_name
|| (old_file_name != NULL
&& file_name != NULL
&& strcmp (old_file_name, file_name) == 0)))
/* Simply return and print nothing. */
return;
old_file_name = file_name;
old_line_number = line_number;
}
#if defined _LIBC && defined __libc_ptf_call
/* We do not want this call to be cut short by a thread
cancellation. Therefore disable cancellation for now. */
int state = PTHREAD_CANCEL_ENABLE;
__libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state),
0);
#endif
flush_stdout ();
#ifdef _LIBC
_IO_flockfile (stderr);
#endif
if (error_print_progname)
(*error_print_progname) ();
else
{
#if _LIBC
__fxprintf (NULL, "%s:", program_name);
#else
fprintf (stderr, "%s:", program_name);
#endif
}
#if _LIBC
__fxprintf (NULL, file_name != NULL ? "%s:%u: " : " ",
file_name, line_number);
#else
fprintf (stderr, file_name != NULL ? "%s:%u: " : " ",
file_name, line_number);
#endif
va_start (args, message);
error_tail (status, errnum, message, args);
va_end (args);
#ifdef _LIBC
_IO_funlockfile (stderr);
# ifdef __libc_ptf_call
__libc_ptf_call (pthread_setcancelstate, (state, NULL), 0);
# endif
#endif
}
#ifdef _LIBC
/* Make the weak alias. */
# undef error
# undef error_at_line
weak_alias (__error, error)
weak_alias (__error_at_line, error_at_line)
#endif

75
lib/error.h Normal file
View File

@ -0,0 +1,75 @@
/* Declaration for error-reporting function
Copyright (C) 1995-1997, 2003, 2006, 2008-2018 Free Software Foundation,
Inc.
This file is part of the GNU C Library.
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 <https://www.gnu.org/licenses/>. */
#ifndef _ERROR_H
#define _ERROR_H 1
/* The __attribute__ feature is available in gcc versions 2.5 and later.
The __-protected variants of the attributes 'format' and 'printf' are
accepted by gcc versions 2.6.4 (effectively 2.7) and later.
We enable _GL_ATTRIBUTE_FORMAT only if these are supported too, because
gnulib and libintl do '#define printf __printf__' when they override
the 'printf' function. */
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7)
# define _GL_ATTRIBUTE_FORMAT(spec) __attribute__ ((__format__ spec))
#else
# define _GL_ATTRIBUTE_FORMAT(spec) /* empty */
#endif
/* On mingw, the flavor of printf depends on whether the extensions module
* is in use; the check for <stdio.h> determines the witness macro. */
#ifndef _GL_ATTRIBUTE_SPEC_PRINTF
# if GNULIB_PRINTF_ATTRIBUTE_FLAVOR_GNU
# define _GL_ATTRIBUTE_SPEC_PRINTF __gnu_printf__
# else
# define _GL_ATTRIBUTE_SPEC_PRINTF __printf__
# endif
#endif
#ifdef __cplusplus
extern "C" {
#endif
/* Print a message with 'fprintf (stderr, FORMAT, ...)';
if ERRNUM is nonzero, follow it with ": " and strerror (ERRNUM).
If STATUS is nonzero, terminate the program with 'exit (STATUS)'. */
extern void error (int __status, int __errnum, const char *__format, ...)
_GL_ATTRIBUTE_FORMAT ((_GL_ATTRIBUTE_SPEC_PRINTF, 3, 4));
extern void error_at_line (int __status, int __errnum, const char *__fname,
unsigned int __lineno, const char *__format, ...)
_GL_ATTRIBUTE_FORMAT ((_GL_ATTRIBUTE_SPEC_PRINTF, 5, 6));
/* If NULL, error will flush stdout, then print on stderr the program
name, a colon and a space. Otherwise, error will call this
function without parameters instead. */
extern void (*error_print_progname) (void);
/* This variable is incremented each time 'error' is called. */
extern unsigned int error_message_count;
/* Sometimes we want to have at most one error per line. This
variable controls whether this mode is selected or not. */
extern int error_one_per_line;
#ifdef __cplusplus
}
#endif
#endif /* error.h */

218
lib/euidaccess.c Normal file
View File

@ -0,0 +1,218 @@
/* euidaccess -- check if effective user id can access file
Copyright (C) 1990-1991, 1995, 1998, 2000, 2003-2006, 2008-2018 Free
Software Foundation, Inc.
This file is part of the GNU C Library.
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 <https://www.gnu.org/licenses/>. */
/* Written by David MacKenzie and Torbjorn Granlund.
Adapted for GNU C library by Roland McGrath. */
#ifndef _LIBC
# include <config.h>
#endif
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include "root-uid.h"
#if HAVE_LIBGEN_H
# include <libgen.h>
#endif
#include <errno.h>
#ifndef __set_errno
# define __set_errno(val) errno = (val)
#endif
#if defined EACCES && !defined EACCESS
# define EACCESS EACCES
#endif
#ifndef F_OK
# define F_OK 0
# define X_OK 1
# define W_OK 2
# define R_OK 4
#endif
#ifdef _LIBC
# define access __access
# define getuid __getuid
# define getgid __getgid
# define geteuid __geteuid
# define getegid __getegid
# define group_member __group_member
# define euidaccess __euidaccess
# undef stat
# define stat stat64
#endif
/* Return 0 if the user has permission of type MODE on FILE;
otherwise, return -1 and set 'errno'.
Like access, except that it uses the effective user and group
id's instead of the real ones, and it does not always check for read-only
file system, text busy, etc. */
int
euidaccess (const char *file, int mode)
{
#if HAVE_FACCESSAT /* glibc, AIX 7, Solaris 11, Cygwin 1.7 */
return faccessat (AT_FDCWD, file, mode, AT_EACCESS);
#elif defined EFF_ONLY_OK /* IRIX, OSF/1, Interix */
return access (file, mode | EFF_ONLY_OK);
#elif defined ACC_SELF /* AIX */
return accessx (file, mode, ACC_SELF);
#elif HAVE_EACCESS /* FreeBSD */
return eaccess (file, mode);
#else /* Mac OS X, NetBSD, OpenBSD, HP-UX, Solaris, Cygwin, mingw, BeOS */
uid_t uid = getuid ();
gid_t gid = getgid ();
uid_t euid = geteuid ();
gid_t egid = getegid ();
struct stat stats;
# if HAVE_DECL_SETREGID && PREFER_NONREENTRANT_EUIDACCESS
/* Define PREFER_NONREENTRANT_EUIDACCESS if you prefer euidaccess to
return the correct result even if this would make it
nonreentrant. Define this only if your entire application is
safe even if the uid or gid might temporarily change. If your
application uses signal handlers or threads it is probably not
safe. */
if (mode == F_OK)
return stat (file, &stats);
else
{
int result;
int saved_errno;
if (uid != euid)
setreuid (euid, uid);
if (gid != egid)
setregid (egid, gid);
result = access (file, mode);
saved_errno = errno;
/* Restore them. */
if (uid != euid)
setreuid (uid, euid);
if (gid != egid)
setregid (gid, egid);
errno = saved_errno;
return result;
}
# else
/* The following code assumes the traditional Unix model, and is not
correct on systems that have ACLs or the like. However, it's
better than nothing, and it is reentrant. */
unsigned int granted;
if (uid == euid && gid == egid)
/* If we are not set-uid or set-gid, access does the same. */
return access (file, mode);
if (stat (file, &stats) != 0)
return -1;
/* The super-user can read and write any file, and execute any file
that anyone can execute. */
if (euid == ROOT_UID
&& ((mode & X_OK) == 0
|| (stats.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))))
return 0;
/* Convert the mode to traditional form, clearing any bogus bits. */
if (R_OK == 4 && W_OK == 2 && X_OK == 1 && F_OK == 0)
mode &= 7;
else
mode = ((mode & R_OK ? 4 : 0)
+ (mode & W_OK ? 2 : 0)
+ (mode & X_OK ? 1 : 0));
if (mode == 0)
return 0; /* The file exists. */
/* Convert the file's permission bits to traditional form. */
if (S_IRUSR == (4 << 6) && S_IWUSR == (2 << 6) && S_IXUSR == (1 << 6)
&& S_IRGRP == (4 << 3) && S_IWGRP == (2 << 3) && S_IXGRP == (1 << 3)
&& S_IROTH == (4 << 0) && S_IWOTH == (2 << 0) && S_IXOTH == (1 << 0))
granted = stats.st_mode;
else
granted = ((stats.st_mode & S_IRUSR ? 4 << 6 : 0)
+ (stats.st_mode & S_IWUSR ? 2 << 6 : 0)
+ (stats.st_mode & S_IXUSR ? 1 << 6 : 0)
+ (stats.st_mode & S_IRGRP ? 4 << 3 : 0)
+ (stats.st_mode & S_IWGRP ? 2 << 3 : 0)
+ (stats.st_mode & S_IXGRP ? 1 << 3 : 0)
+ (stats.st_mode & S_IROTH ? 4 << 0 : 0)
+ (stats.st_mode & S_IWOTH ? 2 << 0 : 0)
+ (stats.st_mode & S_IXOTH ? 1 << 0 : 0));
if (euid == stats.st_uid)
granted >>= 6;
else if (egid == stats.st_gid || group_member (stats.st_gid))
granted >>= 3;
if ((mode & ~granted) == 0)
return 0;
__set_errno (EACCESS);
return -1;
# endif
#endif
}
#undef euidaccess
#ifdef weak_alias
weak_alias (__euidaccess, euidaccess)
#endif
#ifdef TEST
# include <error.h>
# include <stdio.h>
# include <stdlib.h>
int
main (int argc, char **argv)
{
char *file;
int mode;
int err;
if (argc < 3)
abort ();
file = argv[1];
mode = atoi (argv[2]);
err = euidaccess (file, mode);
printf ("%d\n", err);
if (err != 0)
error (0, errno, "%s", file);
exit (0);
}
#endif

24
lib/exitfail.c Normal file
View File

@ -0,0 +1,24 @@
/* Failure exit status
Copyright (C) 2002-2003, 2005-2007, 2009-2018 Free Software Foundation, Inc.
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 <https://www.gnu.org/licenses/>. */
#include <config.h>
#include "exitfail.h"
#include <stdlib.h>
int volatile exit_failure = EXIT_FAILURE;

18
lib/exitfail.h Normal file
View File

@ -0,0 +1,18 @@
/* Failure exit status
Copyright (C) 2002, 2009-2018 Free Software Foundation, Inc.
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 <https://www.gnu.org/licenses/>. */
extern int volatile exit_failure;

91
lib/faccessat.c Normal file
View File

@ -0,0 +1,91 @@
/* Check the access rights of a file relative to an open directory.
Copyright (C) 2009-2018 Free Software Foundation, Inc.
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 <https://www.gnu.org/licenses/>. */
/* written by Eric Blake */
/* If the user's config.h happens to include <unistd.h>, let it include only
the system's <unistd.h> here, so that orig_faccessat doesn't recurse to
rpl_faccessat. */
#define _GL_INCLUDING_UNISTD_H
#include <config.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <sys/stat.h>
#undef _GL_INCLUDING_UNISTD_H
#if HAVE_FACCESSAT
static int
orig_faccessat (int fd, char const *name, int mode, int flag)
{
return faccessat (fd, name, mode, flag);
}
#endif
/* Write "unistd.h" here, not <unistd.h>, otherwise OSF/1 5.1 DTK cc
eliminates this include because of the preliminary #include <unistd.h>
above. */
#include "unistd.h"
#ifndef HAVE_ACCESS
/* Mingw lacks access, but it also lacks real vs. effective ids, so
the gnulib euidaccess module is good enough. */
# undef access
# define access euidaccess
#endif
#if HAVE_FACCESSAT
int
rpl_faccessat (int fd, char const *file, int mode, int flag)
{
int result = orig_faccessat (fd, file, mode, flag);
if (result == 0 && file[strlen (file) - 1] == '/')
{
struct stat st;
result = fstatat (fd, file, &st, 0);
if (result == 0 && !S_ISDIR (st.st_mode))
{
errno = ENOTDIR;
return -1;
}
}
return result;
}
#else /* !HAVE_FACCESSAT */
/* Invoke access or euidaccess on file, FILE, using mode MODE, in the directory
open on descriptor FD. If possible, do it without changing the
working directory. Otherwise, resort to using save_cwd/fchdir, then
(access|euidaccess)/restore_cwd. If either the save_cwd or the
restore_cwd fails, then give a diagnostic and exit nonzero.
Note that this implementation only supports AT_EACCESS, although some
native versions also support AT_SYMLINK_NOFOLLOW. */
# define AT_FUNC_NAME faccessat
# define AT_FUNC_F1 euidaccess
# define AT_FUNC_F2 access
# define AT_FUNC_USE_F1_COND AT_EACCESS
# define AT_FUNC_POST_FILE_PARAM_DECLS , int mode, int flag
# define AT_FUNC_POST_FILE_ARGS , mode
# include "at-func.c"
#endif

208
lib/fchdir.c Normal file
View File

@ -0,0 +1,208 @@
/* fchdir replacement.
Copyright (C) 2006-2018 Free Software Foundation, Inc.
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 <https://www.gnu.org/licenses/>. */
#include <config.h>
/* Specification. */
#include <unistd.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "assure.h"
#include "dosname.h"
#include "filenamecat.h"
#ifndef REPLACE_OPEN_DIRECTORY
# define REPLACE_OPEN_DIRECTORY 0
#endif
/* This replacement assumes that a directory is not renamed while opened
through a file descriptor.
FIXME: On mingw, this would be possible to enforce if we were to
also open a HANDLE to each directory currently visited by a file
descriptor, since mingw refuses to rename any in-use file system
object. */
/* Array of file descriptors opened. If REPLACE_OPEN_DIRECTORY or if it points
to a directory, it stores info about this directory. */
typedef struct
{
char *name; /* Absolute name of the directory, or NULL. */
/* FIXME - add a DIR* member to make dirfd possible on mingw? */
} dir_info_t;
static dir_info_t *dirs;
static size_t dirs_allocated;
/* Try to ensure dirs has enough room for a slot at index fd; free any
contents already in that slot. Return false and set errno to
ENOMEM on allocation failure. */
static bool
ensure_dirs_slot (size_t fd)
{
if (fd < dirs_allocated)
free (dirs[fd].name);
else
{
size_t new_allocated;
dir_info_t *new_dirs;
new_allocated = 2 * dirs_allocated + 1;
if (new_allocated <= fd)
new_allocated = fd + 1;
new_dirs =
(dirs != NULL
? (dir_info_t *) realloc (dirs, new_allocated * sizeof *dirs)
: (dir_info_t *) malloc (new_allocated * sizeof *dirs));
if (new_dirs == NULL)
return false;
memset (new_dirs + dirs_allocated, 0,
(new_allocated - dirs_allocated) * sizeof *dirs);
dirs = new_dirs;
dirs_allocated = new_allocated;
}
return true;
}
/* Return an absolute name of DIR in malloc'd storage. */
static char *
get_name (char const *dir)
{
char *cwd;
char *result;
int saved_errno;
if (IS_ABSOLUTE_FILE_NAME (dir))
return strdup (dir);
/* We often encounter "."; treat it as a special case. */
cwd = getcwd (NULL, 0);
if (!cwd || (dir[0] == '.' && dir[1] == '\0'))
return cwd;
result = mfile_name_concat (cwd, dir, NULL);
saved_errno = errno;
free (cwd);
errno = saved_errno;
return result;
}
/* Hook into the gnulib replacements for open() and close() to keep track
of the open file descriptors. */
/* Close FD, cleaning up any fd to name mapping if fd was visiting a
directory. */
void
_gl_unregister_fd (int fd)
{
if (fd >= 0 && fd < dirs_allocated)
{
free (dirs[fd].name);
dirs[fd].name = NULL;
}
}
/* Mark FD as visiting FILENAME. FD must be non-negative, and refer
to an open file descriptor. If REPLACE_OPEN_DIRECTORY is non-zero,
this should only be called if FD is visiting a directory. Close FD
and return -1 if there is insufficient memory to track the
directory name; otherwise return FD. */
int
_gl_register_fd (int fd, const char *filename)
{
struct stat statbuf;
assure (0 <= fd);
if (REPLACE_OPEN_DIRECTORY
|| (fstat (fd, &statbuf) == 0 && S_ISDIR (statbuf.st_mode)))
{
if (!ensure_dirs_slot (fd)
|| (dirs[fd].name = get_name (filename)) == NULL)
{
int saved_errno = errno;
close (fd);
errno = saved_errno;
return -1;
}
}
return fd;
}
/* Mark NEWFD as a duplicate of OLDFD; useful from dup, dup2, dup3,
and fcntl. Both arguments must be valid and distinct file
descriptors. Close NEWFD and return -1 if OLDFD is tracking a
directory, but there is insufficient memory to track the same
directory in NEWFD; otherwise return NEWFD. */
int
_gl_register_dup (int oldfd, int newfd)
{
assure (0 <= oldfd && 0 <= newfd && oldfd != newfd);
if (oldfd < dirs_allocated && dirs[oldfd].name)
{
/* Duplicated a directory; must ensure newfd is allocated. */
if (!ensure_dirs_slot (newfd)
|| (dirs[newfd].name = strdup (dirs[oldfd].name)) == NULL)
{
int saved_errno = errno;
close (newfd);
errno = saved_errno;
newfd = -1;
}
}
else if (newfd < dirs_allocated)
{
/* Duplicated a non-directory; ensure newfd is cleared. */
free (dirs[newfd].name);
dirs[newfd].name = NULL;
}
return newfd;
}
/* If FD is currently visiting a directory, then return the name of
that directory. Otherwise, return NULL and set errno. */
const char *
_gl_directory_name (int fd)
{
if (0 <= fd && fd < dirs_allocated && dirs[fd].name != NULL)
return dirs[fd].name;
/* At this point, fd is either invalid, or open but not a directory.
If dup2 fails, errno is correctly EBADF. */
if (0 <= fd)
{
if (dup2 (fd, fd) == fd)
errno = ENOTDIR;
}
else
errno = EBADF;
return NULL;
}
/* Implement fchdir() in terms of chdir(). */
int
fchdir (int fd)
{
const char *name = _gl_directory_name (fd);
return name ? chdir (name) : -1;
}

53
lib/fchmodat.c Normal file
View File

@ -0,0 +1,53 @@
/* Change the protections of file relative to an open directory.
Copyright (C) 2006, 2009-2018 Free Software Foundation, Inc.
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 <https://www.gnu.org/licenses/>. */
/* written by Jim Meyering */
#include <config.h>
#include <sys/stat.h>
#include <errno.h>
#ifndef HAVE_LCHMOD
/* Use a different name, to avoid conflicting with any
system-supplied declaration. */
# undef lchmod
# define lchmod lchmod_rpl
static int
lchmod (char const *f _GL_UNUSED, mode_t m _GL_UNUSED)
{
errno = ENOSYS;
return -1;
}
#endif
/* Solaris 10 has no function like this.
Invoke chmod or lchmod on file, FILE, using mode MODE, in the directory
open on descriptor FD. If possible, do it without changing the
working directory. Otherwise, resort to using save_cwd/fchdir,
then (chmod|lchmod)/restore_cwd. If either the save_cwd or the
restore_cwd fails, then give a diagnostic and exit nonzero.
Note that an attempt to use a FLAG value of AT_SYMLINK_NOFOLLOW
on a system without lchmod support causes this function to fail. */
#define AT_FUNC_NAME fchmodat
#define AT_FUNC_F1 lchmod
#define AT_FUNC_F2 chmod
#define AT_FUNC_USE_F1_COND AT_SYMLINK_NOFOLLOW
#define AT_FUNC_POST_FILE_PARAM_DECLS , mode_t mode, int flag
#define AT_FUNC_POST_FILE_ARGS , mode
#include "at-func.c"

16
lib/fchown-stub.c Normal file
View File

@ -0,0 +1,16 @@
#include <config.h>
#include <sys/types.h>
#include <errno.h>
/* A trivial substitute for 'fchown'.
DJGPP 2.03 and earlier (and perhaps later) don't have 'fchown',
so we pretend no-one has permission for this operation. */
int
fchown (int fd, uid_t uid, gid_t gid)
{
errno = EPERM;
return -1;
}

114
lib/fchownat.c Normal file
View File

@ -0,0 +1,114 @@
/* This function serves as replacement for a missing fchownat function,
as well as a work around for the fchownat bug in glibc-2.4:
<https://lists.ubuntu.com/archives/ubuntu-users/2006-September/093218.html>
when the buggy fchownat-with-AT_SYMLINK_NOFOLLOW operates on a symlink, it
mistakenly affects the symlink referent, rather than the symlink itself.
Copyright (C) 2006-2007, 2009-2018 Free Software Foundation, Inc.
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 <https://www.gnu.org/licenses/>. */
/* written by Jim Meyering */
#include <config.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include "openat.h"
#if !HAVE_FCHOWNAT
/* Replacement for Solaris' function by the same name.
Invoke chown or lchown on file, FILE, using OWNER and GROUP, in the
directory open on descriptor FD. If FLAG is AT_SYMLINK_NOFOLLOW, then
use lchown, otherwise, use chown. If possible, do it without changing
the working directory. Otherwise, resort to using save_cwd/fchdir,
then (chown|lchown)/restore_cwd. If either the save_cwd or the
restore_cwd fails, then give a diagnostic and exit nonzero. */
# define AT_FUNC_NAME fchownat
# define AT_FUNC_F1 lchown
# define AT_FUNC_F2 chown
# define AT_FUNC_USE_F1_COND AT_SYMLINK_NOFOLLOW
# define AT_FUNC_POST_FILE_PARAM_DECLS , uid_t owner, gid_t group, int flag
# define AT_FUNC_POST_FILE_ARGS , owner, group
# include "at-func.c"
# undef AT_FUNC_NAME
# undef AT_FUNC_F1
# undef AT_FUNC_F2
# undef AT_FUNC_USE_F1_COND
# undef AT_FUNC_POST_FILE_PARAM_DECLS
# undef AT_FUNC_POST_FILE_ARGS
#else /* HAVE_FCHOWNAT */
# undef fchownat
# if FCHOWNAT_NOFOLLOW_BUG
/* Failure to handle AT_SYMLINK_NOFOLLOW requires the /proc/self/fd or
fchdir workaround to call lchown for lchownat, but there is no need
to penalize chownat. */
static int
local_lchownat (int fd, char const *file, uid_t owner, gid_t group);
# define AT_FUNC_NAME local_lchownat
# define AT_FUNC_F1 lchown
# define AT_FUNC_POST_FILE_PARAM_DECLS , uid_t owner, gid_t group
# define AT_FUNC_POST_FILE_ARGS , owner, group
# include "at-func.c"
# undef AT_FUNC_NAME
# undef AT_FUNC_F1
# undef AT_FUNC_POST_FILE_PARAM_DECLS
# undef AT_FUNC_POST_FILE_ARGS
# endif
/* Work around bugs with trailing slash, using the same workarounds as
chown and lchown. */
int
rpl_fchownat (int fd, char const *file, uid_t owner, gid_t group, int flag)
{
# if FCHOWNAT_NOFOLLOW_BUG
if (flag == AT_SYMLINK_NOFOLLOW)
return local_lchownat (fd, file, owner, group);
# endif
# if FCHOWNAT_EMPTY_FILENAME_BUG
if (file[0] == '\0')
{
errno = ENOENT;
return -1;
}
# endif
# if CHOWN_TRAILING_SLASH_BUG
{
size_t len = strlen (file);
struct stat st;
if (len && file[len - 1] == '/')
{
if (statat (fd, file, &st))
return -1;
if (flag == AT_SYMLINK_NOFOLLOW)
return fchownat (fd, file, owner, group, 0);
}
}
# endif
return fchownat (fd, file, owner, group, flag);
}
#endif /* HAVE_FCHOWNAT */

418
lib/fcntl.c Normal file
View File

@ -0,0 +1,418 @@
/* Provide file descriptor control.
Copyright (C) 2009-2018 Free Software Foundation, Inc.
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 <https://www.gnu.org/licenses/>. */
/* Written by Eric Blake <ebb9@byu.net>. */
#include <config.h>
/* Specification. */
#include <fcntl.h>
#include <errno.h>
#include <limits.h>
#include <stdarg.h>
#include <unistd.h>
#if !HAVE_FCNTL
# define rpl_fcntl fcntl
#endif
#undef fcntl
#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
/* Get declarations of the native Windows API functions. */
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
/* Get _get_osfhandle. */
# if GNULIB_MSVC_NOTHROW
# include "msvc-nothrow.h"
# else
# include <io.h>
# endif
/* Upper bound on getdtablesize(). See lib/getdtablesize.c. */
# define OPEN_MAX_MAX 0x10000
/* Duplicate OLDFD into the first available slot of at least NEWFD,
which must be positive, with FLAGS determining whether the duplicate
will be inheritable. */
static int
dupfd (int oldfd, int newfd, int flags)
{
/* Mingw has no way to create an arbitrary fd. Iterate until all
file descriptors less than newfd are filled up. */
HANDLE curr_process = GetCurrentProcess ();
HANDLE old_handle = (HANDLE) _get_osfhandle (oldfd);
unsigned char fds_to_close[OPEN_MAX_MAX / CHAR_BIT];
unsigned int fds_to_close_bound = 0;
int result;
BOOL inherit = flags & O_CLOEXEC ? FALSE : TRUE;
int mode;
if (newfd < 0 || getdtablesize () <= newfd)
{
errno = EINVAL;
return -1;
}
if (old_handle == INVALID_HANDLE_VALUE
|| (mode = setmode (oldfd, O_BINARY)) == -1)
{
/* oldfd is not open, or is an unassigned standard file
descriptor. */
errno = EBADF;
return -1;
}
setmode (oldfd, mode);
flags |= mode;
for (;;)
{
HANDLE new_handle;
int duplicated_fd;
unsigned int index;
if (!DuplicateHandle (curr_process, /* SourceProcessHandle */
old_handle, /* SourceHandle */
curr_process, /* TargetProcessHandle */
(PHANDLE) &new_handle, /* TargetHandle */
(DWORD) 0, /* DesiredAccess */
inherit, /* InheritHandle */
DUPLICATE_SAME_ACCESS)) /* Options */
{
switch (GetLastError ())
{
case ERROR_TOO_MANY_OPEN_FILES:
errno = EMFILE;
break;
case ERROR_INVALID_HANDLE:
case ERROR_INVALID_TARGET_HANDLE:
case ERROR_DIRECT_ACCESS_HANDLE:
errno = EBADF;
break;
case ERROR_INVALID_PARAMETER:
case ERROR_INVALID_FUNCTION:
case ERROR_INVALID_ACCESS:
errno = EINVAL;
break;
default:
errno = EACCES;
break;
}
result = -1;
break;
}
duplicated_fd = _open_osfhandle ((intptr_t) new_handle, flags);
if (duplicated_fd < 0)
{
CloseHandle (new_handle);
result = -1;
break;
}
if (newfd <= duplicated_fd)
{
result = duplicated_fd;
break;
}
/* Set the bit duplicated_fd in fds_to_close[]. */
index = (unsigned int) duplicated_fd / CHAR_BIT;
if (fds_to_close_bound <= index)
{
if (sizeof fds_to_close <= index)
/* Need to increase OPEN_MAX_MAX. */
abort ();
memset (fds_to_close + fds_to_close_bound, '\0',
index + 1 - fds_to_close_bound);
fds_to_close_bound = index + 1;
}
fds_to_close[index] |= 1 << ((unsigned int) duplicated_fd % CHAR_BIT);
}
/* Close the previous fds that turned out to be too small. */
{
int saved_errno = errno;
unsigned int duplicated_fd;
for (duplicated_fd = 0;
duplicated_fd < fds_to_close_bound * CHAR_BIT;
duplicated_fd++)
if ((fds_to_close[duplicated_fd / CHAR_BIT]
>> (duplicated_fd % CHAR_BIT))
& 1)
close (duplicated_fd);
errno = saved_errno;
}
# if REPLACE_FCHDIR
if (0 <= result)
result = _gl_register_dup (oldfd, result);
# endif
return result;
}
#endif /* W32 */
#ifdef __KLIBC__
# define INCL_DOS
# include <os2.h>
static int
klibc_fcntl (int fd, int action, /* arg */...)
{
va_list arg_ptr;
int arg;
struct stat sbuf;
int result = -1;
va_start (arg_ptr, action);
arg = va_arg (arg_ptr, int);
result = fcntl (fd, action, arg);
/* EPERM for F_DUPFD, ENOTSUP for others */
if (result == -1 && (errno == EPERM || errno == ENOTSUP)
&& !fstat (fd, &sbuf) && S_ISDIR (sbuf.st_mode))
{
ULONG ulMode;
switch (action)
{
case F_DUPFD:
/* Find available fd */
while (fcntl (arg, F_GETFL) != -1 || errno != EBADF)
arg++;
result = dup2 (fd, arg);
break;
/* Using underlying APIs is right ? */
case F_GETFD:
if (DosQueryFHState (fd, &ulMode))
break;
result = (ulMode & OPEN_FLAGS_NOINHERIT) ? FD_CLOEXEC : 0;
break;
case F_SETFD:
if (arg & ~FD_CLOEXEC)
break;
if (DosQueryFHState (fd, &ulMode))
break;
if (arg & FD_CLOEXEC)
ulMode |= OPEN_FLAGS_NOINHERIT;
else
ulMode &= ~OPEN_FLAGS_NOINHERIT;
/* Filter supported flags. */
ulMode &= (OPEN_FLAGS_WRITE_THROUGH | OPEN_FLAGS_FAIL_ON_ERROR
| OPEN_FLAGS_NO_CACHE | OPEN_FLAGS_NOINHERIT);
if (DosSetFHState (fd, ulMode))
break;
result = 0;
break;
case F_GETFL:
result = 0;
break;
case F_SETFL:
if (arg != 0)
break;
result = 0;
break;
default :
errno = EINVAL;
break;
}
}
va_end (arg_ptr);
return result;
}
# define fcntl klibc_fcntl
#endif
/* Perform the specified ACTION on the file descriptor FD, possibly
using the argument ARG further described below. This replacement
handles the following actions, and forwards all others on to the
native fcntl. An unrecognized ACTION returns -1 with errno set to
EINVAL.
F_DUPFD - duplicate FD, with int ARG being the minimum target fd.
If successful, return the duplicate, which will be inheritable;
otherwise return -1 and set errno.
F_DUPFD_CLOEXEC - duplicate FD, with int ARG being the minimum
target fd. If successful, return the duplicate, which will not be
inheritable; otherwise return -1 and set errno.
F_GETFD - ARG need not be present. If successful, return a
non-negative value containing the descriptor flags of FD (only
FD_CLOEXEC is portable, but other flags may be present); otherwise
return -1 and set errno. */
int
rpl_fcntl (int fd, int action, /* arg */...)
{
va_list arg;
int result = -1;
va_start (arg, action);
switch (action)
{
#if !HAVE_FCNTL
case F_DUPFD:
{
int target = va_arg (arg, int);
result = dupfd (fd, target, 0);
break;
}
#elif FCNTL_DUPFD_BUGGY || REPLACE_FCHDIR
case F_DUPFD:
{
int target = va_arg (arg, int);
/* Detect invalid target; needed for cygwin 1.5.x. */
if (target < 0 || getdtablesize () <= target)
errno = EINVAL;
else
{
/* Haiku alpha 2 loses fd flags on original. */
int flags = fcntl (fd, F_GETFD);
if (flags < 0)
{
result = -1;
break;
}
result = fcntl (fd, action, target);
if (0 <= result && fcntl (fd, F_SETFD, flags) == -1)
{
int saved_errno = errno;
close (result);
result = -1;
errno = saved_errno;
}
# if REPLACE_FCHDIR
if (0 <= result)
result = _gl_register_dup (fd, result);
# endif
}
break;
} /* F_DUPFD */
#endif /* FCNTL_DUPFD_BUGGY || REPLACE_FCHDIR */
case F_DUPFD_CLOEXEC:
{
int target = va_arg (arg, int);
#if !HAVE_FCNTL
result = dupfd (fd, target, O_CLOEXEC);
break;
#else /* HAVE_FCNTL */
/* Try the system call first, if the headers claim it exists
(that is, if GNULIB_defined_F_DUPFD_CLOEXEC is 0), since we
may be running with a glibc that has the macro but with an
older kernel that does not support it. Cache the
information on whether the system call really works, but
avoid caching failure if the corresponding F_DUPFD fails
for any reason. 0 = unknown, 1 = yes, -1 = no. */
static int have_dupfd_cloexec = GNULIB_defined_F_DUPFD_CLOEXEC ? -1 : 0;
if (0 <= have_dupfd_cloexec)
{
result = fcntl (fd, action, target);
if (0 <= result || errno != EINVAL)
{
have_dupfd_cloexec = 1;
# if REPLACE_FCHDIR
if (0 <= result)
result = _gl_register_dup (fd, result);
# endif
}
else
{
result = rpl_fcntl (fd, F_DUPFD, target);
if (result < 0)
break;
have_dupfd_cloexec = -1;
}
}
else
result = rpl_fcntl (fd, F_DUPFD, target);
if (0 <= result && have_dupfd_cloexec == -1)
{
int flags = fcntl (result, F_GETFD);
if (flags < 0 || fcntl (result, F_SETFD, flags | FD_CLOEXEC) == -1)
{
int saved_errno = errno;
close (result);
errno = saved_errno;
result = -1;
}
}
break;
#endif /* HAVE_FCNTL */
} /* F_DUPFD_CLOEXEC */
#if !HAVE_FCNTL
case F_GETFD:
{
# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
HANDLE handle = (HANDLE) _get_osfhandle (fd);
DWORD flags;
if (handle == INVALID_HANDLE_VALUE
|| GetHandleInformation (handle, &flags) == 0)
errno = EBADF;
else
result = (flags & HANDLE_FLAG_INHERIT) ? 0 : FD_CLOEXEC;
# else /* !W32 */
/* Use dup2 to reject invalid file descriptors. No way to
access this information, so punt. */
if (0 <= dup2 (fd, fd))
result = 0;
# endif /* !W32 */
break;
} /* F_GETFD */
#endif /* !HAVE_FCNTL */
/* Implementing F_SETFD on mingw is not trivial - there is no
API for changing the O_NOINHERIT bit on an fd, and merely
changing the HANDLE_FLAG_INHERIT bit on the underlying handle
can lead to odd state. It may be possible by duplicating the
handle, using _open_osfhandle with the right flags, then
using dup2 to move the duplicate onto the original, but that
is not supported for now. */
default:
{
#if HAVE_FCNTL
void *p = va_arg (arg, void *);
result = fcntl (fd, action, p);
#else
errno = EINVAL;
#endif
break;
}
}
va_end (arg);
return result;
}

366
lib/fcntl.in.h Normal file
View File

@ -0,0 +1,366 @@
/* Like <fcntl.h>, but with non-working flags defined to 0.
Copyright (C) 2006-2018 Free Software Foundation, Inc.
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 <https://www.gnu.org/licenses/>. */
/* written by Paul Eggert */
#if __GNUC__ >= 3
@PRAGMA_SYSTEM_HEADER@
#endif
@PRAGMA_COLUMNS@
#if defined __need_system_fcntl_h
/* Special invocation convention. */
/* Needed before <sys/stat.h>.
May also define off_t to a 64-bit type on native Windows. */
#include <sys/types.h>
/* On some systems other than glibc, <sys/stat.h> is a prerequisite of
<fcntl.h>. On glibc systems, we would like to avoid namespace pollution.
But on glibc systems, <fcntl.h> includes <sys/stat.h> inside an
extern "C" { ... } block, which leads to errors in C++ mode with the
overridden <sys/stat.h> from gnulib. These errors are known to be gone
with g++ version >= 4.3. */
#if !(defined __GLIBC__ || defined __UCLIBC__) || (defined __cplusplus && defined GNULIB_NAMESPACE && (defined __ICC || !(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))))
# include <sys/stat.h>
#endif
#@INCLUDE_NEXT@ @NEXT_FCNTL_H@
#else
/* Normal invocation convention. */
#ifndef _@GUARD_PREFIX@_FCNTL_H
/* Needed before <sys/stat.h>.
May also define off_t to a 64-bit type on native Windows. */
#include <sys/types.h>
/* On some systems other than glibc, <sys/stat.h> is a prerequisite of
<fcntl.h>. On glibc systems, we would like to avoid namespace pollution.
But on glibc systems, <fcntl.h> includes <sys/stat.h> inside an
extern "C" { ... } block, which leads to errors in C++ mode with the
overridden <sys/stat.h> from gnulib. These errors are known to be gone
with g++ version >= 4.3. */
#if !(defined __GLIBC__ || defined __UCLIBC__) || (defined __cplusplus && defined GNULIB_NAMESPACE && (defined __ICC || !(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))))
# include <sys/stat.h>
#endif
/* The include_next requires a split double-inclusion guard. */
#@INCLUDE_NEXT@ @NEXT_FCNTL_H@
#ifndef _@GUARD_PREFIX@_FCNTL_H
#define _@GUARD_PREFIX@_FCNTL_H
#ifndef __GLIBC__ /* Avoid namespace pollution on glibc systems. */
# include <unistd.h>
#endif
/* Native Windows platforms declare open(), creat() in <io.h>. */
#if (@GNULIB_OPEN@ || defined GNULIB_POSIXCHECK) \
&& ((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__)
# include <io.h>
#endif
/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */
/* The definition of _GL_ARG_NONNULL is copied here. */
/* The definition of _GL_WARN_ON_USE is copied here. */
/* Declare overridden functions. */
#if @GNULIB_FCNTL@
# if @REPLACE_FCNTL@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# undef fcntl
# define fcntl rpl_fcntl
# endif
_GL_FUNCDECL_RPL (fcntl, int, (int fd, int action, ...));
_GL_CXXALIAS_RPL (fcntl, int, (int fd, int action, ...));
# else
# if !@HAVE_FCNTL@
_GL_FUNCDECL_SYS (fcntl, int, (int fd, int action, ...));
# endif
_GL_CXXALIAS_SYS (fcntl, int, (int fd, int action, ...));
# endif
_GL_CXXALIASWARN (fcntl);
#elif defined GNULIB_POSIXCHECK
# undef fcntl
# if HAVE_RAW_DECL_FCNTL
_GL_WARN_ON_USE (fcntl, "fcntl is not always POSIX compliant - "
"use gnulib module fcntl for portability");
# endif
#endif
#if @GNULIB_OPEN@
# if @REPLACE_OPEN@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# undef open
# define open rpl_open
# endif
_GL_FUNCDECL_RPL (open, int, (const char *filename, int flags, ...)
_GL_ARG_NONNULL ((1)));
_GL_CXXALIAS_RPL (open, int, (const char *filename, int flags, ...));
# else
_GL_CXXALIAS_SYS (open, int, (const char *filename, int flags, ...));
# endif
/* On HP-UX 11, in C++ mode, open() is defined as an inline function with a
default argument. _GL_CXXALIASWARN does not work in this case. */
# if !defined __hpux
_GL_CXXALIASWARN (open);
# endif
#elif defined GNULIB_POSIXCHECK
# undef open
/* Assume open is always declared. */
_GL_WARN_ON_USE (open, "open is not always POSIX compliant - "
"use gnulib module open for portability");
#endif
#if @GNULIB_OPENAT@
# if @REPLACE_OPENAT@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# undef openat
# define openat rpl_openat
# endif
_GL_FUNCDECL_RPL (openat, int,
(int fd, char const *file, int flags, /* mode_t mode */ ...)
_GL_ARG_NONNULL ((2)));
_GL_CXXALIAS_RPL (openat, int,
(int fd, char const *file, int flags, /* mode_t mode */ ...));
# else
# if !@HAVE_OPENAT@
_GL_FUNCDECL_SYS (openat, int,
(int fd, char const *file, int flags, /* mode_t mode */ ...)
_GL_ARG_NONNULL ((2)));
# endif
_GL_CXXALIAS_SYS (openat, int,
(int fd, char const *file, int flags, /* mode_t mode */ ...));
# endif
_GL_CXXALIASWARN (openat);
#elif defined GNULIB_POSIXCHECK
# undef openat
# if HAVE_RAW_DECL_OPENAT
_GL_WARN_ON_USE (openat, "openat is not portable - "
"use gnulib module openat for portability");
# endif
#endif
/* Fix up the FD_* macros, only known to be missing on mingw. */
#ifndef FD_CLOEXEC
# define FD_CLOEXEC 1
#endif
/* Fix up the supported F_* macros. Intentionally leave other F_*
macros undefined. Only known to be missing on mingw. */
#ifndef F_DUPFD_CLOEXEC
# define F_DUPFD_CLOEXEC 0x40000000
/* Witness variable: 1 if gnulib defined F_DUPFD_CLOEXEC, 0 otherwise. */
# define GNULIB_defined_F_DUPFD_CLOEXEC 1
#else
# define GNULIB_defined_F_DUPFD_CLOEXEC 0
#endif
#ifndef F_DUPFD
# define F_DUPFD 1
#endif
#ifndef F_GETFD
# define F_GETFD 2
#endif
/* Fix up the O_* macros. */
/* AIX 7.1 with XL C 12.1 defines O_CLOEXEC, O_NOFOLLOW, and O_TTY_INIT
to values outside 'int' range, so omit these misdefinitions.
But avoid namespace pollution on non-AIX systems. */
#ifdef _AIX
# include <limits.h>
# if defined O_CLOEXEC && ! (INT_MIN <= O_CLOEXEC && O_CLOEXEC <= INT_MAX)
# undef O_CLOEXEC
# endif
# if defined O_NOFOLLOW && ! (INT_MIN <= O_NOFOLLOW && O_NOFOLLOW <= INT_MAX)
# undef O_NOFOLLOW
# endif
# if defined O_TTY_INIT && ! (INT_MIN <= O_TTY_INIT && O_TTY_INIT <= INT_MAX)
# undef O_TTY_INIT
# endif
#endif
#if !defined O_DIRECT && defined O_DIRECTIO
/* Tru64 spells it 'O_DIRECTIO'. */
# define O_DIRECT O_DIRECTIO
#endif
#if !defined O_CLOEXEC && defined O_NOINHERIT
/* Mingw spells it 'O_NOINHERIT'. */
# define O_CLOEXEC O_NOINHERIT
#endif
#ifndef O_CLOEXEC
# define O_CLOEXEC 0x40000000 /* Try to not collide with system O_* flags. */
# define GNULIB_defined_O_CLOEXEC 1
#else
# define GNULIB_defined_O_CLOEXEC 0
#endif
#ifndef O_DIRECT
# define O_DIRECT 0
#endif
#ifndef O_DIRECTORY
# define O_DIRECTORY 0
#endif
#ifndef O_DSYNC
# define O_DSYNC 0
#endif
#ifndef O_EXEC
# define O_EXEC O_RDONLY /* This is often close enough in older systems. */
#endif
#ifndef O_IGNORE_CTTY
# define O_IGNORE_CTTY 0
#endif
#ifndef O_NDELAY
# define O_NDELAY 0
#endif
#ifndef O_NOATIME
# define O_NOATIME 0
#endif
#ifndef O_NONBLOCK
# define O_NONBLOCK O_NDELAY
#endif
/* If the gnulib module 'nonblocking' is in use, guarantee a working non-zero
value of O_NONBLOCK. Otherwise, O_NONBLOCK is defined (above) to O_NDELAY
or to 0 as fallback. */
#if @GNULIB_NONBLOCKING@
# if O_NONBLOCK
# define GNULIB_defined_O_NONBLOCK 0
# else
# define GNULIB_defined_O_NONBLOCK 1
# undef O_NONBLOCK
# define O_NONBLOCK 0x40000000
# endif
#endif
#ifndef O_NOCTTY
# define O_NOCTTY 0
#endif
#ifndef O_NOFOLLOW
# define O_NOFOLLOW 0
#endif
#ifndef O_NOLINK
# define O_NOLINK 0
#endif
#ifndef O_NOLINKS
# define O_NOLINKS 0
#endif
#ifndef O_NOTRANS
# define O_NOTRANS 0
#endif
#ifndef O_RSYNC
# define O_RSYNC 0
#endif
#ifndef O_SEARCH
# define O_SEARCH O_RDONLY /* This is often close enough in older systems. */
#endif
#ifndef O_SYNC
# define O_SYNC 0
#endif
#ifndef O_TTY_INIT
# define O_TTY_INIT 0
#endif
#if ~O_ACCMODE & (O_RDONLY | O_WRONLY | O_RDWR | O_EXEC | O_SEARCH)
# undef O_ACCMODE
# define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR | O_EXEC | O_SEARCH)
#endif
/* For systems that distinguish between text and binary I/O.
O_BINARY is usually declared in fcntl.h */
#if !defined O_BINARY && defined _O_BINARY
/* For MSC-compatible compilers. */
# define O_BINARY _O_BINARY
# define O_TEXT _O_TEXT
#endif
#if defined __BEOS__ || defined __HAIKU__
/* BeOS 5 and Haiku have O_BINARY and O_TEXT, but they have no effect. */
# undef O_BINARY
# undef O_TEXT
#endif
#ifndef O_BINARY
# define O_BINARY 0
# define O_TEXT 0
#endif
/* Fix up the AT_* macros. */
/* Work around a bug in Solaris 9 and 10: AT_FDCWD is positive. Its
value exceeds INT_MAX, so its use as an int doesn't conform to the
C standard, and GCC and Sun C complain in some cases. If the bug
is present, undef AT_FDCWD here, so it can be redefined below. */
#if 0 < AT_FDCWD && AT_FDCWD == 0xffd19553
# undef AT_FDCWD
#endif
/* Use the same bit pattern as Solaris 9, but with the proper
signedness. The bit pattern is important, in case this actually is
Solaris with the above workaround. */
#ifndef AT_FDCWD
# define AT_FDCWD (-3041965)
#endif
/* Use the same values as Solaris 9. This shouldn't matter, but
there's no real reason to differ. */
#ifndef AT_SYMLINK_NOFOLLOW
# define AT_SYMLINK_NOFOLLOW 4096
#endif
#ifndef AT_REMOVEDIR
# define AT_REMOVEDIR 1
#endif
/* Solaris 9 lacks these two, so just pick unique values. */
#ifndef AT_SYMLINK_FOLLOW
# define AT_SYMLINK_FOLLOW 2
#endif
#ifndef AT_EACCESS
# define AT_EACCESS 4
#endif
#endif /* _@GUARD_PREFIX@_FCNTL_H */
#endif /* _@GUARD_PREFIX@_FCNTL_H */
#endif

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