updated findutils to 4.2.33 (sorry, not latest).
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@28750 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
+591
-254
@@ -1,285 +1,627 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
675 Mass Ave, Cambridge, MA 02139, USA
|
||||
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 licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
0. Definitions.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"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.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
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) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
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.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
To "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.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
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.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
1. Source Code.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
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) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
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.
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
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.
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
The "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 source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
2. Basic Permissions.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
14. Revised Versions of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
NO WARRANTY
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
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
|
||||
|
||||
Appendix: How to Apply These Terms to Your New Programs
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
@@ -287,15 +629,15 @@ free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) 19yy <name of author>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
@@ -304,36 +646,31 @@ the "copyright" line and a pointer to where the full notice is found.
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) 19yy name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
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>.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
Public License instead of this License.
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
SubDir HAIKU_TOP src bin findutils ;
|
||||
|
||||
SubInclude HAIKU_TOP src bin findutils gnulib ;
|
||||
SubInclude HAIKU_TOP src bin findutils lib ;
|
||||
SubInclude HAIKU_TOP src bin findutils find ;
|
||||
SubInclude HAIKU_TOP src bin findutils locate ;
|
||||
|
||||
@@ -1,12 +1,21 @@
|
||||
This package contains the GNU find, xargs, and locate programs. find
|
||||
and xargs comply with POSIX 1003.2, as far as I know. They also
|
||||
support some additional options, some borrowed from Unix and some
|
||||
unique to GNU.
|
||||
and xargs comply with POSIX 1003.2, as far as I know (with the
|
||||
exception of the "+" modifier for the "-exec" action, which isn't
|
||||
implemented yet). They also support a large number of additional
|
||||
options, some borrowed from Unix and some unique to GNU.
|
||||
|
||||
See the file NEWS for a list of major changes in the current release.
|
||||
|
||||
See the file INSTALL for compilation and installation instructions.
|
||||
|
||||
To verify the GPG signature of the release, you will need the public
|
||||
key of the findutils maintainer. You can download this from
|
||||
ftp://ftp.gnu.org/gnu/gnu-keyring.gpg. Alternatively, you could query
|
||||
a PGP keyserver, but you will need to use one that can cope with
|
||||
subkeys containing photos. Many older key servers cannot do this. I
|
||||
use subkeys.pgp.net. I think that one works. See also the
|
||||
"Downloading" section of http://www.gnu.org/software/findutils/.
|
||||
|
||||
Special configure options:
|
||||
|
||||
--with-afs
|
||||
@@ -21,6 +30,13 @@ getpwuid or getgrgid when needed. Speeds up -nouser and -nogroup
|
||||
unless you are running NIS or Hesiod, which make password and group
|
||||
calls very expensive.
|
||||
|
||||
--enable-debug
|
||||
Produce output on the standard error output indicating what find is
|
||||
doing. This information includes details about how the command line
|
||||
has been parsed and what files have been stat()ed. This output is
|
||||
normally interesting only to the maintainer, and so is off by default.
|
||||
|
||||
|
||||
To gain speed, GNU find avoids statting files whenever possible.
|
||||
It does this by:
|
||||
1. Checking the number of links to directories and not statting files
|
||||
@@ -39,9 +55,5 @@ searching has been moved to a separate program, `locate'; the same
|
||||
thing has been done in 4.4BSD. If you use locate, you should run the
|
||||
included `updatedb' script from cron periodically (typically nightly).
|
||||
|
||||
The `Makefile.am' files are used by an experimental program called
|
||||
AutoMake that is under development. It's not ready for general use
|
||||
yet, so don't worry about them.
|
||||
|
||||
Mail suggestions and bug reports for these programs to
|
||||
bug-gnu-utils@prep.ai.mit.edu.
|
||||
bug-findutils@gnu.org.
|
||||
|
||||
+979
-109
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,6 @@
|
||||
SubDir HAIKU_TOP src bin findutils find ;
|
||||
|
||||
SubDirSysHdrs [ FDirName $(SUBDIR) $(DOTDOT) gnulib lib ] ;
|
||||
SubDirSysHdrs [ FDirName $(SUBDIR) $(DOTDOT) lib ] ;
|
||||
SubDirSysHdrs [ FDirName $(SUBDIR) $(DOTDOT) ] ;
|
||||
|
||||
@@ -19,6 +20,6 @@ BinCommand find :
|
||||
pred.c
|
||||
tree.c
|
||||
util.c
|
||||
: libfindutils.a : findutils.rdef ;
|
||||
: libfindutils.a gnulibfindutils.a : findutils.rdef ;
|
||||
|
||||
SEARCH on [ FGristFiles findutils.rdef ] = [ FDirName $(SUBDIR) $(DOTDOT) ] ;
|
||||
|
||||
+405
-126
@@ -1,19 +1,28 @@
|
||||
/* defs.h -- data types and declarations.
|
||||
Copyright (C) 1990, 91, 92, 93, 94 Free Software Foundation, Inc.
|
||||
Copyright (C) 1990, 91, 92, 93, 94, 2000, 2001, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef INC_DEFS_H
|
||||
#define INC_DEFS_H 1
|
||||
|
||||
#include <config.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#if defined(HAVE_STRING_H) || defined(STDC_HEADERS)
|
||||
#include <string.h>
|
||||
@@ -36,27 +45,106 @@ extern int errno;
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
/* The presence of unistd.h is assumed by gnulib these days, so we
|
||||
* might as well assume it too.
|
||||
*/
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include "regex.h"
|
||||
|
||||
#if __STDC__
|
||||
# define P_(s) s
|
||||
#else
|
||||
# define P_(s) ()
|
||||
#if HAVE_LIMITS_H
|
||||
# include <limits.h>
|
||||
#endif
|
||||
#ifndef CHAR_BIT
|
||||
# define CHAR_BIT 8
|
||||
#endif
|
||||
|
||||
#if HAVE_INTTYPES_H
|
||||
# include <inttypes.h>
|
||||
#endif
|
||||
|
||||
#include "regex.h"
|
||||
|
||||
#ifndef S_IFLNK
|
||||
#define lstat stat
|
||||
#endif
|
||||
|
||||
# ifndef PARAMS
|
||||
# if defined PROTOTYPES || (defined __STDC__ && __STDC__)
|
||||
# define PARAMS(Args) Args
|
||||
# else
|
||||
# define PARAMS(Args) ()
|
||||
# endif
|
||||
# endif
|
||||
|
||||
int lstat PARAMS((const char *__path, struct stat *__statbuf));
|
||||
int stat PARAMS((const char *__path, struct stat *__statbuf));
|
||||
|
||||
int optionl_stat PARAMS((const char *name, struct stat *p));
|
||||
int optionp_stat PARAMS((const char *name, struct stat *p));
|
||||
int optionh_stat PARAMS((const char *name, struct stat *p));
|
||||
|
||||
int get_statinfo PARAMS((const char *pathname, const char *name, struct stat *p));
|
||||
|
||||
|
||||
|
||||
#ifndef S_ISUID
|
||||
# define S_ISUID 0004000
|
||||
#endif
|
||||
#ifndef S_ISGID
|
||||
# define S_ISGID 0002000
|
||||
#endif
|
||||
#ifndef S_ISVTX
|
||||
# define S_ISVTX 0001000
|
||||
#endif
|
||||
#ifndef S_IRUSR
|
||||
# define S_IRUSR 0000400
|
||||
#endif
|
||||
#ifndef S_IWUSR
|
||||
# define S_IWUSR 0000200
|
||||
#endif
|
||||
#ifndef S_IXUSR
|
||||
# define S_IXUSR 0000100
|
||||
#endif
|
||||
#ifndef S_IRGRP
|
||||
# define S_IRGRP 0000040
|
||||
#endif
|
||||
#ifndef S_IWGRP
|
||||
# define S_IWGRP 0000020
|
||||
#endif
|
||||
#ifndef S_IXGRP
|
||||
# define S_IXGRP 0000010
|
||||
#endif
|
||||
#ifndef S_IROTH
|
||||
# define S_IROTH 0000004
|
||||
#endif
|
||||
#ifndef S_IWOTH
|
||||
# define S_IWOTH 0000002
|
||||
#endif
|
||||
#ifndef S_IXOTH
|
||||
# define S_IXOTH 0000001
|
||||
#endif
|
||||
|
||||
#define MODE_WXUSR (S_IWUSR | S_IXUSR)
|
||||
#define MODE_R (S_IRUSR | S_IRGRP | S_IROTH)
|
||||
#define MODE_RW (S_IWUSR | S_IWGRP | S_IWOTH | MODE_R)
|
||||
#define MODE_RWX (S_IXUSR | S_IXGRP | S_IXOTH | MODE_RW)
|
||||
#define MODE_ALL (S_ISUID | S_ISGID | S_ISVTX | MODE_RWX)
|
||||
|
||||
#if 1
|
||||
#include <stdbool.h>
|
||||
typedef bool boolean;
|
||||
#else
|
||||
/* Not char because of type promotion; NeXT gcc can't handle it. */
|
||||
typedef int boolean;
|
||||
#define true 1
|
||||
#define false 0
|
||||
#endif
|
||||
|
||||
/* Pointer to function returning boolean. */
|
||||
typedef boolean (*PFB)();
|
||||
struct predicate;
|
||||
|
||||
/* Pointer to a predicate function. */
|
||||
typedef boolean (*PRED_FUNC)(char *pathname, struct stat *stat_buf, struct predicate *pred_ptr);
|
||||
|
||||
/* The number of seconds in a day. */
|
||||
#define DAYSECS 86400
|
||||
@@ -70,6 +158,13 @@ enum comparison_type
|
||||
COMP_EQ
|
||||
};
|
||||
|
||||
enum permissions_type
|
||||
{
|
||||
PERM_AT_LEAST,
|
||||
PERM_ANY,
|
||||
PERM_EXACT
|
||||
};
|
||||
|
||||
enum predicate_type
|
||||
{
|
||||
NO_TYPE,
|
||||
@@ -93,27 +188,63 @@ enum predicate_precedence
|
||||
struct long_val
|
||||
{
|
||||
enum comparison_type kind;
|
||||
unsigned long l_val;
|
||||
boolean negative; /* Defined only when representing time_t. */
|
||||
uintmax_t l_val;
|
||||
};
|
||||
|
||||
struct perm_val
|
||||
{
|
||||
enum permissions_type kind;
|
||||
mode_t val[2];
|
||||
};
|
||||
|
||||
/* dir_id is used to support loop detection in find.c and
|
||||
* also to support the -samefile test.
|
||||
*/
|
||||
struct dir_id
|
||||
{
|
||||
ino_t ino;
|
||||
dev_t dev;
|
||||
};
|
||||
|
||||
struct size_val
|
||||
{
|
||||
enum comparison_type kind;
|
||||
int blocksize;
|
||||
unsigned long size;
|
||||
uintmax_t size;
|
||||
};
|
||||
|
||||
#define NEW_EXEC 1
|
||||
/*
|
||||
#undef NEW_EXEC
|
||||
*/
|
||||
|
||||
#if !defined(NEW_EXEC)
|
||||
struct path_arg
|
||||
{
|
||||
short offset; /* Offset in `vec' of this arg. */
|
||||
short count; /* Number of path replacements in this arg. */
|
||||
char *origarg; /* Arg with "{}" intact. */
|
||||
};
|
||||
#endif
|
||||
|
||||
#include "buildcmd.h"
|
||||
|
||||
struct exec_val
|
||||
{
|
||||
#if defined(NEW_EXEC)
|
||||
/* new-style */
|
||||
boolean multiple; /* -exec {} \+ denotes multiple argument. */
|
||||
struct buildcmd_control ctl;
|
||||
struct buildcmd_state state;
|
||||
char **replace_vec; /* Command arguments (for ";" style) */
|
||||
int num_args;
|
||||
boolean use_current_dir; /* If nonzero, don't chdir to start dir */
|
||||
boolean close_stdin; /* If true, close stdin in the child. */
|
||||
#else
|
||||
struct path_arg *paths; /* Array of args with path replacements. */
|
||||
char **vec; /* Array of args to pass to program. */
|
||||
#endif
|
||||
};
|
||||
|
||||
/* The format string for a -printf or -fprintf is chopped into one or
|
||||
@@ -137,12 +268,14 @@ struct format_val
|
||||
{
|
||||
struct segment *segment; /* Linked list of segments. */
|
||||
FILE *stream; /* Output stream to print on. */
|
||||
boolean dest_is_tty; /* True if the destination is a terminal. */
|
||||
struct quoting_options *quote_opts;
|
||||
};
|
||||
|
||||
struct predicate
|
||||
{
|
||||
/* Pointer to the function that implements this predicate. */
|
||||
PFB pred_func;
|
||||
PRED_FUNC pred_func;
|
||||
|
||||
/* Only used for debugging, but defined unconditionally so individual
|
||||
modules can be compiled with -DDEBUG. */
|
||||
@@ -156,12 +289,20 @@ struct predicate
|
||||
/* The precedence of this node. Only has meaning for operators. */
|
||||
enum predicate_precedence p_prec;
|
||||
|
||||
/* True if this predicate node produces side effects. */
|
||||
/* True if this predicate node produces side effects.
|
||||
If side_effects are produced
|
||||
then optimization will not be performed */
|
||||
boolean side_effects;
|
||||
|
||||
/* True if this predicate node requires default print be turned off. */
|
||||
boolean no_default_print;
|
||||
|
||||
/* True if this predicate node requires a stat system call to execute. */
|
||||
boolean need_stat;
|
||||
|
||||
/* True if this predicate node requires knowledge of the file type. */
|
||||
boolean need_type;
|
||||
|
||||
/* Information needed by the predicate processor.
|
||||
Next to each member are listed the predicates that use it. */
|
||||
union
|
||||
@@ -169,19 +310,21 @@ struct predicate
|
||||
char *str; /* fstype [i]lname [i]name [i]path */
|
||||
struct re_pattern_buffer *regex; /* regex */
|
||||
struct exec_val exec_vec; /* exec ok */
|
||||
struct long_val info; /* atime ctime mtime inum links */
|
||||
struct long_val info; /* atime ctime gid inum links mtime
|
||||
size uid */
|
||||
struct size_val size; /* size */
|
||||
uid_t uid; /* user */
|
||||
gid_t gid; /* group */
|
||||
time_t time; /* newer */
|
||||
unsigned long perm; /* perm */
|
||||
unsigned long type; /* type */
|
||||
FILE *stream; /* fprint fprint0 */
|
||||
struct format_val printf_vec; /* printf fprintf */
|
||||
struct perm_val perm; /* perm */
|
||||
struct dir_id fileid; /* samefile */
|
||||
mode_t type; /* type */
|
||||
FILE *stream; /* ls fls fprint0 */
|
||||
struct format_val printf_vec; /* printf fprintf fprint */
|
||||
} args;
|
||||
|
||||
/* The next predicate in the user input sequence,
|
||||
which repesents the order in which the user supplied the
|
||||
which represents the order in which the user supplied the
|
||||
predicates on the command line. */
|
||||
struct predicate *pred_next;
|
||||
|
||||
@@ -190,30 +333,34 @@ struct predicate
|
||||
processed. */
|
||||
struct predicate *pred_left;
|
||||
struct predicate *pred_right;
|
||||
|
||||
const struct parser_table* parser_entry;
|
||||
};
|
||||
|
||||
/* find.c. */
|
||||
int get_info PARAMS((const char *pathname, const char *name, struct stat *p, struct predicate *pred_ptr));
|
||||
int following_links(void);
|
||||
|
||||
|
||||
/* find library function declarations. */
|
||||
|
||||
/* dirname.c */
|
||||
char *dirname P_((char *path));
|
||||
char *dirname PARAMS((char *path));
|
||||
|
||||
/* error.c */
|
||||
void error P_((int status, int errnum, char *message, ...));
|
||||
void error PARAMS((int status, int errnum, char *message, ...));
|
||||
|
||||
/* listfile.c */
|
||||
void list_file P_((char *name, char *relname, struct stat *statp, FILE *stream));
|
||||
char *get_link_name P_((char *name, char *relname));
|
||||
|
||||
/* savedir.c */
|
||||
char *savedir P_((char *dir, unsigned name_size));
|
||||
void list_file PARAMS((char *name, char *relname, struct stat *statp, time_t current_time, int output_block_size, FILE *stream));
|
||||
char *get_link_name PARAMS((char *name, char *relname));
|
||||
|
||||
/* stpcpy.c */
|
||||
#if !HAVE_STPCPY
|
||||
char *stpcpy P_((char *dest, const char *src));
|
||||
char *stpcpy PARAMS((char *dest, const char *src));
|
||||
#endif
|
||||
|
||||
/* xgetcwd.c */
|
||||
char *xgetcwd P_((void));
|
||||
char *xgetcwd PARAMS((void));
|
||||
|
||||
/* xmalloc.c */
|
||||
#if __STDC__
|
||||
@@ -222,111 +369,243 @@ char *xgetcwd P_((void));
|
||||
#define VOID char
|
||||
#endif
|
||||
|
||||
VOID *xmalloc P_((size_t n));
|
||||
VOID *xrealloc P_((VOID *p, size_t n));
|
||||
|
||||
/* xstrdup.c */
|
||||
char *xstrdup P_((char *string));
|
||||
|
||||
/* find global function declarations. */
|
||||
|
||||
/* find.c */
|
||||
/* SymlinkOption represents the choice of
|
||||
* -P, -L or -P (default) on the command line.
|
||||
*/
|
||||
enum SymlinkOption
|
||||
{
|
||||
SYMLINK_NEVER_DEREF, /* Option -P */
|
||||
SYMLINK_ALWAYS_DEREF, /* Option -L */
|
||||
SYMLINK_DEREF_ARGSONLY /* Option -H */
|
||||
};
|
||||
extern enum SymlinkOption symlink_handling; /* defined in find.c. */
|
||||
|
||||
void set_follow_state PARAMS((enum SymlinkOption opt));
|
||||
void cleanup(void);
|
||||
|
||||
/* fstype.c */
|
||||
char *filesystem_type P_((char *path, char *relpath, struct stat *statp));
|
||||
char *filesystem_type PARAMS((const struct stat *statp, const char *path));
|
||||
char * get_mounted_filesystems (void);
|
||||
dev_t * get_mounted_devices PARAMS((size_t *));
|
||||
|
||||
|
||||
|
||||
enum arg_type
|
||||
{
|
||||
ARG_OPTION, /* regular options like -maxdepth */
|
||||
ARG_POSITIONAL_OPTION, /* options whose position is important (-follow) */
|
||||
ARG_TEST, /* a like -name */
|
||||
ARG_PUNCTUATION, /* like -o or ( */
|
||||
ARG_ACTION /* like -print */
|
||||
};
|
||||
|
||||
|
||||
struct parser_table;
|
||||
/* Pointer to a parser function. */
|
||||
typedef boolean (*PARSE_FUNC)(const struct parser_table *p,
|
||||
char *argv[], int *arg_ptr);
|
||||
struct parser_table
|
||||
{
|
||||
enum arg_type type;
|
||||
char *parser_name;
|
||||
PARSE_FUNC parser_func;
|
||||
PRED_FUNC pred_func;
|
||||
};
|
||||
|
||||
/* parser.c */
|
||||
PFB find_parser P_((char *search_name));
|
||||
boolean parse_close P_((char *argv[], int *arg_ptr));
|
||||
boolean parse_open P_((char *argv[], int *arg_ptr));
|
||||
boolean parse_print P_((char *argv[], int *arg_ptr));
|
||||
const struct parser_table* find_parser PARAMS((char *search_name));
|
||||
boolean parse_open PARAMS((const struct parser_table* entry, char *argv[], int *arg_ptr));
|
||||
boolean parse_close PARAMS((const struct parser_table* entry, char *argv[], int *arg_ptr));
|
||||
boolean parse_print PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
|
||||
void pred_sanity_check PARAMS((const struct predicate *predicates));
|
||||
void parse_begin_user_args PARAMS((char **args, int argno, const struct predicate *last, const struct predicate *predicates));
|
||||
void parse_end_user_args PARAMS((char **args, int argno, const struct predicate *last, const struct predicate *predicates));
|
||||
boolean parse_openparen PARAMS((const struct parser_table* entry, char *argv[], int *arg_ptr));
|
||||
boolean parse_closeparen PARAMS((const struct parser_table* entry, char *argv[], int *arg_ptr));
|
||||
|
||||
/* pred.c */
|
||||
boolean pred_amin P_((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_and P_((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_anewer P_((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_atime P_((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_close P_((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_cmin P_((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_cnewer P_((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_comma P_((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_ctime P_((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_empty P_((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_exec P_((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_false P_((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_fls P_((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_fprint P_((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_fprint0 P_((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_fprintf P_((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_fstype P_((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_gid P_((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_group P_((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_ilname P_((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_iname P_((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_inum P_((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_ipath P_((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_links P_((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_lname P_((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_ls P_((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_mmin P_((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_mtime P_((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_name P_((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_negate P_((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_newer P_((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_nogroup P_((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_nouser P_((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_ok P_((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_open P_((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_or P_((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_path P_((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_perm P_((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_print P_((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_print0 P_((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_prune P_((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_regex P_((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_size P_((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_true P_((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_type P_((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_uid P_((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_used P_((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_user P_((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_xtype P_((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
char *find_pred_name P_((PFB pred_func));
|
||||
boolean pred_amin PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_and PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_anewer PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_atime PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_closeparen PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_cmin PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_cnewer PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_comma PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_ctime PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_delete PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_empty PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_exec PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_execdir PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_false PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_fls PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_fprint PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_fprint0 PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_fprintf PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_fstype PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_gid PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_group PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_ilname PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_iname PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_inum PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_ipath PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_links PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_lname PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_ls PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_mmin PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_mtime PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_name PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_negate PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_newer PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_nogroup PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_nouser PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_ok PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_okdir PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_openparen PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_or PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_path PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_perm PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_print PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_print0 PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_prune PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_quit PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_regex PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_samefile PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_size PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_true PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_type PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_uid PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_used PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_user PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
boolean pred_xtype PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
|
||||
|
||||
|
||||
|
||||
int launch PARAMS((const struct buildcmd_control *ctl,
|
||||
struct buildcmd_state *buildstate));
|
||||
|
||||
|
||||
char *find_pred_name PARAMS((PRED_FUNC pred_func));
|
||||
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
void print_tree P_((struct predicate *node, int indent));
|
||||
void print_list P_((struct predicate *node));
|
||||
void print_tree PARAMS((FILE*, struct predicate *node, int indent));
|
||||
void print_list PARAMS((FILE*, struct predicate *node));
|
||||
void print_optlist PARAMS((FILE *fp, struct predicate *node));
|
||||
#endif /* DEBUG */
|
||||
|
||||
/* tree.c */
|
||||
struct predicate *get_expr P_((struct predicate **input, int prev_prec));
|
||||
boolean opt_expr P_((struct predicate **eval_treep));
|
||||
boolean mark_stat P_((struct predicate *tree));
|
||||
struct predicate *
|
||||
get_expr PARAMS((struct predicate **input, short int prev_prec));
|
||||
boolean opt_expr PARAMS((struct predicate **eval_treep));
|
||||
boolean mark_stat PARAMS((struct predicate *tree));
|
||||
boolean mark_type PARAMS((struct predicate *tree));
|
||||
|
||||
/* util.c */
|
||||
char *basename P_((char *fname));
|
||||
struct predicate *get_new_pred P_((void));
|
||||
struct predicate *get_new_pred_chk_op P_((void));
|
||||
struct predicate *insert_primary P_((boolean (*pred_func )()));
|
||||
void usage P_((char *msg));
|
||||
struct predicate *get_new_pred PARAMS((const struct parser_table *entry));
|
||||
struct predicate *get_new_pred_chk_op PARAMS((const struct parser_table *entry));
|
||||
struct predicate *insert_primary PARAMS((const struct parser_table *entry));
|
||||
struct predicate *insert_primary_withpred PARAMS((const struct parser_table *entry, PRED_FUNC fptr));
|
||||
void usage PARAMS((char *msg));
|
||||
|
||||
extern char *program_name;
|
||||
extern struct predicate *predicates;
|
||||
extern struct predicate *last_pred;
|
||||
extern boolean do_dir_first;
|
||||
extern int maxdepth;
|
||||
extern int mindepth;
|
||||
extern int curdepth;
|
||||
extern time_t cur_day_start;
|
||||
extern boolean full_days;
|
||||
extern boolean no_leaf_check;
|
||||
extern boolean stay_on_filesystem;
|
||||
extern boolean stop_at_current_level;
|
||||
extern boolean have_stat;
|
||||
extern char *rel_pathname;
|
||||
#ifndef HAVE_FCHDIR
|
||||
extern char *starting_dir;
|
||||
#else
|
||||
|
||||
struct options
|
||||
{
|
||||
/* If true, process directory before contents. True unless -depth given. */
|
||||
boolean do_dir_first;
|
||||
|
||||
/* If >=0, don't descend more than this many levels of subdirectories. */
|
||||
int maxdepth;
|
||||
|
||||
/* If >=0, don't process files above this level. */
|
||||
int mindepth;
|
||||
|
||||
/* If true, do not assume that files in directories with nlink == 2
|
||||
are non-directories. */
|
||||
boolean no_leaf_check;
|
||||
|
||||
/* If true, don't cross filesystem boundaries. */
|
||||
boolean stay_on_filesystem;
|
||||
|
||||
/* If true, we ignore the problem where we find that a directory entry
|
||||
* no longer exists by the time we get around to processing it.
|
||||
*/
|
||||
boolean ignore_readdir_race;
|
||||
|
||||
/* If true, we issue warning messages
|
||||
*/
|
||||
boolean warnings;
|
||||
time_t start_time; /* Time at start of execution. */
|
||||
|
||||
/* Seconds between 00:00 1/1/70 and either one day before now
|
||||
(the default), or the start of today (if -daystart is given). */
|
||||
time_t cur_day_start;
|
||||
|
||||
/* If true, cur_day_start has been adjusted to the start of the day. */
|
||||
boolean full_days;
|
||||
|
||||
int output_block_size; /* Output block size. */
|
||||
|
||||
enum SymlinkOption symlink_handling;
|
||||
|
||||
|
||||
/* Pointer to the function used to stat files. */
|
||||
int (*xstat) (const char *name, struct stat *statbuf);
|
||||
|
||||
|
||||
/* Indicate if we can implement safely_chdir() using the O_NOFOLLOW
|
||||
* flag to open(2).
|
||||
*/
|
||||
boolean open_nofollow_available;
|
||||
|
||||
/* The variety of regular expression that we support.
|
||||
* The default is POSIX Basic Regular Expressions, but this
|
||||
* can be changed with the positional option, -regextype.
|
||||
*/
|
||||
int regex_options;
|
||||
};
|
||||
extern struct options options;
|
||||
|
||||
|
||||
struct state
|
||||
{
|
||||
/* Current depth; 0 means current path is a command line arg. */
|
||||
int curdepth;
|
||||
|
||||
/* If true, we have called stat on the current path. */
|
||||
boolean have_stat;
|
||||
|
||||
/* If true, we know the type of the current path. */
|
||||
boolean have_type;
|
||||
mode_t type; /* this is the actual type */
|
||||
|
||||
/* The file being operated on, relative to the current directory.
|
||||
Used for stat, readlink, remove, and opendir. */
|
||||
char *rel_pathname;
|
||||
|
||||
/* Length of current path. */
|
||||
int path_length;
|
||||
|
||||
/* If true, don't descend past current directory.
|
||||
Can be set by -prune, -maxdepth, and -xdev/-mount. */
|
||||
boolean stop_at_current_level;
|
||||
|
||||
/* Status value to return to system. */
|
||||
int exit_status;
|
||||
};
|
||||
extern struct state state;
|
||||
|
||||
extern char const *starting_dir;
|
||||
extern int starting_desc;
|
||||
#if ! defined HAVE_FCHDIR && ! defined fchdir
|
||||
# define fchdir(fd) (-1)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
extern int exit_status;
|
||||
extern int path_length;
|
||||
extern int (*xstat) ();
|
||||
extern boolean dereference;
|
||||
|
||||
+898
-92
File diff suppressed because it is too large
Load Diff
+1808
-269
File diff suppressed because it is too large
Load Diff
+213
-287
@@ -1,10 +1,10 @@
|
||||
/* fstype.c -- determine type of filesystems that files are on
|
||||
Copyright (C) 1990, 91, 92, 93, 94 Free Software Foundation, Inc.
|
||||
Copyright (C) 1990, 91, 92, 93, 94, 2000, 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
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
|
||||
@@ -12,144 +12,109 @@
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* Written by David MacKenzie <[email protected]>.
|
||||
*
|
||||
* Converted to use gnulib's read_file_system_list()
|
||||
* by James Youngman <[email protected]> (which saves a lot
|
||||
* of manual hacking of configure.in).
|
||||
*/
|
||||
|
||||
/* Written by David MacKenzie <[email protected]>. */
|
||||
|
||||
#include <config.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include "defs.h"
|
||||
#include "modetype.h"
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
/* The presence of unistd.h is assumed by gnulib these days, so we
|
||||
* might as well assume it too.
|
||||
*/
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef HAVE_SYS_MNTIO_H
|
||||
#ifdef HAVE_FCNTL_H
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
#include <sys/mntio.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_MKDEV_H
|
||||
#include <sys/mkdev.h>
|
||||
#endif
|
||||
|
||||
#ifdef STDC_HEADERS
|
||||
#include <stdlib.h>
|
||||
#else
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
char *strdup ();
|
||||
char *strstr ();
|
||||
#include "defs.h"
|
||||
#include "../gnulib/lib/dirname.h"
|
||||
#include "xalloc.h"
|
||||
#include "modetype.h"
|
||||
|
||||
static char *filesystem_type_uncached P_((char *path, char *relpath, struct stat *statp));
|
||||
static int xatoi P_((char *cp));
|
||||
/* Need declaration of function `xstrtoumax' */
|
||||
#include "../gnulib/lib/xstrtol.h"
|
||||
|
||||
#ifdef FSTYPE_MNTENT /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
|
||||
#include <mntent.h>
|
||||
#if !defined(MOUNTED)
|
||||
# if defined(MNT_MNTTAB) /* HP-UX. */
|
||||
# define MOUNTED MNT_MNTTAB
|
||||
# endif
|
||||
# if defined(MNTTABNAME) /* Dynix. */
|
||||
# define MOUNTED MNTTABNAME
|
||||
# endif
|
||||
#include "extendbuf.h"
|
||||
#include "mountlist.h"
|
||||
|
||||
|
||||
|
||||
#if ENABLE_NLS
|
||||
# include <libintl.h>
|
||||
# define _(Text) gettext (Text)
|
||||
#else
|
||||
# define _(Text) Text
|
||||
#endif
|
||||
#ifdef gettext_noop
|
||||
# define N_(String) gettext_noop (String)
|
||||
#else
|
||||
/* See locate.c for explanation as to why not use (String) */
|
||||
# define N_(String) String
|
||||
#endif
|
||||
|
||||
#ifdef FSTYPE_GETMNT /* Ultrix. */
|
||||
#include <sys/param.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/fs_types.h>
|
||||
static char *filesystem_type_uncached PARAMS((const struct stat *statp, const char *path));
|
||||
|
||||
|
||||
/* Get MNTTYPE_IGNORE if it is available. */
|
||||
#if HAVE_MNTENT_H
|
||||
# include <mntent.h>
|
||||
#endif
|
||||
#if HAVE_SYS_MNTTAB_H
|
||||
# include <stdio.h>
|
||||
# include <sys/mnttab.h>
|
||||
#endif
|
||||
|
||||
#ifdef FSTYPE_USG_STATFS /* SVR3. */
|
||||
#include <sys/statfs.h>
|
||||
#include <sys/fstyp.h>
|
||||
#endif
|
||||
|
||||
#ifdef FSTYPE_STATVFS /* SVR4. */
|
||||
#include <sys/statvfs.h>
|
||||
#include <sys/fstyp.h>
|
||||
#endif
|
||||
|
||||
#ifdef FSTYPE_STATFS /* 4.4BSD. */
|
||||
#include <sys/param.h> /* NetBSD needs this. */
|
||||
#include <sys/mount.h>
|
||||
|
||||
#ifndef MFSNAMELEN /* NetBSD defines this. */
|
||||
static char *
|
||||
fstype_to_string (t)
|
||||
short t;
|
||||
|
||||
static void
|
||||
free_file_system_list(struct mount_entry *p)
|
||||
{
|
||||
#ifdef INITMOUNTNAMES /* Defined in 4.4BSD, not in NET/2. */
|
||||
static char *mn[] = INITMOUNTNAMES;
|
||||
if (t >= 0 && t <= MOUNT_MAXTYPE)
|
||||
return mn[t];
|
||||
else
|
||||
return "?";
|
||||
#else /* !INITMOUNTNAMES */
|
||||
switch (t)
|
||||
while (p)
|
||||
{
|
||||
case MOUNT_UFS:
|
||||
return "ufs";
|
||||
case MOUNT_NFS:
|
||||
return "nfs";
|
||||
#ifdef MOUNT_PC
|
||||
case MOUNT_PC:
|
||||
return "pc";
|
||||
#endif
|
||||
#ifdef MOUNT_MFS
|
||||
case MOUNT_MFS:
|
||||
return "mfs";
|
||||
#endif
|
||||
#ifdef MOUNT_LO
|
||||
case MOUNT_LO:
|
||||
return "lofs";
|
||||
#endif
|
||||
#ifdef MOUNT_TFS
|
||||
case MOUNT_TFS:
|
||||
return "tfs";
|
||||
#endif
|
||||
#ifdef MOUNT_TMP
|
||||
case MOUNT_TMP:
|
||||
return "tmp";
|
||||
#endif
|
||||
#ifdef MOUNT_MSDOS
|
||||
case MOUNT_MSDOS:
|
||||
return "msdos";
|
||||
#endif
|
||||
#ifdef MOUNT_ISO9660
|
||||
case MOUNT_ISO9660:
|
||||
return "iso9660fs";
|
||||
#endif
|
||||
default:
|
||||
return "?";
|
||||
}
|
||||
#endif /* !INITMOUNTNAMES */
|
||||
}
|
||||
#endif /* !MFSNAMELEN */
|
||||
#endif /* FSTYPE_STATFS */
|
||||
|
||||
#ifdef FSTYPE_AIX_STATFS /* AIX. */
|
||||
#include <sys/vmount.h>
|
||||
#include <sys/statfs.h>
|
||||
|
||||
#define FSTYPE_STATFS /* Otherwise like 4.4BSD. */
|
||||
#define f_type f_vfstype
|
||||
|
||||
static char *
|
||||
fstype_to_string (t)
|
||||
short t;
|
||||
{
|
||||
switch (t)
|
||||
{
|
||||
case MNT_AIX:
|
||||
#if 0 /* NFS filesystems are actually MNT_AIX. */
|
||||
return "aix";
|
||||
#endif
|
||||
case MNT_NFS:
|
||||
return "nfs";
|
||||
case MNT_JFS:
|
||||
return "jfs";
|
||||
case MNT_CDROM:
|
||||
return "cdrom";
|
||||
default:
|
||||
return "?";
|
||||
struct mount_entry *pnext = p->me_next;
|
||||
|
||||
free(p->me_devname);
|
||||
free(p->me_mountdir);
|
||||
|
||||
if(p->me_type_malloced)
|
||||
free(p->me_type);
|
||||
p->me_next = NULL;
|
||||
free(p);
|
||||
p = pnext;
|
||||
}
|
||||
}
|
||||
#endif /* FSTYPE_AIX_STATFS */
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef AFS
|
||||
#include <netinet/in.h>
|
||||
@@ -165,8 +130,7 @@ fstype_to_string (t)
|
||||
#endif
|
||||
|
||||
static int
|
||||
in_afs (path)
|
||||
char *path;
|
||||
in_afs (char *path)
|
||||
{
|
||||
static char space[2048];
|
||||
struct ViceIoctl vi;
|
||||
@@ -191,10 +155,7 @@ static int fstype_known = 0;
|
||||
Return "unknown" if its filesystem type is unknown. */
|
||||
|
||||
char *
|
||||
filesystem_type (path, relpath, statp)
|
||||
char *path;
|
||||
char *relpath;
|
||||
struct stat *statp;
|
||||
filesystem_type (const struct stat *statp, const char *path)
|
||||
{
|
||||
static char *current_fstype = NULL;
|
||||
static dev_t current_dev;
|
||||
@@ -206,181 +167,146 @@ filesystem_type (path, relpath, statp)
|
||||
free (current_fstype);
|
||||
}
|
||||
current_dev = statp->st_dev;
|
||||
current_fstype = filesystem_type_uncached (path, relpath, statp);
|
||||
current_fstype = filesystem_type_uncached (statp, path);
|
||||
return current_fstype;
|
||||
}
|
||||
|
||||
static int
|
||||
set_fstype_devno(struct mount_entry *p)
|
||||
{
|
||||
struct stat stbuf;
|
||||
|
||||
if (p->me_dev == (dev_t)-1)
|
||||
{
|
||||
if (0 == (options.xstat)(p->me_mountdir, &stbuf))
|
||||
{
|
||||
p->me_dev = stbuf.st_dev;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0; /* not needed */
|
||||
}
|
||||
|
||||
static struct mount_entry *
|
||||
must_read_fs_list(bool need_fs_type)
|
||||
{
|
||||
struct mount_entry *entries = read_file_system_list(need_fs_type);
|
||||
if (NULL == entries)
|
||||
{
|
||||
/* We cannot determine for sure which file we were trying to
|
||||
* use because gnulib has extracted all that stuff away.
|
||||
* Hence we cannot issue a specific error message here.
|
||||
*/
|
||||
error(1, 0, "Cannot read mounted filesystem list");
|
||||
}
|
||||
return entries;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Return a newly allocated string naming the type of filesystem that the
|
||||
file PATH, described by STATP, is on.
|
||||
RELPATH is the file name relative to the current directory.
|
||||
Return "unknown" if its filesystem type is unknown. */
|
||||
|
||||
static char *
|
||||
filesystem_type_uncached (path, relpath, statp)
|
||||
char *path;
|
||||
char *relpath;
|
||||
struct stat *statp;
|
||||
filesystem_type_uncached (const struct stat *statp, const char *path)
|
||||
{
|
||||
char *type = NULL;
|
||||
|
||||
#ifdef FSTYPE_MNTENT /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
|
||||
char *table = MOUNTED;
|
||||
FILE *mfp;
|
||||
struct mntent *mnt;
|
||||
|
||||
mfp = setmntent (table, "r");
|
||||
if (mfp == NULL)
|
||||
error (1, errno, "%s", table);
|
||||
|
||||
/* Find the entry with the same device number as STATP, and return
|
||||
that entry's fstype. */
|
||||
while (type == NULL && (mnt = getmntent (mfp)))
|
||||
{
|
||||
char *devopt;
|
||||
dev_t dev;
|
||||
struct stat disk_stats;
|
||||
|
||||
#ifdef MNTTYPE_IGNORE
|
||||
if (!strcmp (mnt->mnt_type, MNTTYPE_IGNORE))
|
||||
continue;
|
||||
#endif
|
||||
|
||||
/* Newer systems like SunOS 4.1 keep the dev number in the mtab,
|
||||
in the options string. For older systems, we need to stat the
|
||||
directory that the filesystem is mounted on to get it.
|
||||
|
||||
Unfortunately, the HPUX 9.x mnttab entries created by automountq
|
||||
contain a dev= option but the option value does not match the
|
||||
st_dev value of the file (maybe the lower 16 bits match?). */
|
||||
|
||||
#if !defined(hpux) && !defined(__hpux__)
|
||||
devopt = strstr (mnt->mnt_opts, "dev=");
|
||||
if (devopt)
|
||||
{
|
||||
if (devopt[4] == '0' && (devopt[5] == 'x' || devopt[5] == 'X'))
|
||||
dev = xatoi (devopt + 6);
|
||||
else
|
||||
dev = xatoi (devopt + 4);
|
||||
}
|
||||
else
|
||||
#endif /* not hpux */
|
||||
{
|
||||
if (stat (mnt->mnt_dir, &disk_stats) == -1)
|
||||
error (1, errno, "error in %s: %s", table, mnt->mnt_dir);
|
||||
dev = disk_stats.st_dev;
|
||||
}
|
||||
|
||||
if (dev == statp->st_dev)
|
||||
type = mnt->mnt_type;
|
||||
}
|
||||
|
||||
if (endmntent (mfp) == 0)
|
||||
error (0, errno, "%s", table);
|
||||
#endif
|
||||
|
||||
#ifdef FSTYPE_GETMNT /* Ultrix. */
|
||||
int offset = 0;
|
||||
struct fs_data fsd;
|
||||
|
||||
while (type == NULL
|
||||
&& getmnt (&offset, &fsd, sizeof (fsd), NOSTAT_MANY, 0) > 0)
|
||||
{
|
||||
if (fsd.fd_req.dev == statp->st_dev)
|
||||
type = gt_names[fsd.fd_req.fstype];
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef FSTYPE_USG_STATFS /* SVR3. */
|
||||
struct statfs fss;
|
||||
char typebuf[FSTYPSZ];
|
||||
|
||||
if (statfs (relpath, &fss, sizeof (struct statfs), 0) == -1)
|
||||
{
|
||||
/* Don't die if a file was just removed. */
|
||||
if (errno != ENOENT)
|
||||
error (1, errno, "%s", path);
|
||||
}
|
||||
else if (!sysfs (GETFSTYP, fss.f_fstyp, typebuf))
|
||||
type = typebuf;
|
||||
#endif
|
||||
|
||||
#ifdef FSTYPE_STATVFS /* SVR4. */
|
||||
struct statvfs fss;
|
||||
|
||||
if (statvfs (relpath, &fss) == -1)
|
||||
{
|
||||
/* Don't die if a file was just removed. */
|
||||
if (errno != ENOENT)
|
||||
error (1, errno, "%s", path);
|
||||
}
|
||||
else
|
||||
type = fss.f_basetype;
|
||||
#endif
|
||||
|
||||
#ifdef FSTYPE_STATFS /* 4.4BSD. */
|
||||
struct statfs fss;
|
||||
char *p;
|
||||
|
||||
if (S_ISLNK (statp->st_mode))
|
||||
p = dirname (relpath);
|
||||
else
|
||||
p = relpath;
|
||||
|
||||
if (statfs (p, &fss) == -1)
|
||||
{
|
||||
/* Don't die if symlink to nonexisting file, or a file that was
|
||||
just removed. */
|
||||
if (errno != ENOENT)
|
||||
error (1, errno, "%s", path);
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef MFSNAMELEN /* NetBSD. */
|
||||
type = xstrdup (fss.f_fstypename);
|
||||
#else
|
||||
type = fstype_to_string (fss.f_type);
|
||||
#endif
|
||||
}
|
||||
if (p != relpath)
|
||||
free (p);
|
||||
#endif
|
||||
struct mount_entry *entries, *entry;
|
||||
char *type;
|
||||
|
||||
#ifdef AFS
|
||||
if ((!type || !strcmp (type, "xx")) && in_afs (relpath))
|
||||
type = "afs";
|
||||
#endif
|
||||
|
||||
/* An unknown value can be caused by an ENOENT error condition.
|
||||
Don't cache those values. */
|
||||
fstype_known = (type != NULL);
|
||||
|
||||
return xstrdup (type ? type : "unknown");
|
||||
}
|
||||
|
||||
#ifdef FSTYPE_MNTENT /* 4.3BSD etc. */
|
||||
/* Return the value of the hexadecimal number represented by CP.
|
||||
No prefix (like '0x') or suffix (like 'h') is expected to be
|
||||
part of CP. */
|
||||
|
||||
static int
|
||||
xatoi (cp)
|
||||
char *cp;
|
||||
{
|
||||
int val;
|
||||
|
||||
val = 0;
|
||||
while (*cp)
|
||||
if (in_afs(path))
|
||||
{
|
||||
if (*cp >= 'a' && *cp <= 'f')
|
||||
val = val * 16 + *cp - 'a' + 10;
|
||||
else if (*cp >= 'A' && *cp <= 'F')
|
||||
val = val * 16 + *cp - 'A' + 10;
|
||||
else if (*cp >= '0' && *cp <= '9')
|
||||
val = val * 16 + *cp - '0';
|
||||
else
|
||||
break;
|
||||
cp++;
|
||||
fstype_known = 1;
|
||||
return xstrdup("afs");
|
||||
}
|
||||
return val;
|
||||
}
|
||||
#endif
|
||||
|
||||
entries = must_read_fs_list(true);
|
||||
for (type=NULL, entry=entries; entry; entry=entry->me_next)
|
||||
{
|
||||
#ifdef MNTTYPE_IGNORE
|
||||
if (!strcmp (entry->me_type, MNTTYPE_IGNORE))
|
||||
continue;
|
||||
#endif
|
||||
set_fstype_devno(entry);
|
||||
if (entry->me_dev == statp->st_dev)
|
||||
{
|
||||
type = xstrdup(entry->me_type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
free_file_system_list(entries);
|
||||
|
||||
/* Don't cache unknown values. */
|
||||
fstype_known = (type != NULL);
|
||||
|
||||
return type ? type : xstrdup(_("unknown"));
|
||||
}
|
||||
|
||||
|
||||
char *
|
||||
get_mounted_filesystems (void)
|
||||
{
|
||||
char *result = NULL;
|
||||
size_t alloc_size = 0u;
|
||||
size_t used = 0u;
|
||||
struct mount_entry *entries, *entry;
|
||||
|
||||
entries = must_read_fs_list(false);
|
||||
for (entry=entries; entry; entry=entry->me_next)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
#ifdef MNTTYPE_IGNORE
|
||||
if (!strcmp (entry->me_type, MNTTYPE_IGNORE))
|
||||
continue;
|
||||
#endif
|
||||
set_fstype_devno(entry);
|
||||
|
||||
len = strlen(entry->me_mountdir) + 1;
|
||||
result = extendbuf(result, used+len, &alloc_size);
|
||||
strcpy(&result[used], entry->me_mountdir);
|
||||
used += len; /* len already includes one for the \0 */
|
||||
}
|
||||
|
||||
free_file_system_list(entries);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
dev_t *
|
||||
get_mounted_devices (size_t *n)
|
||||
{
|
||||
size_t alloc_size = 0u;
|
||||
size_t used = 0u;
|
||||
struct mount_entry *entries, *entry;
|
||||
dev_t *result = NULL;
|
||||
|
||||
/* Use read_file_system_list() rather than must_read_fs_list()
|
||||
* because on some system this is always called at startup,
|
||||
* and find should only exit fatally if it needs to use the
|
||||
* result of this operation. If we can't get the fs list
|
||||
* but we never need the information, there is no need to fail.
|
||||
*/
|
||||
for (entry = entries = read_file_system_list(false);
|
||||
entry;
|
||||
entry = entry->me_next)
|
||||
{
|
||||
result = extendbuf(result, sizeof(dev_t)*(used+1), &alloc_size);
|
||||
set_fstype_devno(entry);
|
||||
result[used] = entry->me_dev;
|
||||
++used;
|
||||
}
|
||||
free_file_system_list(entries);
|
||||
*n = used;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
+1489
-807
File diff suppressed because it is too large
Load Diff
+1060
-634
File diff suppressed because it is too large
Load Diff
+115
-53
@@ -1,29 +1,41 @@
|
||||
/* tree.c -- helper functions to build and evaluate the expression tree.
|
||||
Copyright (C) 1990, 91, 92, 93, 94 Free Software Foundation, Inc.
|
||||
Copyright (C) 1990, 91, 92, 93, 94, 2000, 2001, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdio.h>
|
||||
#include "defs.h"
|
||||
#include "../gnulib/lib/xalloc.h"
|
||||
|
||||
static struct predicate *scan_rest P_((struct predicate **input, struct predicate *head, int prev_prec));
|
||||
static void merge_pred P_((struct predicate *beg_list, struct predicate *end_list, struct predicate **last_p));
|
||||
static struct predicate *set_new_parent P_((struct predicate *curr, enum predicate_precedence high_prec, struct predicate **prevp));
|
||||
#if ENABLE_NLS
|
||||
# include <libintl.h>
|
||||
# define _(Text) gettext (Text)
|
||||
#else
|
||||
# define _(Text) Text
|
||||
#endif
|
||||
#ifdef gettext_noop
|
||||
# define N_(String) gettext_noop (String)
|
||||
#else
|
||||
/* See locate.c for explanation as to why not use (String) */
|
||||
# define N_(String) String
|
||||
#endif
|
||||
|
||||
static struct predicate *scan_rest PARAMS((struct predicate **input,
|
||||
struct predicate *head,
|
||||
short int prev_prec));
|
||||
static void merge_pred PARAMS((struct predicate *beg_list, struct predicate *end_list, struct predicate **last_p));
|
||||
static struct predicate *set_new_parent PARAMS((struct predicate *curr, enum predicate_precedence high_prec, struct predicate **prevp));
|
||||
|
||||
/* Return a pointer to a tree that represents the
|
||||
expression prior to non-unary operator *INPUT.
|
||||
@@ -45,20 +57,25 @@ static struct predicate *set_new_parent P_((struct predicate *curr, enum predica
|
||||
our caller, so get_expr recurses. */
|
||||
|
||||
struct predicate *
|
||||
get_expr (input, prev_prec)
|
||||
struct predicate **input;
|
||||
short prev_prec;
|
||||
get_expr (struct predicate **input, short int prev_prec)
|
||||
{
|
||||
struct predicate *next;
|
||||
struct predicate *next = NULL;
|
||||
|
||||
if (*input == NULL)
|
||||
error (1, 0, "invalid expression");
|
||||
error (1, 0, _("invalid expression"));
|
||||
|
||||
switch ((*input)->p_type)
|
||||
{
|
||||
case NO_TYPE:
|
||||
error (1, 0, _("invalid expression"));
|
||||
break;
|
||||
|
||||
case BI_OP:
|
||||
error (1, 0, _("invalid expression; you have used a binary operator with nothing before it."));
|
||||
break;
|
||||
|
||||
case CLOSE_PAREN:
|
||||
error (1, 0, "invalid expression");
|
||||
error (1, 0, _("invalid expression; you have too many ')'"));
|
||||
break;
|
||||
|
||||
case PRIMARY_TYPE:
|
||||
@@ -77,12 +94,12 @@ get_expr (input, prev_prec)
|
||||
next = get_expr (input, NO_PREC);
|
||||
if ((*input == NULL)
|
||||
|| ((*input)->p_type != CLOSE_PAREN))
|
||||
error (1, 0, "invalid expression");
|
||||
error (1, 0, _("invalid expression; I was expecting to find a ')' somewhere but did not see one."));
|
||||
*input = (*input)->pred_next; /* move over close */
|
||||
break;
|
||||
|
||||
default:
|
||||
error (1, 0, "oops -- invalid expression type!");
|
||||
error (1, 0, _("oops -- invalid expression type!"));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -97,7 +114,7 @@ get_expr (input, prev_prec)
|
||||
{
|
||||
next = scan_rest (input, next, prev_prec);
|
||||
if (next == NULL)
|
||||
error (1, 0, "invalid expression");
|
||||
error (1, 0, _("invalid expression"));
|
||||
}
|
||||
return (next);
|
||||
}
|
||||
@@ -116,10 +133,9 @@ get_expr (input, prev_prec)
|
||||
PREV_PREC is the precedence of the previous predicate element. */
|
||||
|
||||
static struct predicate *
|
||||
scan_rest (input, head, prev_prec)
|
||||
struct predicate **input;
|
||||
struct predicate *head;
|
||||
short prev_prec;
|
||||
scan_rest (struct predicate **input,
|
||||
struct predicate *head,
|
||||
short int prev_prec)
|
||||
{
|
||||
struct predicate *tree; /* The new tree we are building. */
|
||||
|
||||
@@ -134,7 +150,10 @@ scan_rest (input, head, prev_prec)
|
||||
case PRIMARY_TYPE:
|
||||
case UNI_OP:
|
||||
case OPEN_PAREN:
|
||||
error (1, 0, "invalid expression");
|
||||
/* I'm not sure how we get here, so it is not obvious what
|
||||
* sort of mistakes might give rise to this condition.
|
||||
*/
|
||||
error (1, 0, _("invalid expression"));
|
||||
break;
|
||||
|
||||
case BI_OP:
|
||||
@@ -145,14 +164,16 @@ scan_rest (input, head, prev_prec)
|
||||
break;
|
||||
|
||||
case CLOSE_PAREN:
|
||||
return (tree);
|
||||
return tree;
|
||||
|
||||
default:
|
||||
error (1, 0, "oops -- invalid expression type!");
|
||||
error (1, 0,
|
||||
_("oops -- invalid expression type (%d)!"),
|
||||
(int)(*input)->p_type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (tree);
|
||||
return tree;
|
||||
}
|
||||
|
||||
/* Optimize the ordering of the predicates in the tree. Rearrange
|
||||
@@ -162,9 +183,12 @@ scan_rest (input, head, prev_prec)
|
||||
predicates (if any) which have "side effects", such as printing.
|
||||
The grouping implements the partial ordering on predicates which
|
||||
those with side effects impose.
|
||||
* Place -name, -path, and -regex at the front of a group, with
|
||||
-name and -path ahead of -regex. Predicates that are moved to the
|
||||
front of a group by definition do not have side effects.
|
||||
|
||||
* Place -name, -iname, -path, -ipath, -regex and -iregex at the front
|
||||
of a group, with -name, -iname, -path and -ipath ahead of
|
||||
-regex and -iregex. Predicates which are moved to the front
|
||||
of a group by definition do not have side effects. Both
|
||||
-regex and -iregex both use pred_regex.
|
||||
|
||||
This routine "normalizes" the predicate tree by ensuring that
|
||||
all expression predicates have AND (or OR or COMMA) parent nodes
|
||||
@@ -176,8 +200,7 @@ scan_rest (input, head, prev_prec)
|
||||
Return true if the tree contains side effects, false if not. */
|
||||
|
||||
boolean
|
||||
opt_expr (eval_treep)
|
||||
struct predicate **eval_treep;
|
||||
opt_expr (struct predicate **eval_treep)
|
||||
{
|
||||
/* List of -name and -path predicates to move. */
|
||||
struct predicate *name_list = NULL;
|
||||
@@ -188,7 +211,7 @@ opt_expr (eval_treep)
|
||||
struct predicate *curr;
|
||||
struct predicate **prevp; /* Address of `curr' node. */
|
||||
struct predicate **last_sidep; /* Last predicate with side effects. */
|
||||
PFB pred_func;
|
||||
PRED_FUNC pred_func;
|
||||
enum predicate_type p_type;
|
||||
boolean has_side_effects = false; /* Return value. */
|
||||
enum predicate_precedence prev_prec, /* precedence of last BI_OP in branch */
|
||||
@@ -217,12 +240,13 @@ opt_expr (eval_treep)
|
||||
|
||||
#ifdef DEBUG
|
||||
/* Normalized tree. */
|
||||
printf ("Normalized Eval Tree:\n");
|
||||
print_tree (*eval_treep, 0);
|
||||
fprintf (stderr, "Normalized Eval Tree:\n");
|
||||
print_tree (stderr, *eval_treep, 0);
|
||||
#endif
|
||||
|
||||
/* Rearrange the predicates. */
|
||||
prevp = eval_treep;
|
||||
biop_prec = NO_PREC; /* not COMMA_PREC */
|
||||
if ((*prevp) && (*prevp)->p_type == BI_OP)
|
||||
biop_prec = (*prevp)->p_prec;
|
||||
while ((curr = *prevp) != NULL)
|
||||
@@ -237,8 +261,6 @@ opt_expr (eval_treep)
|
||||
{
|
||||
if (curr->p_prec != biop_prec)
|
||||
curr = set_new_parent(curr, biop_prec, prevp);
|
||||
else
|
||||
biop_prec = curr->p_prec;
|
||||
}
|
||||
|
||||
/* See which predicate type we have. */
|
||||
@@ -249,9 +271,15 @@ opt_expr (eval_treep)
|
||||
{
|
||||
case NO_TYPE:
|
||||
case PRIMARY_TYPE:
|
||||
/* Don't rearrange the arguments of the comma operator, it is
|
||||
not commutative. */
|
||||
if (biop_prec == COMMA_PREC)
|
||||
break;
|
||||
|
||||
/* If it's one of our special primaries, move it to the
|
||||
front of the list for that primary. */
|
||||
if (pred_func == pred_name || pred_func == pred_path)
|
||||
if (pred_func == pred_name || pred_func == pred_path ||
|
||||
pred_func == pred_iname || pred_func == pred_ipath)
|
||||
{
|
||||
*prevp = curr->pred_left;
|
||||
curr->pred_left = name_list;
|
||||
@@ -293,7 +321,7 @@ opt_expr (eval_treep)
|
||||
all of the user's parentheses. */
|
||||
|
||||
default:
|
||||
error (1, 0, "oops -- invalid expression type!");
|
||||
error (1, 0, _("oops -- invalid expression type!"));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -334,10 +362,7 @@ opt_expr (eval_treep)
|
||||
HIGH_PREC. */
|
||||
|
||||
static struct predicate *
|
||||
set_new_parent (curr, high_prec, prevp)
|
||||
struct predicate *curr;
|
||||
enum predicate_precedence high_prec;
|
||||
struct predicate **prevp;
|
||||
set_new_parent (struct predicate *curr, enum predicate_precedence high_prec, struct predicate **prevp)
|
||||
{
|
||||
struct predicate *new_parent;
|
||||
|
||||
@@ -345,6 +370,7 @@ set_new_parent (curr, high_prec, prevp)
|
||||
new_parent->p_type = BI_OP;
|
||||
new_parent->p_prec = high_prec;
|
||||
new_parent->need_stat = false;
|
||||
new_parent->need_type = false;
|
||||
|
||||
switch (high_prec)
|
||||
{
|
||||
@@ -362,6 +388,7 @@ set_new_parent (curr, high_prec, prevp)
|
||||
}
|
||||
|
||||
new_parent->side_effects = false;
|
||||
new_parent->no_default_print = false;
|
||||
new_parent->args.str = NULL;
|
||||
new_parent->pred_next = NULL;
|
||||
|
||||
@@ -382,8 +409,7 @@ set_new_parent (curr, high_prec, prevp)
|
||||
into the tree at LAST_P. */
|
||||
|
||||
static void
|
||||
merge_pred (beg_list, end_list, last_p)
|
||||
struct predicate *beg_list, *end_list, **last_p;
|
||||
merge_pred (struct predicate *beg_list, struct predicate *end_list, struct predicate **last_p)
|
||||
{
|
||||
end_list->pred_left = *last_p;
|
||||
*last_p = beg_list;
|
||||
@@ -400,8 +426,7 @@ merge_pred (beg_list, end_list, last_p)
|
||||
in TREE requires a stat, false if not. */
|
||||
|
||||
boolean
|
||||
mark_stat (tree)
|
||||
struct predicate *tree;
|
||||
mark_stat (struct predicate *tree)
|
||||
{
|
||||
/* The tree is executed in-order, so walk this way (apologies to Aerosmith)
|
||||
to find the first predicate for which the stat is needed. */
|
||||
@@ -427,7 +452,44 @@ mark_stat (tree)
|
||||
return (false);
|
||||
|
||||
default:
|
||||
error (1, 0, "oops -- invalid expression type!");
|
||||
error (1, 0, _("oops -- invalid expression type in mark_stat!"));
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
|
||||
/* Find the first node in expression tree TREE that we will
|
||||
need to know the file type, if any. Operates in the same
|
||||
was as mark_stat().
|
||||
*/
|
||||
boolean
|
||||
mark_type (struct predicate *tree)
|
||||
{
|
||||
/* The tree is executed in-order, so walk this way (apologies to Aerosmith)
|
||||
to find the first predicate for which the type information is needed. */
|
||||
switch (tree->p_type)
|
||||
{
|
||||
case NO_TYPE:
|
||||
case PRIMARY_TYPE:
|
||||
return tree->need_type;
|
||||
|
||||
case UNI_OP:
|
||||
if (mark_type (tree->pred_right))
|
||||
tree->need_type = true;
|
||||
return false;
|
||||
|
||||
case BI_OP:
|
||||
/* ANDs and ORs are linked along ->left ending in NULL. */
|
||||
if (tree->pred_left != NULL)
|
||||
mark_type (tree->pred_left);
|
||||
|
||||
if (mark_type (tree->pred_right))
|
||||
tree->need_type = true;
|
||||
|
||||
return false;
|
||||
|
||||
default:
|
||||
error (1, 0, _("oops -- invalid expression type in mark_type!"));
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,43 +1,38 @@
|
||||
/* util.c -- functions for initializing new tree elements, and other things.
|
||||
Copyright (C) 1990, 91, 92, 93, 94 Free Software Foundation, Inc.
|
||||
Copyright (C) 1990, 91, 92, 93, 94, 2000, 2001, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdio.h>
|
||||
#include "defs.h"
|
||||
|
||||
/* Return the last component of pathname FNAME, with leading slashes
|
||||
compressed into one slash. */
|
||||
#include "xalloc.h"
|
||||
|
||||
char *
|
||||
basename (fname)
|
||||
char *fname;
|
||||
{
|
||||
char *p;
|
||||
#if ENABLE_NLS
|
||||
# include <libintl.h>
|
||||
# define _(Text) gettext (Text)
|
||||
#else
|
||||
# define _(Text) Text
|
||||
#endif
|
||||
#ifdef gettext_noop
|
||||
# define N_(String) gettext_noop (String)
|
||||
#else
|
||||
/* See locate.c for explanation as to why not use (String) */
|
||||
# define N_(String) String
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
/* For "/", "//", etc., return "/". */
|
||||
for (p = fname; *p == '/'; ++p)
|
||||
/* Do nothing. */ ;
|
||||
if (*p == '\0')
|
||||
return p - 1;
|
||||
p = strrchr (fname, '/');
|
||||
return (p == NULL ? fname : p + 1);
|
||||
}
|
||||
|
||||
/* Return a pointer to a new predicate structure, which has been
|
||||
linked in as the last one in the predicates list.
|
||||
@@ -48,10 +43,15 @@ basename (fname)
|
||||
Set all cells in the new structure to the default values. */
|
||||
|
||||
struct predicate *
|
||||
get_new_pred ()
|
||||
get_new_pred (const struct parser_table *entry)
|
||||
{
|
||||
register struct predicate *new_pred;
|
||||
(void) entry;
|
||||
|
||||
/* Options should not be turned into predicates. */
|
||||
assert(entry->type != ARG_OPTION);
|
||||
assert(entry->type != ARG_POSITIONAL_OPTION);
|
||||
|
||||
if (predicates == NULL)
|
||||
{
|
||||
predicates = (struct predicate *)
|
||||
@@ -64,6 +64,7 @@ get_new_pred ()
|
||||
last_pred->pred_next = new_pred;
|
||||
last_pred = new_pred;
|
||||
}
|
||||
last_pred->parser_entry = entry;
|
||||
last_pred->pred_func = NULL;
|
||||
#ifdef DEBUG
|
||||
last_pred->p_name = NULL;
|
||||
@@ -71,7 +72,9 @@ get_new_pred ()
|
||||
last_pred->p_type = NO_TYPE;
|
||||
last_pred->p_prec = NO_PREC;
|
||||
last_pred->side_effects = false;
|
||||
last_pred->no_default_print = false;
|
||||
last_pred->need_stat = true;
|
||||
last_pred->need_type = true;
|
||||
last_pred->args.str = NULL;
|
||||
last_pred->pred_next = NULL;
|
||||
last_pred->pred_left = NULL;
|
||||
@@ -84,20 +87,29 @@ get_new_pred ()
|
||||
predicate is an operator. If it isn't, the AND operator is inserted. */
|
||||
|
||||
struct predicate *
|
||||
get_new_pred_chk_op ()
|
||||
get_new_pred_chk_op (const struct parser_table *entry)
|
||||
{
|
||||
struct predicate *new_pred;
|
||||
static const struct parser_table *entry_and = NULL;
|
||||
|
||||
/* Locate the entry in the parser table for the "and" operator */
|
||||
if (NULL == entry_and)
|
||||
entry_and = find_parser("and");
|
||||
|
||||
/* Check that it's actually there. If not, that is a bug.*/
|
||||
assert(entry_and != NULL);
|
||||
|
||||
if (last_pred)
|
||||
switch (last_pred->p_type)
|
||||
{
|
||||
case NO_TYPE:
|
||||
error (1, 0, "oops -- invalid default insertion of and!");
|
||||
error (1, 0, _("oops -- invalid default insertion of and!"));
|
||||
break;
|
||||
|
||||
case PRIMARY_TYPE:
|
||||
case CLOSE_PAREN:
|
||||
new_pred = get_new_pred ();
|
||||
/* We need to interpose the and operator. */
|
||||
new_pred = get_new_pred (entry_and);
|
||||
new_pred->pred_func = pred_and;
|
||||
#ifdef DEBUG
|
||||
new_pred->p_name = find_pred_name (pred_and);
|
||||
@@ -105,15 +117,22 @@ get_new_pred_chk_op ()
|
||||
new_pred->p_type = BI_OP;
|
||||
new_pred->p_prec = AND_PREC;
|
||||
new_pred->need_stat = false;
|
||||
new_pred->need_type = false;
|
||||
new_pred->args.str = NULL;
|
||||
new_pred->side_effects = false;
|
||||
new_pred->no_default_print = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return (get_new_pred ());
|
||||
|
||||
new_pred = get_new_pred (entry);
|
||||
new_pred->parser_entry = entry;
|
||||
return new_pred;
|
||||
}
|
||||
|
||||
/* Add a primary of predicate type PRED_FUNC to the predicate input list.
|
||||
/* Add a primary of predicate type PRED_FUNC (described by ENTRY) to the predicate input list.
|
||||
|
||||
Return a pointer to the predicate node just inserted.
|
||||
|
||||
@@ -130,29 +149,51 @@ get_new_pred_chk_op ()
|
||||
operator. */
|
||||
|
||||
struct predicate *
|
||||
insert_primary (pred_func)
|
||||
boolean (*pred_func) ();
|
||||
insert_primary_withpred (const struct parser_table *entry, PRED_FUNC pred_func)
|
||||
{
|
||||
struct predicate *new_pred;
|
||||
|
||||
new_pred = get_new_pred_chk_op ();
|
||||
new_pred = get_new_pred_chk_op (entry);
|
||||
new_pred->pred_func = pred_func;
|
||||
#ifdef DEBUG
|
||||
new_pred->p_name = find_pred_name (pred_func);
|
||||
new_pred->p_name = entry->parser_name;
|
||||
#endif /* DEBUG */
|
||||
new_pred->args.str = NULL;
|
||||
new_pred->p_type = PRIMARY_TYPE;
|
||||
new_pred->p_prec = NO_PREC;
|
||||
return (new_pred);
|
||||
return new_pred;
|
||||
}
|
||||
|
||||
/* Add a primary described by ENTRY to the predicate input list.
|
||||
|
||||
Return a pointer to the predicate node just inserted.
|
||||
|
||||
Fills in the following cells of the new predicate node:
|
||||
|
||||
pred_func PRED_FUNC
|
||||
args(.str) NULL
|
||||
p_type PRIMARY_TYPE
|
||||
p_prec NO_PREC
|
||||
|
||||
Other cells that need to be filled in are defaulted by
|
||||
get_new_pred_chk_op, which is used to insure that the prior node is
|
||||
either not there at all (we are the very first node) or is an
|
||||
operator. */
|
||||
struct predicate *
|
||||
insert_primary (const struct parser_table *entry)
|
||||
{
|
||||
assert(entry->pred_func != NULL);
|
||||
return insert_primary_withpred(entry, entry->pred_func);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
usage (msg)
|
||||
char *msg;
|
||||
usage (char *msg)
|
||||
{
|
||||
if (msg)
|
||||
fprintf (stderr, "%s: %s\n", program_name, msg);
|
||||
fprintf (stderr, "\
|
||||
Usage: %s [path...] [expression]\n", program_name);
|
||||
fprintf (stderr, _("\
|
||||
Usage: %s [-H] [-L] [-P] [path...] [expression]\n"), program_name);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
char *version_string = "4.1";
|
||||
#include <config.h>
|
||||
char *version_string = VERSION;
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
resource app_version
|
||||
{
|
||||
major = 4,
|
||||
middle = 1,
|
||||
minor = 0,
|
||||
middle = 2,
|
||||
minor = 33,
|
||||
variety = 5,
|
||||
internal = 0,
|
||||
short_info = "4.1",
|
||||
long_info = "4.1 ©1994 The Free Software Foundation"
|
||||
short_info = "4.2.33",
|
||||
long_info = "4.2.33 ©2008 The Free Software Foundation"
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
SubDir HAIKU_TOP src bin findutils gnulib ;
|
||||
|
||||
SubInclude HAIKU_TOP src bin findutils gnulib lib ;
|
||||
@@ -0,0 +1,58 @@
|
||||
SubDir HAIKU_TOP src bin findutils gnulib lib ;
|
||||
|
||||
SubDirSysHdrs [ FDirName $(SUBDIR) ] ;
|
||||
SubDirSysHdrs [ FDirName $(SUBDIR) $(DOTDOT) $(DOTDOT) ] ;
|
||||
|
||||
# filter warnings we don't want here
|
||||
TARGET_WARNING_CCFLAGS = [ FFilter $(TARGET_WARNING_CCFLAGS)
|
||||
: -Wall -Wmissing-prototypes -Wsign-compare ] ;
|
||||
|
||||
# set some additional defines
|
||||
{
|
||||
SubDirCcFlags -DHAVE_CONFIG_H ;
|
||||
}
|
||||
|
||||
|
||||
StaticLibrary gnulibfindutils.a :
|
||||
areadlink-with-size.c
|
||||
argmatch.c
|
||||
basename.c
|
||||
canonicalize.c
|
||||
closein.c
|
||||
closeout.c
|
||||
close-stream.c
|
||||
dirname.c
|
||||
dup-safer.c
|
||||
error.c
|
||||
exitfail.c
|
||||
filemode.c
|
||||
file-set.c
|
||||
fnmatch.c
|
||||
fopen-safer.c
|
||||
fpending.c
|
||||
freadahead.c
|
||||
getcwd.c
|
||||
hash.c
|
||||
hash-pjw.c
|
||||
hash-triple.c
|
||||
human.c
|
||||
idcache.c
|
||||
localcharset.c
|
||||
modechange.c
|
||||
mountlist.c
|
||||
quote.c
|
||||
quotearg.c
|
||||
regex.c
|
||||
same.c
|
||||
stripslash.c
|
||||
strndup.c
|
||||
xalloc-die.c
|
||||
xgetcwd.c
|
||||
xmalloc.c
|
||||
xstrndup.c
|
||||
xstrtol-error.c
|
||||
xstrtoumax.c
|
||||
yesno.c
|
||||
;
|
||||
|
||||
#SEARCH on [ FGristFiles version.c ] = [ FDirName $(SUBDIR) $(DOTDOT) find ] ;
|
||||
@@ -21,12 +21,22 @@
|
||||
allocating any. It is a good idea to use alloca(0) in
|
||||
your main control loop, etc. to force garbage collection. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <alloca.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef emacs
|
||||
#include "blockinput.h"
|
||||
# include "lisp.h"
|
||||
# include "blockinput.h"
|
||||
# ifdef EMACS_FREE
|
||||
# undef free
|
||||
# define free EMACS_FREE
|
||||
# endif
|
||||
#else
|
||||
# define memory_full() abort ()
|
||||
#endif
|
||||
|
||||
/* If compiling with GCC 2, this file's not needed. */
|
||||
@@ -34,54 +44,33 @@
|
||||
|
||||
/* If someone has defined alloca as a macro,
|
||||
there must be some other way alloca is supposed to work. */
|
||||
#ifndef alloca
|
||||
# ifndef alloca
|
||||
|
||||
#ifdef emacs
|
||||
#ifdef static
|
||||
# ifdef emacs
|
||||
# ifdef static
|
||||
/* actually, only want this if static is defined as ""
|
||||
-- this is for usg, in which emacs must undefine static
|
||||
in order to make unexec workable
|
||||
*/
|
||||
#ifndef STACK_DIRECTION
|
||||
# ifndef STACK_DIRECTION
|
||||
you
|
||||
lose
|
||||
-- must know STACK_DIRECTION at compile-time
|
||||
#endif /* STACK_DIRECTION undefined */
|
||||
#endif /* static */
|
||||
#endif /* emacs */
|
||||
/* Using #error here is not wise since this file should work for
|
||||
old and obscure compilers. */
|
||||
# endif /* STACK_DIRECTION undefined */
|
||||
# endif /* static */
|
||||
# endif /* emacs */
|
||||
|
||||
/* If your stack is a linked list of frames, you have to
|
||||
provide an "address metric" ADDRESS_FUNCTION macro. */
|
||||
|
||||
#if defined (CRAY) && defined (CRAY_STACKSEG_END)
|
||||
# if defined (CRAY) && defined (CRAY_STACKSEG_END)
|
||||
long i00afunc ();
|
||||
#define ADDRESS_FUNCTION(arg) (char *) i00afunc (&(arg))
|
||||
#else
|
||||
#define ADDRESS_FUNCTION(arg) &(arg)
|
||||
#endif
|
||||
|
||||
#if __STDC__
|
||||
typedef void *pointer;
|
||||
#else
|
||||
typedef char *pointer;
|
||||
#endif
|
||||
|
||||
#define NULL 0
|
||||
|
||||
/* Different portions of Emacs need to call different versions of
|
||||
malloc. The Emacs executable needs alloca to call xmalloc, because
|
||||
ordinary malloc isn't protected from input signals. On the other
|
||||
hand, the utilities in lib-src need alloca to call malloc; some of
|
||||
them are very simple, and don't have an xmalloc routine.
|
||||
|
||||
Non-Emacs programs expect this to call use xmalloc.
|
||||
|
||||
Callers below should use malloc. */
|
||||
|
||||
#ifndef emacs
|
||||
#define malloc xmalloc
|
||||
#endif
|
||||
extern pointer malloc ();
|
||||
# define ADDRESS_FUNCTION(arg) (char *) i00afunc (&(arg))
|
||||
# else
|
||||
# define ADDRESS_FUNCTION(arg) &(arg)
|
||||
# endif
|
||||
|
||||
/* Define STACK_DIRECTION if you know the direction of stack
|
||||
growth for your system; otherwise it will be automatically
|
||||
@@ -91,21 +80,21 @@ extern pointer malloc ();
|
||||
STACK_DIRECTION < 0 => grows toward lower addresses
|
||||
STACK_DIRECTION = 0 => direction of growth unknown */
|
||||
|
||||
#ifndef STACK_DIRECTION
|
||||
#define STACK_DIRECTION 0 /* Direction unknown. */
|
||||
#endif
|
||||
# ifndef STACK_DIRECTION
|
||||
# define STACK_DIRECTION 0 /* Direction unknown. */
|
||||
# endif
|
||||
|
||||
#if STACK_DIRECTION != 0
|
||||
# if STACK_DIRECTION != 0
|
||||
|
||||
#define STACK_DIR STACK_DIRECTION /* Known at compile-time. */
|
||||
# define STACK_DIR STACK_DIRECTION /* Known at compile-time. */
|
||||
|
||||
#else /* STACK_DIRECTION == 0; need run-time code. */
|
||||
# else /* STACK_DIRECTION == 0; need run-time code. */
|
||||
|
||||
static int stack_dir; /* 1 or -1 once known. */
|
||||
#define STACK_DIR stack_dir
|
||||
# define STACK_DIR stack_dir
|
||||
|
||||
static void
|
||||
find_stack_direction ()
|
||||
find_stack_direction (void)
|
||||
{
|
||||
static char *addr = NULL; /* Address of first `dummy', once known. */
|
||||
auto char dummy; /* To get stack address. */
|
||||
@@ -126,7 +115,7 @@ find_stack_direction ()
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* STACK_DIRECTION == 0 */
|
||||
# endif /* STACK_DIRECTION == 0 */
|
||||
|
||||
/* An "alloca header" is used to:
|
||||
(a) chain together all alloca'ed blocks;
|
||||
@@ -135,9 +124,9 @@ find_stack_direction ()
|
||||
It is very important that sizeof(header) agree with malloc
|
||||
alignment chunk size. The following default should work okay. */
|
||||
|
||||
#ifndef ALIGN_SIZE
|
||||
#define ALIGN_SIZE sizeof(double)
|
||||
#endif
|
||||
# ifndef ALIGN_SIZE
|
||||
# define ALIGN_SIZE sizeof(double)
|
||||
# endif
|
||||
|
||||
typedef union hdr
|
||||
{
|
||||
@@ -158,27 +147,26 @@ static header *last_alloca_header = NULL; /* -> last alloca header. */
|
||||
caller, but that method cannot be made to work for some
|
||||
implementations of C, for example under Gould's UTX/32. */
|
||||
|
||||
pointer
|
||||
alloca (size)
|
||||
unsigned size;
|
||||
void *
|
||||
alloca (size_t size)
|
||||
{
|
||||
auto char probe; /* Probes stack depth: */
|
||||
register char *depth = ADDRESS_FUNCTION (probe);
|
||||
|
||||
#if STACK_DIRECTION == 0
|
||||
# if STACK_DIRECTION == 0
|
||||
if (STACK_DIR == 0) /* Unknown growth direction. */
|
||||
find_stack_direction ();
|
||||
#endif
|
||||
# endif
|
||||
|
||||
/* Reclaim garbage, defined as all alloca'd storage that
|
||||
was allocated from deeper in the stack than currently. */
|
||||
was allocated from deeper in the stack than currently. */
|
||||
|
||||
{
|
||||
register header *hp; /* Traverses linked list. */
|
||||
|
||||
#ifdef emacs
|
||||
# ifdef emacs
|
||||
BLOCK_INPUT;
|
||||
#endif
|
||||
# endif
|
||||
|
||||
for (hp = last_alloca_header; hp != NULL;)
|
||||
if ((STACK_DIR > 0 && hp->h.deep > depth)
|
||||
@@ -186,7 +174,7 @@ alloca (size)
|
||||
{
|
||||
register header *np = hp->h.next;
|
||||
|
||||
free ((pointer) hp); /* Collect garbage. */
|
||||
free (hp); /* Collect garbage. */
|
||||
|
||||
hp = np; /* -> next header. */
|
||||
}
|
||||
@@ -195,9 +183,9 @@ alloca (size)
|
||||
|
||||
last_alloca_header = hp; /* -> last valid storage. */
|
||||
|
||||
#ifdef emacs
|
||||
# ifdef emacs
|
||||
UNBLOCK_INPUT;
|
||||
#endif
|
||||
# endif
|
||||
}
|
||||
|
||||
if (size == 0)
|
||||
@@ -206,29 +194,38 @@ alloca (size)
|
||||
/* Allocate combined header + user data storage. */
|
||||
|
||||
{
|
||||
register pointer new = malloc (sizeof (header) + size);
|
||||
/* Address of header. */
|
||||
register header *new;
|
||||
|
||||
((header *) new)->h.next = last_alloca_header;
|
||||
((header *) new)->h.deep = depth;
|
||||
size_t combined_size = sizeof (header) + size;
|
||||
if (combined_size < sizeof (header))
|
||||
memory_full ();
|
||||
|
||||
last_alloca_header = (header *) new;
|
||||
new = malloc (combined_size);
|
||||
|
||||
if (! new)
|
||||
memory_full ();
|
||||
|
||||
new->h.next = last_alloca_header;
|
||||
new->h.deep = depth;
|
||||
|
||||
last_alloca_header = new;
|
||||
|
||||
/* User storage begins just after header. */
|
||||
|
||||
return (pointer) ((char *) new + sizeof (header));
|
||||
return (void *) (new + 1);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined (CRAY) && defined (CRAY_STACKSEG_END)
|
||||
# if defined (CRAY) && defined (CRAY_STACKSEG_END)
|
||||
|
||||
#ifdef DEBUG_I00AFUNC
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
# ifdef DEBUG_I00AFUNC
|
||||
# include <stdio.h>
|
||||
# endif
|
||||
|
||||
#ifndef CRAY_STACK
|
||||
#define CRAY_STACK
|
||||
#ifndef CRAY2
|
||||
# ifndef CRAY_STACK
|
||||
# define CRAY_STACK
|
||||
# ifndef CRAY2
|
||||
/* Stack structures for CRAY-1, CRAY X-MP, and CRAY Y-MP */
|
||||
struct stack_control_header
|
||||
{
|
||||
@@ -280,7 +277,7 @@ struct stack_segment_linkage
|
||||
long sss7;
|
||||
};
|
||||
|
||||
#else /* CRAY2 */
|
||||
# else /* CRAY2 */
|
||||
/* The following structure defines the vector of words
|
||||
returned by the STKSTAT library routine. */
|
||||
struct stk_stat
|
||||
@@ -333,12 +330,12 @@ struct stk_trailer
|
||||
long unknown14;
|
||||
};
|
||||
|
||||
#endif /* CRAY2 */
|
||||
#endif /* not CRAY_STACK */
|
||||
# endif /* CRAY2 */
|
||||
# endif /* not CRAY_STACK */
|
||||
|
||||
#ifdef CRAY2
|
||||
# ifdef CRAY2
|
||||
/* Determine a "stack measure" for an arbitrary ADDRESS.
|
||||
I doubt that "lint" will like this much. */
|
||||
I doubt that "lint" will like this much. */
|
||||
|
||||
static long
|
||||
i00afunc (long *address)
|
||||
@@ -407,7 +404,7 @@ i00afunc (long *address)
|
||||
return (result);
|
||||
}
|
||||
|
||||
#else /* not CRAY2 */
|
||||
# else /* not CRAY2 */
|
||||
/* Stack address function for a CRAY-1, CRAY X-MP, or CRAY Y-MP.
|
||||
Determine the number of the cell within the stack,
|
||||
given the address of the cell. The purpose of this
|
||||
@@ -452,9 +449,9 @@ i00afunc (long address)
|
||||
|
||||
while (!(this_segment <= address && address <= stkl))
|
||||
{
|
||||
#ifdef DEBUG_I00AFUNC
|
||||
# ifdef DEBUG_I00AFUNC
|
||||
fprintf (stderr, "%011o %011o %011o\n", this_segment, address, stkl);
|
||||
#endif
|
||||
# endif
|
||||
if (pseg == 0)
|
||||
break;
|
||||
stkl = stkl - pseg;
|
||||
@@ -473,9 +470,9 @@ i00afunc (long address)
|
||||
|
||||
while (pseg != 0)
|
||||
{
|
||||
#ifdef DEBUG_I00AFUNC
|
||||
# ifdef DEBUG_I00AFUNC
|
||||
fprintf (stderr, "%011o %011o\n", pseg, size);
|
||||
#endif
|
||||
# endif
|
||||
stkl = stkl - pseg;
|
||||
ssptr = (struct stack_segment_linkage *) stkl;
|
||||
size = ssptr->sssize;
|
||||
@@ -485,8 +482,8 @@ i00afunc (long address)
|
||||
return (result);
|
||||
}
|
||||
|
||||
#endif /* not CRAY2 */
|
||||
#endif /* CRAY */
|
||||
# endif /* not CRAY2 */
|
||||
# endif /* CRAY */
|
||||
|
||||
#endif /* no alloca */
|
||||
#endif /* not GCC version 2 */
|
||||
# endif /* no alloca */
|
||||
#endif /* not GCC version 3 */
|
||||
@@ -0,0 +1,55 @@
|
||||
/* DO NOT EDIT! GENERATED AUTOMATICALLY! */
|
||||
/* Memory allocation on the stack.
|
||||
|
||||
Copyright (C) 1995, 1999, 2001-2004, 2006-2007 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, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
USA. */
|
||||
|
||||
/* 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
|
||||
# else
|
||||
# include <stddef.h>
|
||||
# ifdef __cplusplus
|
||||
extern "C"
|
||||
# endif
|
||||
void *alloca (size_t);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif /* _GL_ALLOCA_H */
|
||||
@@ -0,0 +1,54 @@
|
||||
/* Memory allocation on the stack.
|
||||
|
||||
Copyright (C) 1995, 1999, 2001-2004, 2006-2007 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, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
USA. */
|
||||
|
||||
/* 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
|
||||
# else
|
||||
# include <stddef.h>
|
||||
# ifdef __cplusplus
|
||||
extern "C"
|
||||
# endif
|
||||
void *alloca (size_t);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif /* _GL_ALLOCA_H */
|
||||
@@ -0,0 +1,108 @@
|
||||
/* readlink wrapper to return the link name in malloc'd storage.
|
||||
Unlike xreadlink and xreadlink_with_size, don't ever call exit.
|
||||
|
||||
Copyright (C) 2001, 2003-2007 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/>. */
|
||||
|
||||
/* Written by Jim Meyering <[email protected]> */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "areadlink.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifndef SIZE_MAX
|
||||
# define SIZE_MAX ((size_t) -1)
|
||||
#endif
|
||||
#ifndef SSIZE_MAX
|
||||
# define SSIZE_MAX ((ssize_t) (SIZE_MAX / 2))
|
||||
#endif
|
||||
|
||||
/* SYMLINK_MAX is used only for an initial memory-allocation sanity
|
||||
check, so it's OK to guess too small on hosts where there is no
|
||||
arbitrary limit to symbolic link length. */
|
||||
#ifndef SYMLINK_MAX
|
||||
# define SYMLINK_MAX 1024
|
||||
#endif
|
||||
|
||||
#define MAXSIZE (SIZE_MAX < SSIZE_MAX ? SIZE_MAX : SSIZE_MAX)
|
||||
|
||||
/* Call readlink to get the symbolic link value of FILE.
|
||||
SIZE is a hint as to how long the link is expected to be;
|
||||
typically it is taken from st_size. It need not be correct.
|
||||
Return a pointer to that NUL-terminated string in malloc'd storage.
|
||||
If readlink fails, malloc fails, or if the link value is longer
|
||||
than SSIZE_MAX, return NULL (caller may use errno to diagnose). */
|
||||
|
||||
char *
|
||||
areadlink_with_size (char const *file, size_t size)
|
||||
{
|
||||
/* Some buggy file systems report garbage in st_size. Defend
|
||||
against them by ignoring outlandish st_size values in the initial
|
||||
memory allocation. */
|
||||
size_t symlink_max = SYMLINK_MAX;
|
||||
size_t INITIAL_LIMIT_BOUND = 8 * 1024;
|
||||
size_t initial_limit = (symlink_max < INITIAL_LIMIT_BOUND
|
||||
? symlink_max + 1
|
||||
: INITIAL_LIMIT_BOUND);
|
||||
|
||||
/* The initial buffer size for the link value. */
|
||||
size_t buf_size = size < initial_limit ? size + 1 : initial_limit;
|
||||
|
||||
while (1)
|
||||
{
|
||||
ssize_t r;
|
||||
size_t link_length;
|
||||
char *buffer = malloc (buf_size);
|
||||
|
||||
if (buffer == NULL)
|
||||
return NULL;
|
||||
r = readlink (file, buffer, buf_size);
|
||||
link_length = r;
|
||||
|
||||
/* On AIX 5L v5.3 and HP-UX 11i v2 04/09, readlink returns -1
|
||||
with errno == ERANGE if the buffer is too small. */
|
||||
if (r < 0 && errno != ERANGE)
|
||||
{
|
||||
int saved_errno = errno;
|
||||
free (buffer);
|
||||
errno = saved_errno;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (link_length < buf_size)
|
||||
{
|
||||
buffer[link_length] = 0;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
free (buffer);
|
||||
if (buf_size <= MAXSIZE / 2)
|
||||
buf_size *= 2;
|
||||
else if (buf_size < MAXSIZE)
|
||||
buf_size = MAXSIZE;
|
||||
else
|
||||
{
|
||||
errno = ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/* Read symbolic links without size limitation.
|
||||
|
||||
Copyright (C) 2001, 2003, 2004, 2007 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/>. */
|
||||
|
||||
/* Written by Jim Meyering <[email protected]> */
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
extern char *areadlink (char const *filename);
|
||||
extern char *areadlink_with_size (char const *filename, size_t size_hint);
|
||||
@@ -0,0 +1,277 @@
|
||||
/* argmatch.c -- find a match for a string in an array
|
||||
|
||||
Copyright (C) 1990, 1998, 1999, 2001, 2002, 2003, 2004, 2005, 2006, 2007
|
||||
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/>. */
|
||||
|
||||
/* Written by David MacKenzie <[email protected]>
|
||||
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"
|
||||
|
||||
#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 */
|
||||
fprintf (stderr, _("Valid arguments are:"));
|
||||
for (i = 0; arglist[i]; i++)
|
||||
if ((i == 0)
|
||||
|| memcmp (last_val, vallist + valsize * i, valsize))
|
||||
{
|
||||
fprintf (stderr, "\n - `%s'", arglist[i]);
|
||||
last_val = vallist + valsize * i;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf (stderr, ", `%s'", 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>
|
||||
*/
|
||||
char *program_name;
|
||||
|
||||
/* 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;
|
||||
|
||||
program_name = (char *) argv[0];
|
||||
|
||||
if (argc > 2)
|
||||
{
|
||||
fprintf (stderr, "Usage: %s [VERSION_CONTROL]\n", program_name);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if ((cp = getenv ("VERSION_CONTROL")))
|
||||
backup_type = XARGMATCH ("$VERSION_CONTROL", cp,
|
||||
backup_args, backup_vals);
|
||||
|
||||
if (argc == 2)
|
||||
backup_type = XARGMATCH (program_name, 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
|
||||
@@ -0,0 +1,102 @@
|
||||
/* argmatch.h -- definitions and prototypes for argmatch.c
|
||||
|
||||
Copyright (C) 1990, 1998, 1999, 2001, 2002, 2004, 2005 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/>. */
|
||||
|
||||
/* Written by David MacKenzie <[email protected]>
|
||||
Modified by Akim Demaille <demaille@inf.enst.fr> */
|
||||
|
||||
#ifndef ARGMATCH_H_
|
||||
# define ARGMATCH_H_ 1
|
||||
|
||||
# include <stddef.h>
|
||||
|
||||
# include "verify.h"
|
||||
|
||||
# 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);
|
||||
|
||||
# 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, reports a explanation on the
|
||||
failure, and exits 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);
|
||||
|
||||
# define ARGMATCH_TO_ARGUMENT(Value, Arglist, Vallist) \
|
||||
argmatch_to_argument (Value, Arglist, \
|
||||
(char const *) (Vallist), sizeof *(Vallist))
|
||||
|
||||
#endif /* ARGMATCH_H_ */
|
||||
@@ -0,0 +1,85 @@
|
||||
/* Define an at-style functions like fstatat, unlinkat, fchownat, etc.
|
||||
Copyright (C) 2006 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/>. */
|
||||
|
||||
/* written by Jim Meyering */
|
||||
|
||||
#define CALL_FUNC(F) \
|
||||
(AT_FUNC_USE_F1_COND \
|
||||
? AT_FUNC_F1 (F AT_FUNC_POST_FILE_ARGS) \
|
||||
: AT_FUNC_F2 (F AT_FUNC_POST_FILE_ARGS))
|
||||
|
||||
/* Call AT_FUNC_F1 or AT_FUNC_F2 (testing AT_FUNC_USE_F1_COND to
|
||||
determine which) to operate on FILE, which is in the directory
|
||||
open on descriptor FD. 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. */
|
||||
int
|
||||
AT_FUNC_NAME (int fd, char const *file AT_FUNC_POST_FILE_PARAM_DECLS)
|
||||
{
|
||||
struct saved_cwd saved_cwd;
|
||||
int saved_errno;
|
||||
int err;
|
||||
|
||||
if (fd == AT_FDCWD || IS_ABSOLUTE_FILE_NAME (file))
|
||||
return CALL_FUNC (file);
|
||||
|
||||
{
|
||||
char buf[OPENAT_BUFFER_SIZE];
|
||||
char *proc_file = openat_proc_name (buf, fd, file);
|
||||
if (proc_file)
|
||||
{
|
||||
int proc_result = CALL_FUNC (proc_file);
|
||||
int proc_errno = errno;
|
||||
if (proc_file != 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 (0 <= 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 (fchdir (fd) != 0)
|
||||
{
|
||||
saved_errno = errno;
|
||||
free_cwd (&saved_cwd);
|
||||
errno = saved_errno;
|
||||
return -1;
|
||||
}
|
||||
|
||||
err = CALL_FUNC (file);
|
||||
saved_errno = (err < 0 ? errno : 0);
|
||||
|
||||
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
|
||||
@@ -0,0 +1,128 @@
|
||||
/* basename.c -- return the last element in a file name
|
||||
|
||||
Copyright (C) 1990, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006 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/>. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "dirname.h"
|
||||
|
||||
#include <string.h>
|
||||
#include "xalloc.h"
|
||||
#include "xstrndup.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;
|
||||
}
|
||||
|
||||
|
||||
/* In general, we can't use the builtin `basename' function if available,
|
||||
since it has different meanings in different environments.
|
||||
In some environments the builtin `basename' modifies its argument.
|
||||
|
||||
Return the last file name component of NAME, allocated with
|
||||
xmalloc. On systems with drive letters, a leading "./"
|
||||
distinguishes relative names that would otherwise look like a drive
|
||||
letter. Unlike POSIX basename(), NAME cannot be NULL,
|
||||
base_name("") returns "", and the first trailing slash is not
|
||||
stripped.
|
||||
|
||||
If lstat (NAME) would succeed, then { chdir (dir_name (NAME));
|
||||
lstat (base_name (NAME)); } will access the same file. Likewise,
|
||||
if the sequence { chdir (dir_name (NAME));
|
||||
rename (base_name (NAME), "foo"); } succeeds, you have renamed NAME
|
||||
to "foo" in the same directory NAME was in. */
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/* Binary mode I/O.
|
||||
Copyright (C) 2001, 2003, 2005 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/>. */
|
||||
|
||||
#ifndef _BINARY_H
|
||||
#define _BINARY_H
|
||||
|
||||
/* For systems that distinguish between text and binary I/O.
|
||||
O_BINARY is usually declared in <fcntl.h>. */
|
||||
#include <fcntl.h>
|
||||
|
||||
/* The MSVC7 <stdio.h> doesn't like to be included after '#define fileno ...',
|
||||
so we include it here first. */
|
||||
#include <stdio.h>
|
||||
|
||||
#if !defined O_BINARY && defined _O_BINARY
|
||||
/* For MSC-compatible compilers. */
|
||||
# define O_BINARY _O_BINARY
|
||||
# define O_TEXT _O_TEXT
|
||||
#endif
|
||||
#ifdef __BEOS__
|
||||
/* BeOS 5 has O_BINARY and O_TEXT, but they have no effect. */
|
||||
# undef O_BINARY
|
||||
# undef O_TEXT
|
||||
#endif
|
||||
#if O_BINARY
|
||||
# if !(defined __EMX__ || defined __DJGPP__ || defined __CYGWIN__)
|
||||
# define setmode _setmode
|
||||
# undef fileno
|
||||
# define fileno _fileno
|
||||
# endif
|
||||
# if defined __DJGPP__ || defined __CYGWIN__
|
||||
# include <io.h> /* declares setmode() */
|
||||
# endif
|
||||
# ifdef __DJGPP__
|
||||
# include <unistd.h> /* declares isatty() */
|
||||
# /* Avoid putting stdin/stdout in binary mode if it is connected to the
|
||||
# console, because that would make it impossible for the user to
|
||||
# interrupt the program through Ctrl-C or Ctrl-Break. */
|
||||
# define SET_BINARY(fd) (!isatty (fd) ? (setmode (fd, O_BINARY), 0) : 0)
|
||||
# else
|
||||
# define SET_BINARY(fd) setmode (fd, O_BINARY)
|
||||
# endif
|
||||
#else
|
||||
/* On reasonable systems, binary I/O is the default. */
|
||||
# undef O_BINARY
|
||||
# define O_BINARY 0
|
||||
# define SET_BINARY(fd) /* nothing */
|
||||
#endif
|
||||
|
||||
#endif /* _BINARY_H */
|
||||
@@ -0,0 +1,362 @@
|
||||
/* Return the canonical absolute name of a given file.
|
||||
Copyright (C) 1996-2003, 2005-2007 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 <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
/* Avoid a clash of our rpl_realpath() function with the prototype in
|
||||
<stdlib.h> on Solaris 2.5.1. */
|
||||
#undef realpath
|
||||
|
||||
#if !HAVE_CANONICALIZE_FILE_NAME || defined _LIBC
|
||||
|
||||
#include <alloca.h>
|
||||
|
||||
/* Specification. */
|
||||
#include "canonicalize.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#if HAVE_UNISTD_H || defined _LIBC
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#if HAVE_SYS_PARAM_H || defined _LIBC
|
||||
# include <sys/param.h>
|
||||
#endif
|
||||
#ifndef MAXSYMLINKS
|
||||
# define MAXSYMLINKS 20
|
||||
#endif
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <errno.h>
|
||||
#ifndef _LIBC
|
||||
# define __set_errno(e) errno = (e)
|
||||
# ifndef ENAMETOOLONG
|
||||
# define ENAMETOOLONG EINVAL
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef _LIBC
|
||||
# include <shlib-compat.h>
|
||||
#else
|
||||
# define SHLIB_COMPAT(lib, introduced, obsoleted) 0
|
||||
# define versioned_symbol(lib, local, symbol, version)
|
||||
# define compat_symbol(lib, local, symbol, version)
|
||||
# define weak_alias(local, symbol)
|
||||
# define __canonicalize_file_name canonicalize_file_name
|
||||
# define __realpath rpl_realpath
|
||||
# include "pathmax.h"
|
||||
# include "malloca.h"
|
||||
# if HAVE_GETCWD
|
||||
# ifdef VMS
|
||||
/* We want the directory in Unix syntax, not in VMS syntax. */
|
||||
# define __getcwd(buf, max) getcwd (buf, max, 0)
|
||||
# else
|
||||
# define __getcwd getcwd
|
||||
# endif
|
||||
# else
|
||||
# define __getcwd(buf, max) getwd (buf)
|
||||
# endif
|
||||
# define __readlink readlink
|
||||
/* On systems without symbolic links, call stat() instead of lstat(). */
|
||||
# if !defined S_ISNLK && !HAVE_READLINK
|
||||
# define lstat stat
|
||||
# endif
|
||||
#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;
|
||||
#if HAVE_READLINK
|
||||
int num_links = 0;
|
||||
#endif
|
||||
|
||||
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 = 1024;
|
||||
#endif
|
||||
|
||||
if (resolved == NULL)
|
||||
{
|
||||
rpath = malloc (path_max);
|
||||
if (rpath == NULL)
|
||||
{
|
||||
/* It's easier to set errno to ENOMEM than to rely on the
|
||||
'malloc-posix' gnulib module. */
|
||||
errno = ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
rpath = resolved;
|
||||
rpath_limit = rpath + path_max;
|
||||
|
||||
if (name[0] != '/')
|
||||
{
|
||||
if (!__getcwd (rpath, path_max))
|
||||
{
|
||||
rpath[0] = '\0';
|
||||
goto error;
|
||||
}
|
||||
dest = strchr (rpath, '\0');
|
||||
}
|
||||
else
|
||||
{
|
||||
rpath[0] = '/';
|
||||
dest = rpath + 1;
|
||||
}
|
||||
|
||||
for (start = end = name; *start; start = end)
|
||||
{
|
||||
#ifdef _LIBC
|
||||
struct stat64 st;
|
||||
#else
|
||||
struct stat st;
|
||||
#endif
|
||||
|
||||
/* Skip sequence of multiple path-separators. */
|
||||
while (*start == '/')
|
||||
++start;
|
||||
|
||||
/* Find end of path component. */
|
||||
for (end = start; *end && *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 + 1)
|
||||
while ((--dest)[-1] != '/');
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t new_size;
|
||||
|
||||
if (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 + 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)
|
||||
{
|
||||
/* It's easier to set errno to ENOMEM than to rely on the
|
||||
'realloc-posix' gnulib module. */
|
||||
errno = ENOMEM;
|
||||
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';
|
||||
|
||||
#ifdef _LIBC
|
||||
if (__lxstat64 (_STAT_VER, rpath, &st) < 0)
|
||||
#else
|
||||
if (lstat (rpath, &st) < 0)
|
||||
#endif
|
||||
goto error;
|
||||
|
||||
#if HAVE_READLINK
|
||||
if (S_ISLNK (st.st_mode))
|
||||
{
|
||||
char *buf;
|
||||
size_t len;
|
||||
int n;
|
||||
|
||||
if (++num_links > MAXSYMLINKS)
|
||||
{
|
||||
__set_errno (ELOOP);
|
||||
goto error;
|
||||
}
|
||||
|
||||
buf = malloca (path_max);
|
||||
if (!buf)
|
||||
{
|
||||
errno = ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
|
||||
n = __readlink (rpath, buf, path_max);
|
||||
if (n < 0)
|
||||
{
|
||||
int saved_errno = errno;
|
||||
freea (buf);
|
||||
errno = saved_errno;
|
||||
goto error;
|
||||
}
|
||||
buf[n] = '\0';
|
||||
|
||||
if (!extra_buf)
|
||||
{
|
||||
extra_buf = malloca (path_max);
|
||||
if (!extra_buf)
|
||||
{
|
||||
freea (buf);
|
||||
errno = ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
len = strlen (end);
|
||||
if ((long int) (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 (buf[0] == '/')
|
||||
dest = rpath + 1; /* It's an absolute symlink */
|
||||
else
|
||||
/* Back up to previous component, ignore if at root already: */
|
||||
if (dest > rpath + 1)
|
||||
while ((--dest)[-1] != '/');
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if (dest > rpath + 1 && dest[-1] == '/')
|
||||
--dest;
|
||||
*dest = '\0';
|
||||
|
||||
if (extra_buf)
|
||||
freea (extra_buf);
|
||||
|
||||
return resolved ? memcpy (resolved, rpath, dest - rpath + 1) : rpath;
|
||||
|
||||
error:
|
||||
{
|
||||
int saved_errno = errno;
|
||||
if (extra_buf)
|
||||
freea (extra_buf);
|
||||
if (resolved)
|
||||
strcpy (resolved, rpath);
|
||||
else
|
||||
free (rpath);
|
||||
errno = saved_errno;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#ifdef _LIBC
|
||||
versioned_symbol (libc, __realpath, realpath, GLIBC_2_3);
|
||||
#endif
|
||||
|
||||
|
||||
#if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_3)
|
||||
char *
|
||||
__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
|
||||
@@ -0,0 +1,337 @@
|
||||
/* Return the canonical absolute name of a given file.
|
||||
Copyright (C) 1996-2007 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/>. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "canonicalize.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#if HAVE_SYS_PARAM_H
|
||||
# include <sys/param.h>
|
||||
#endif
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "file-set.h"
|
||||
#include "filenamecat.h"
|
||||
#include "hash-triple.h"
|
||||
#include "xalloc.h"
|
||||
#include "xgetcwd.h"
|
||||
|
||||
#ifndef ELOOP
|
||||
# define ELOOP 0
|
||||
#endif
|
||||
#ifndef __set_errno
|
||||
# define __set_errno(Val) errno = (Val)
|
||||
#endif
|
||||
|
||||
#include "pathmax.h"
|
||||
#include "areadlink.h"
|
||||
|
||||
#if !HAVE_CANONICALIZE_FILE_NAME
|
||||
/* Return the canonical absolute name of file NAME. A canonical name
|
||||
does not contain any `.', `..' components nor any repeated file name
|
||||
separators ('/') or symlinks. All components must exist.
|
||||
The result is malloc'd. */
|
||||
|
||||
char *
|
||||
canonicalize_file_name (const char *name)
|
||||
{
|
||||
# if HAVE_RESOLVEPATH
|
||||
|
||||
char *resolved, *extra_buf = NULL;
|
||||
size_t resolved_size;
|
||||
ssize_t resolved_len;
|
||||
|
||||
if (name == NULL)
|
||||
{
|
||||
__set_errno (EINVAL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (name[0] == '\0')
|
||||
{
|
||||
__set_errno (ENOENT);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* All known hosts with resolvepath (e.g. Solaris 7) don't turn
|
||||
relative names into absolute ones, so prepend the working
|
||||
directory if the file name is not absolute. */
|
||||
if (name[0] != '/')
|
||||
{
|
||||
char *wd;
|
||||
|
||||
if (!(wd = xgetcwd ()))
|
||||
return NULL;
|
||||
|
||||
extra_buf = file_name_concat (wd, name, NULL);
|
||||
name = extra_buf;
|
||||
free (wd);
|
||||
}
|
||||
|
||||
resolved_size = strlen (name);
|
||||
while (1)
|
||||
{
|
||||
resolved_size = 2 * resolved_size + 1;
|
||||
resolved = xmalloc (resolved_size);
|
||||
resolved_len = resolvepath (name, resolved, resolved_size);
|
||||
if (resolved_len < 0)
|
||||
{
|
||||
free (resolved);
|
||||
free (extra_buf);
|
||||
return NULL;
|
||||
}
|
||||
if (resolved_len < resolved_size)
|
||||
break;
|
||||
free (resolved);
|
||||
}
|
||||
|
||||
free (extra_buf);
|
||||
|
||||
/* NUL-terminate the resulting name. */
|
||||
resolved[resolved_len] = '\0';
|
||||
|
||||
return resolved;
|
||||
|
||||
# else
|
||||
|
||||
return canonicalize_filename_mode (name, CAN_EXISTING);
|
||||
|
||||
# endif /* !HAVE_RESOLVEPATH */
|
||||
}
|
||||
#endif /* !HAVE_CANONICALIZE_FILE_NAME */
|
||||
|
||||
/* Return true if we've already seen the triple, <FILENAME, dev, ino>.
|
||||
If *HT is not initialized, initialize it. */
|
||||
static bool
|
||||
seen_triple (Hash_table **ht, char const *filename, struct stat const *st)
|
||||
{
|
||||
if (*ht == NULL)
|
||||
{
|
||||
size_t initial_capacity = 7;
|
||||
*ht = hash_initialize (initial_capacity,
|
||||
NULL,
|
||||
triple_hash,
|
||||
triple_compare_ino_str,
|
||||
triple_free);
|
||||
if (*ht == NULL)
|
||||
xalloc_die ();
|
||||
}
|
||||
|
||||
if (seen_file (*ht, filename, st))
|
||||
return true;
|
||||
|
||||
record_file (*ht, filename, st);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Return the canonical absolute name of file NAME. A canonical name
|
||||
does not contain any `.', `..' components nor any repeated file name
|
||||
separators ('/') or symlinks. Whether components must exist
|
||||
or not depends on canonicalize mode. The result is malloc'd. */
|
||||
|
||||
char *
|
||||
canonicalize_filename_mode (const char *name, canonicalize_mode_t can_mode)
|
||||
{
|
||||
char *rname, *dest, *extra_buf = NULL;
|
||||
char const *start;
|
||||
char const *end;
|
||||
char const *rname_limit;
|
||||
size_t extra_len = 0;
|
||||
Hash_table *ht = NULL;
|
||||
|
||||
if (name == NULL)
|
||||
{
|
||||
__set_errno (EINVAL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (name[0] == '\0')
|
||||
{
|
||||
__set_errno (ENOENT);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (name[0] != '/')
|
||||
{
|
||||
rname = xgetcwd ();
|
||||
if (!rname)
|
||||
return NULL;
|
||||
dest = strchr (rname, '\0');
|
||||
if (dest - rname < PATH_MAX)
|
||||
{
|
||||
char *p = xrealloc (rname, PATH_MAX);
|
||||
dest = p + (dest - rname);
|
||||
rname = p;
|
||||
rname_limit = rname + PATH_MAX;
|
||||
}
|
||||
else
|
||||
{
|
||||
rname_limit = dest;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rname = xmalloc (PATH_MAX);
|
||||
rname_limit = rname + PATH_MAX;
|
||||
rname[0] = '/';
|
||||
dest = rname + 1;
|
||||
}
|
||||
|
||||
for (start = end = name; *start; start = end)
|
||||
{
|
||||
/* Skip sequence of multiple file name separators. */
|
||||
while (*start == '/')
|
||||
++start;
|
||||
|
||||
/* Find end of component. */
|
||||
for (end = start; *end && *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 > rname + 1)
|
||||
while ((--dest)[-1] != '/');
|
||||
}
|
||||
else
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
if (dest[-1] != '/')
|
||||
*dest++ = '/';
|
||||
|
||||
if (dest + (end - start) >= rname_limit)
|
||||
{
|
||||
ptrdiff_t dest_offset = dest - rname;
|
||||
size_t new_size = rname_limit - rname;
|
||||
|
||||
if (end - start + 1 > PATH_MAX)
|
||||
new_size += end - start + 1;
|
||||
else
|
||||
new_size += PATH_MAX;
|
||||
rname = xrealloc (rname, new_size);
|
||||
rname_limit = rname + new_size;
|
||||
|
||||
dest = rname + dest_offset;
|
||||
}
|
||||
|
||||
dest = memcpy (dest, start, end - start);
|
||||
dest += end - start;
|
||||
*dest = '\0';
|
||||
|
||||
if (lstat (rname, &st) != 0)
|
||||
{
|
||||
if (can_mode == CAN_EXISTING)
|
||||
goto error;
|
||||
if (can_mode == CAN_ALL_BUT_LAST && *end)
|
||||
goto error;
|
||||
st.st_mode = 0;
|
||||
}
|
||||
|
||||
if (S_ISLNK (st.st_mode))
|
||||
{
|
||||
char *buf;
|
||||
size_t n, len;
|
||||
|
||||
/* Detect loops. We cannot use the cycle-check module here,
|
||||
since it's actually possible to encounter the same symlink
|
||||
more than once in a given traversal. However, encountering
|
||||
the same symlink,NAME pair twice does indicate a loop. */
|
||||
if (seen_triple (&ht, name, &st))
|
||||
{
|
||||
__set_errno (ELOOP);
|
||||
if (can_mode == CAN_MISSING)
|
||||
continue;
|
||||
else
|
||||
goto error;
|
||||
}
|
||||
|
||||
buf = areadlink_with_size (rname, st.st_size);
|
||||
if (!buf)
|
||||
{
|
||||
if (can_mode == CAN_MISSING && errno != ENOMEM)
|
||||
continue;
|
||||
else
|
||||
goto error;
|
||||
}
|
||||
|
||||
n = strlen (buf);
|
||||
len = strlen (end);
|
||||
|
||||
if (!extra_len)
|
||||
{
|
||||
extra_len =
|
||||
((n + len + 1) > PATH_MAX) ? (n + len + 1) : PATH_MAX;
|
||||
extra_buf = xmalloc (extra_len);
|
||||
}
|
||||
else if ((n + len + 1) > extra_len)
|
||||
{
|
||||
extra_len = n + len + 1;
|
||||
extra_buf = xrealloc (extra_buf, extra_len);
|
||||
}
|
||||
|
||||
/* 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 (buf[0] == '/')
|
||||
dest = rname + 1; /* It's an absolute symlink */
|
||||
else
|
||||
/* Back up to previous component, ignore if at root already: */
|
||||
if (dest > rname + 1)
|
||||
while ((--dest)[-1] != '/');
|
||||
|
||||
free (buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!S_ISDIR (st.st_mode) && *end && (can_mode != CAN_MISSING))
|
||||
{
|
||||
errno = ENOTDIR;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (dest > rname + 1 && dest[-1] == '/')
|
||||
--dest;
|
||||
*dest = '\0';
|
||||
|
||||
free (extra_buf);
|
||||
if (ht)
|
||||
hash_free (ht);
|
||||
return rname;
|
||||
|
||||
error:
|
||||
free (extra_buf);
|
||||
free (rname);
|
||||
if (ht)
|
||||
hash_free (ht);
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/* Return the canonical absolute name of a given file.
|
||||
Copyright (C) 1996-2007 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/>. */
|
||||
|
||||
#ifndef CANONICALIZE_H_
|
||||
# define CANONICALIZE_H_
|
||||
|
||||
# if GNULIB_CANONICALIZE
|
||||
enum canonicalize_mode_t
|
||||
{
|
||||
/* All components must exist. */
|
||||
CAN_EXISTING = 0,
|
||||
|
||||
/* All components excluding last one must exist. */
|
||||
CAN_ALL_BUT_LAST = 1,
|
||||
|
||||
/* No requirements on components existence. */
|
||||
CAN_MISSING = 2
|
||||
};
|
||||
typedef enum canonicalize_mode_t canonicalize_mode_t;
|
||||
|
||||
/* Return a malloc'd string containing the canonical absolute name of
|
||||
the named file. This acts like canonicalize_file_name, except that
|
||||
whether components must exist depends on the canonicalize_mode_t
|
||||
argument. */
|
||||
char *canonicalize_filename_mode (const char *, canonicalize_mode_t);
|
||||
# endif
|
||||
|
||||
# if HAVE_DECL_CANONICALIZE_FILE_NAME
|
||||
# include <stdlib.h>
|
||||
# else
|
||||
/* Return a malloc'd string containing the canonical absolute name of
|
||||
the named file. If any file name component does not exist or is a
|
||||
symlink to a nonexistent file, return NULL. A canonical name does
|
||||
not contain any `.', `..' components nor any repeated file name
|
||||
separators ('/') or symlinks. */
|
||||
char *canonicalize_file_name (const char *);
|
||||
# endif
|
||||
|
||||
#endif /* !CANONICALIZE_H_ */
|
||||
@@ -0,0 +1,264 @@
|
||||
/* provide a chdir function that tries not to fail due to ENAMETOOLONG
|
||||
Copyright (C) 2004, 2005, 2006, 2007 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/>. */
|
||||
|
||||
/* written by Jim Meyering */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "chdir-long.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "openat.h"
|
||||
|
||||
#ifndef PATH_MAX
|
||||
# error "compile this file only if your system defines PATH_MAX"
|
||||
#endif
|
||||
|
||||
struct cd_buf
|
||||
{
|
||||
int fd;
|
||||
};
|
||||
|
||||
static inline void
|
||||
cdb_init (struct cd_buf *cdb)
|
||||
{
|
||||
cdb->fd = AT_FDCWD;
|
||||
}
|
||||
|
||||
static inline int
|
||||
cdb_fchdir (struct cd_buf const *cdb)
|
||||
{
|
||||
return fchdir (cdb->fd);
|
||||
}
|
||||
|
||||
static inline void
|
||||
cdb_free (struct cd_buf const *cdb)
|
||||
{
|
||||
if (0 <= cdb->fd)
|
||||
{
|
||||
bool close_fail = close (cdb->fd);
|
||||
assert (! 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_RDONLY | 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 inline char *
|
||||
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. */
|
||||
assert (0 < len);
|
||||
assert (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;
|
||||
}
|
||||
|
||||
assert (*dir != '/');
|
||||
assert (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';
|
||||
assert (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 <stdio.h>
|
||||
# include "closeout.h"
|
||||
# include "error.h"
|
||||
|
||||
char *program_name;
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
char *line = NULL;
|
||||
size_t n = 0;
|
||||
int len;
|
||||
|
||||
program_name = argv[0];
|
||||
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:
|
||||
*/
|
||||
@@ -0,0 +1,34 @@
|
||||
/* provide a chdir function that tries not to fail due to ENAMETOOLONG
|
||||
Copyright (C) 2004, 2005 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/>. */
|
||||
|
||||
/* Written by Jim Meyering. */
|
||||
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
|
||||
#ifndef PATH_MAX
|
||||
# ifdef MAXPATHLEN
|
||||
# define PATH_MAX MAXPATHLEN
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* 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
|
||||
@@ -0,0 +1,103 @@
|
||||
/* 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, 2005, 2006, 2007 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/>. */
|
||||
|
||||
/* written by Jim Meyering */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
/* Specification. */
|
||||
#include <unistd.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
/* Below we refer to the system's chown(). */
|
||||
#undef chown
|
||||
|
||||
/* The results of open() in this file are not used with fchdir,
|
||||
therefore save some unnecessary work in fchdir.c. */
|
||||
#undef open
|
||||
#undef close
|
||||
|
||||
/* 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)
|
||||
{
|
||||
#if CHOWN_FAILS_TO_HONOR_ID_OF_NEGATIVE_ONE
|
||||
if (gid == (gid_t) -1 || uid == (uid_t) -1)
|
||||
{
|
||||
struct stat file_stats;
|
||||
|
||||
/* Stat file to get id(s) that should remain unchanged. */
|
||||
if (stat (file, &file_stats))
|
||||
return -1;
|
||||
|
||||
if (gid == (gid_t) -1)
|
||||
gid = file_stats.st_gid;
|
||||
|
||||
if (uid == (uid_t) -1)
|
||||
uid = file_stats.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 result = fchown (fd, uid, gid);
|
||||
int saved_errno = errno;
|
||||
|
||||
/* POSIX says fchown can fail with errno == EINVAL on sockets,
|
||||
so fall back on chown in that case. */
|
||||
struct stat sb;
|
||||
bool fchown_socket_failure =
|
||||
(result != 0 && saved_errno == EINVAL
|
||||
&& fstat (fd, &sb) == 0 && S_ISFIFO (sb.st_mode));
|
||||
|
||||
close (fd);
|
||||
|
||||
if (! fchown_socket_failure)
|
||||
{
|
||||
errno = saved_errno;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
else if (errno != EACCES)
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
return chown (file, uid, gid);
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/* Close a stream, with nicer error checking than fclose's.
|
||||
|
||||
Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2006, 2007 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/>. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "close-stream.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "fpending.h"
|
||||
|
||||
#if USE_UNLOCKED_IO
|
||||
# include "unlocked-io.h"
|
||||
#endif
|
||||
|
||||
/* Close STREAM. Return 0 if successful, EOF (setting errno)
|
||||
otherwise. A failure might set errno to 0 if the error number
|
||||
cannot be determined.
|
||||
|
||||
If a program writes *anything* to STREAM, that program should close
|
||||
STREAM and make sure that it succeeds before exiting. Otherwise,
|
||||
suppose that you go to the extreme of checking the return status
|
||||
of every function that does an explicit write to STREAM. The last
|
||||
printf can succeed in writing to the internal stream buffer, and yet
|
||||
the fclose(STREAM) could still fail (due e.g., to a disk full error)
|
||||
when it tries to write out that buffered data. Thus, you would be
|
||||
left with an incomplete output file and the offending program would
|
||||
exit successfully. Even calling fflush is not always sufficient,
|
||||
since some file systems (NFS and CODA) buffer written/flushed data
|
||||
until an actual close call.
|
||||
|
||||
Besides, it's wasteful to check the return value from every call
|
||||
that writes to STREAM -- just let the internal stream state record
|
||||
the failure. That's what the ferror test is checking below. */
|
||||
|
||||
int
|
||||
close_stream (FILE *stream)
|
||||
{
|
||||
bool some_pending = (__fpending (stream) != 0);
|
||||
bool prev_fail = (ferror (stream) != 0);
|
||||
bool fclose_fail = (fclose (stream) != 0);
|
||||
|
||||
/* Return an error indication if there was a previous failure or if
|
||||
fclose failed, with one exception: ignore an fclose failure if
|
||||
there was no previous error, no data remains to be flushed, and
|
||||
fclose failed with EBADF. That can happen when a program like cp
|
||||
is invoked like this `cp a b >&-' (i.e., with standard output
|
||||
closed) and doesn't generate any output (hence no previous error
|
||||
and nothing to be flushed). */
|
||||
|
||||
if (prev_fail || (fclose_fail && (some_pending || errno != EBADF)))
|
||||
{
|
||||
if (! fclose_fail)
|
||||
errno = 0;
|
||||
return EOF;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
#include <stdio.h>
|
||||
int close_stream (FILE *stream);
|
||||
@@ -0,0 +1,111 @@
|
||||
/* Close standard input, rewinding seekable stdin if necessary.
|
||||
|
||||
Copyright (C) 2007 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/>. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "closein.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "gettext.h"
|
||||
#define _(msgid) gettext (msgid)
|
||||
|
||||
#include "close-stream.h"
|
||||
#include "closeout.h"
|
||||
#include "error.h"
|
||||
#include "exitfail.h"
|
||||
#include "freadahead.h"
|
||||
#include "quotearg.h"
|
||||
|
||||
static const char *file_name;
|
||||
|
||||
/* Set the file name to be reported in the event an error is detected
|
||||
on stdin by close_stdin. See also close_stdout_set_file_name, if
|
||||
an error is detected when closing stdout. */
|
||||
void
|
||||
close_stdin_set_file_name (const char *file)
|
||||
{
|
||||
file_name = file;
|
||||
}
|
||||
|
||||
/* Close standard input, rewinding any unused input if stdin is
|
||||
seekable. On error, issue a diagnostic and _exit with status
|
||||
'exit_failure'. Then call close_stdout.
|
||||
|
||||
Most programs can get by with close_stdout. close_stdin is only
|
||||
needed when a program wants to guarantee that partially read input
|
||||
from seekable stdin is not consumed, for any subsequent clients.
|
||||
For example, POSIX requires that these two commands behave alike:
|
||||
|
||||
(sed -ne 1q; cat) < file
|
||||
tail -n 1 file
|
||||
|
||||
Since close_stdin is commonly registered via 'atexit', POSIX
|
||||
and the C standard both say that it should not call 'exit',
|
||||
because the behavior is undefined if 'exit' is called more than
|
||||
once. So it calls '_exit' instead of 'exit'. If close_stdin
|
||||
is registered via atexit before other functions are registered,
|
||||
the other functions can act before this _exit is invoked.
|
||||
|
||||
Applications that use close_stdout should flush any streams other
|
||||
than stdin, stdout, and stderr before exiting, since the call to
|
||||
_exit will bypass other buffer flushing. Applications should be
|
||||
flushing and closing other streams anyway, to check for I/O errors.
|
||||
Also, applications should not use tmpfile, since _exit can bypass
|
||||
the removal of these files.
|
||||
|
||||
It's important to detect such failures and exit nonzero because many
|
||||
tools (most notably `make' and other build-management systems) depend
|
||||
on being able to detect failure in other tools via their exit status. */
|
||||
|
||||
void
|
||||
close_stdin (void)
|
||||
{
|
||||
bool fail = false;
|
||||
|
||||
/* There is no need to flush stdin if we can determine quickly that stdin's
|
||||
input buffer is empty; in this case we know that if stdin is seekable,
|
||||
fseeko (stdin, 0, SEEK_CUR) == lseek (0, 0, SEEK_CUR). */
|
||||
if (freadahead (stdin) > 0)
|
||||
{
|
||||
/* Only attempt flush if stdin is seekable, as fflush is entitled to
|
||||
fail on non-seekable streams. */
|
||||
if (fseeko (stdin, 0, SEEK_CUR) == 0 && fflush (stdin) != 0)
|
||||
fail = true;
|
||||
}
|
||||
if (close_stream (stdin) != 0)
|
||||
fail = true;
|
||||
if (fail)
|
||||
{
|
||||
/* Report failure, but defer exit until after closing stdout,
|
||||
since the failure report should still be flushed. */
|
||||
char const *close_error = _("error closing file");
|
||||
if (file_name)
|
||||
error (0, errno, "%s: %s", quotearg_colon (file_name),
|
||||
close_error);
|
||||
else
|
||||
error (0, errno, "%s", close_error);
|
||||
}
|
||||
|
||||
close_stdout ();
|
||||
|
||||
if (fail)
|
||||
_exit (exit_failure);
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/* Close standard input, rewinding seekable stdin if necessary.
|
||||
|
||||
Copyright (C) 2007 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/>. */
|
||||
|
||||
#ifndef _GL_CLOSEIN_H
|
||||
# define _GL_CLOSEIN_H 1
|
||||
|
||||
# ifdef __cplusplus
|
||||
extern "C" {
|
||||
# endif
|
||||
|
||||
void close_stdin_set_file_name (const char *file);
|
||||
void close_stdin (void);
|
||||
|
||||
# ifdef __cplusplus
|
||||
}
|
||||
# endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,85 @@
|
||||
/* Close standard output and standard error, exiting with a diagnostic on error.
|
||||
|
||||
Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2006 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/>. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "closeout.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "gettext.h"
|
||||
#define _(msgid) gettext (msgid)
|
||||
|
||||
#include "close-stream.h"
|
||||
#include "error.h"
|
||||
#include "exitfail.h"
|
||||
#include "quotearg.h"
|
||||
|
||||
static const char *file_name;
|
||||
|
||||
/* Set the file name to be reported in the event an error is detected
|
||||
by close_stdout. */
|
||||
void
|
||||
close_stdout_set_file_name (const char *file)
|
||||
{
|
||||
file_name = file;
|
||||
}
|
||||
|
||||
/* Close standard output. On error, issue a diagnostic and _exit
|
||||
with status 'exit_failure'.
|
||||
|
||||
Also close standard error. On error, _exit with status 'exit_failure'.
|
||||
|
||||
Since close_stdout is commonly registered via 'atexit', POSIX
|
||||
and the C standard both say that it should not call 'exit',
|
||||
because the behavior is undefined if 'exit' is called more than
|
||||
once. So it calls '_exit' instead of 'exit'. If close_stdout
|
||||
is registered via atexit before other functions are registered,
|
||||
the other functions can act before this _exit is invoked.
|
||||
|
||||
Applications that use close_stdout should flush any streams
|
||||
other than stdout and stderr before exiting, since the call to
|
||||
_exit will bypass other buffer flushing. Applications should
|
||||
be flushing and closing other streams anyway, to check for I/O
|
||||
errors. Also, applications should not use tmpfile, since _exit
|
||||
can bypass the removal of these files.
|
||||
|
||||
It's important to detect such failures and exit nonzero because many
|
||||
tools (most notably `make' and other build-management systems) depend
|
||||
on being able to detect failure in other tools via their exit status. */
|
||||
|
||||
void
|
||||
close_stdout (void)
|
||||
{
|
||||
if (close_stream (stdout) != 0)
|
||||
{
|
||||
char const *write_error = _("write error");
|
||||
if (file_name)
|
||||
error (0, errno, "%s: %s", quotearg_colon (file_name),
|
||||
write_error);
|
||||
else
|
||||
error (0, errno, "%s", write_error);
|
||||
|
||||
_exit (exit_failure);
|
||||
}
|
||||
|
||||
if (close_stream (stderr) != 0)
|
||||
_exit (exit_failure);
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/* Close standard output and standard error.
|
||||
|
||||
Copyright (C) 1998, 2000, 2003, 2004, 2006 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/>. */
|
||||
|
||||
#ifndef CLOSEOUT_H
|
||||
# define CLOSEOUT_H 1
|
||||
|
||||
# ifdef __cplusplus
|
||||
extern "C" {
|
||||
# endif
|
||||
|
||||
void close_stdout_set_file_name (const char *file);
|
||||
void close_stdout (void);
|
||||
|
||||
# ifdef __cplusplus
|
||||
}
|
||||
# endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,25 @@
|
||||
/* DO NOT EDIT! GENERATED AUTOMATICALLY! */
|
||||
#define PREFIX "/usr/local"
|
||||
#define EXEC_PREFIX "/usr/local"
|
||||
#define BINDIR "/usr/local/bin"
|
||||
#define SBINDIR "/usr/local/sbin"
|
||||
#define LIBEXECDIR "/usr/local/libexec"
|
||||
#define DATAROOTDIR "/usr/local/share"
|
||||
#define DATADIR "/usr/local/share"
|
||||
#define SYSCONFDIR "/usr/local/etc"
|
||||
#define SHAREDSTATEDIR "/usr/local/com"
|
||||
#define LOCALSTATEDIR "/usr/local/var"
|
||||
#define INCLUDEDIR "/usr/local/include"
|
||||
#define OLDINCLUDEDIR "/usr/include"
|
||||
#define DOCDIR "/usr/local/share/doc/findutils"
|
||||
#define INFODIR "/usr/local/share/info"
|
||||
#define HTMLDIR "/usr/local/share/doc/findutils"
|
||||
#define DVIDIR "/usr/local/share/doc/findutils"
|
||||
#define PDFDIR "/usr/local/share/doc/findutils"
|
||||
#define PSDIR "/usr/local/share/doc/findutils"
|
||||
#define LIBDIR "/usr/local/lib"
|
||||
#define LOCALEDIR "/usr/local/share/locale"
|
||||
#define MANDIR "/usr/local/share/man"
|
||||
#define PKGDATADIR "/usr/local/share/findutils"
|
||||
#define PKGINCLUDEDIR "/usr/local/include/findutils"
|
||||
#define PKGLIBDIR "/usr/local/lib/findutils"
|
||||
@@ -0,0 +1,31 @@
|
||||
/* Invoke creat, but avoid some glitches.
|
||||
|
||||
Copyright (C) 2005, 2006 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/>. */
|
||||
|
||||
/* Written by Jim Meyering. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "fcntl-safer.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include "unistd-safer.h"
|
||||
|
||||
int
|
||||
creat_safer (char const *file, mode_t mode)
|
||||
{
|
||||
return fd_safer (creat (file, mode));
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/* Wrapper around <dirent.h>.
|
||||
Copyright (C) 2006-2007 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/>. */
|
||||
|
||||
#ifndef _GL_DIRENT_H
|
||||
|
||||
/* The include_next requires a split double-inclusion guard. */
|
||||
#@INCLUDE_NEXT@ @NEXT_DIRENT_H@
|
||||
|
||||
#ifndef _GL_DIRENT_H
|
||||
#define _GL_DIRENT_H
|
||||
|
||||
|
||||
/* Declare overridden functions. */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if @REPLACE_FCHDIR@
|
||||
# define opendir rpl_opendir
|
||||
extern DIR * opendir (const char *);
|
||||
# define closedir rpl_closedir
|
||||
extern int closedir (DIR *);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* _GL_DIRENT_H */
|
||||
#endif /* _GL_DIRENT_H */
|
||||
@@ -0,0 +1,28 @@
|
||||
/* dirfd.c -- return the file descriptor associated with an open DIR*
|
||||
|
||||
Copyright (C) 2001, 2006 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/>. */
|
||||
|
||||
/* Written by Jim Meyering. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "dirfd.h"
|
||||
|
||||
int
|
||||
dirfd (DIR const *dir_p)
|
||||
{
|
||||
return DIR_TO_FD (dir_p);
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/* Declare dirfd, if necessary.
|
||||
Copyright (C) 2001, 2002, 2006 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/>.
|
||||
|
||||
Written by Jim Meyering. */
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <dirent.h>
|
||||
|
||||
#ifndef HAVE_DECL_DIRFD
|
||||
"this configure-time declaration test was not run"
|
||||
#endif
|
||||
#if !HAVE_DECL_DIRFD && !defined dirfd
|
||||
int dirfd (DIR const *);
|
||||
#endif
|
||||
@@ -0,0 +1,84 @@
|
||||
/* dirname.c -- return all but the last element in a file name
|
||||
|
||||
Copyright (C) 1990, 1998, 2000, 2001, 2003, 2004, 2005, 2006 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/>. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "dirname.h"
|
||||
|
||||
#include <string.h>
|
||||
#include "xalloc.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 xmalloc.
|
||||
Works properly even if there are trailing slashes (by effectively
|
||||
ignoring them). Unlike POSIX dirname(), FILE cannot be NULL.
|
||||
|
||||
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 *
|
||||
dir_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 = xmalloc (length + append_dot + 1);
|
||||
memcpy (dir, file, length);
|
||||
if (append_dot)
|
||||
dir[length++] = '.';
|
||||
dir[length] = '\0';
|
||||
return dir;
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/* Take file names apart into directory and base names.
|
||||
|
||||
Copyright (C) 1998, 2001, 2003-2006 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/>. */
|
||||
|
||||
#ifndef DIRNAME_H_
|
||||
# define DIRNAME_H_ 1
|
||||
|
||||
# include <stdbool.h>
|
||||
# include <stddef.h>
|
||||
|
||||
# ifndef DIRECTORY_SEPARATOR
|
||||
# define DIRECTORY_SEPARATOR '/'
|
||||
# endif
|
||||
|
||||
# ifndef ISSLASH
|
||||
# define ISSLASH(C) ((C) == DIRECTORY_SEPARATOR)
|
||||
# endif
|
||||
|
||||
# ifndef FILE_SYSTEM_PREFIX_LEN
|
||||
# if FILE_SYSTEM_ACCEPTS_DRIVE_LETTER_PREFIX
|
||||
/* 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)
|
||||
# else
|
||||
# define FILE_SYSTEM_PREFIX_LEN(Filename) 0
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# ifndef FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
|
||||
# define FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE 0
|
||||
# endif
|
||||
|
||||
# ifndef DOUBLE_SLASH_IS_DISTINCT_ROOT
|
||||
# define DOUBLE_SLASH_IS_DISTINCT_ROOT 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]) || 0 < FILE_SYSTEM_PREFIX_LEN (F))
|
||||
# endif
|
||||
# define IS_RELATIVE_FILE_NAME(F) (! IS_ABSOLUTE_FILE_NAME (F))
|
||||
|
||||
char *base_name (char const *file);
|
||||
char *dir_name (char const *file);
|
||||
size_t base_len (char const *file);
|
||||
size_t dir_len (char const *file);
|
||||
char *last_component (char const *file);
|
||||
|
||||
bool strip_trailing_slashes (char *file);
|
||||
|
||||
#endif /* not DIRNAME_H_ */
|
||||
@@ -0,0 +1,44 @@
|
||||
/* Invoke dup, but avoid some glitches.
|
||||
|
||||
Copyright (C) 2001, 2004, 2005, 2006 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/>. */
|
||||
|
||||
/* Written by Paul Eggert. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "unistd-safer.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <unistd.h>
|
||||
#ifndef STDERR_FILENO
|
||||
# define STDERR_FILENO 2
|
||||
#endif
|
||||
|
||||
/* Like dup, but do not return STDIN_FILENO, STDOUT_FILENO, or
|
||||
STDERR_FILENO. */
|
||||
|
||||
int
|
||||
dup_safer (int fd)
|
||||
{
|
||||
#if defined F_DUPFD && !defined FCHDIR_REPLACEMENT
|
||||
return fcntl (fd, F_DUPFD, STDERR_FILENO + 1);
|
||||
#else
|
||||
/* fd_safer calls us back, but eventually the recursion unwinds and
|
||||
does the right thing. */
|
||||
return fd_safer (dup (fd));
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/* Duplicate an open file descriptor to a specified file descriptor.
|
||||
|
||||
Copyright (C) 1999, 2004, 2005, 2006, 2007 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/>. */
|
||||
|
||||
/* written by Paul Eggert */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
/* Specification. */
|
||||
#include <unistd.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#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)
|
||||
{
|
||||
if (fd == desired_fd)
|
||||
return fd;
|
||||
close (desired_fd);
|
||||
#ifdef F_DUPFD
|
||||
return fcntl (fd, F_DUPFD, desired_fd);
|
||||
#else
|
||||
return dupfd (fd, desired_fd);
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,338 @@
|
||||
/* Error handler for noninteractive utilities
|
||||
Copyright (C) 1990-1998, 2000-2007 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 <http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* Written by David MacKenzie <[email protected]>. */
|
||||
|
||||
#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
|
||||
#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) INTUSE(_IO_fflush) (s)
|
||||
# undef putc
|
||||
# define putc(c, fp) INTUSE(_IO_putc) (c, fp)
|
||||
|
||||
# include <bits/libc-lock.h>
|
||||
|
||||
#else /* not _LIBC */
|
||||
|
||||
# if !HAVE_DECL_STRERROR_R && STRERROR_R_CHAR_P
|
||||
# ifndef HAVE_DECL_STRERROR_R
|
||||
"this configure-time declaration test was not run"
|
||||
# endif
|
||||
char *strerror_r ();
|
||||
# endif
|
||||
|
||||
/* The calling program should define program_name and set it to the
|
||||
name of the executing program. */
|
||||
extern char *program_name;
|
||||
|
||||
# if HAVE_STRERROR_R || defined strerror_r
|
||||
# define __strerror_r strerror_r
|
||||
# endif /* HAVE_STRERROR_R || defined strerror_r */
|
||||
#endif /* not _LIBC */
|
||||
|
||||
static void
|
||||
print_errno_message (int errnum)
|
||||
{
|
||||
char const *s;
|
||||
|
||||
#if defined HAVE_STRERROR_R || _LIBC
|
||||
char errbuf[1024];
|
||||
# if STRERROR_R_CHAR_P || _LIBC
|
||||
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
|
||||
error_tail (int status, int errnum, const char *message, va_list args)
|
||||
{
|
||||
#if _LIBC
|
||||
if (_IO_fwide (stderr, 0) > 0)
|
||||
{
|
||||
# define ALLOCA_LIMIT 2000
|
||||
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 / 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);
|
||||
va_end (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
|
||||
|
||||
fflush (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);
|
||||
|
||||
#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
|
||||
|| 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
|
||||
|
||||
fflush (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:%d: " : " ",
|
||||
file_name, line_number);
|
||||
#else
|
||||
fprintf (stderr, file_name != NULL ? "%s:%d: " : " ",
|
||||
file_name, line_number);
|
||||
#endif
|
||||
|
||||
va_start (args, message);
|
||||
error_tail (status, errnum, message, 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
|
||||
@@ -0,0 +1,65 @@
|
||||
/* Declaration for error-reporting function
|
||||
Copyright (C) 1995, 1996, 1997, 2003, 2006 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 <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _ERROR_H
|
||||
#define _ERROR_H 1
|
||||
|
||||
#ifndef __attribute__
|
||||
/* This feature is available in gcc versions 2.5 and later. */
|
||||
# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || __STRICT_ANSI__
|
||||
# define __attribute__(Spec) /* empty */
|
||||
# endif
|
||||
/* The __-protected variants of `format' and `printf' attributes
|
||||
are accepted by gcc versions 2.6.4 (effectively 2.7) and later. */
|
||||
# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
|
||||
# define __format__ format
|
||||
# define __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, ...)
|
||||
__attribute__ ((__format__ (__printf__, 3, 4)));
|
||||
|
||||
extern void error_at_line (int __status, int __errnum, const char *__fname,
|
||||
unsigned int __lineno, const char *__format, ...)
|
||||
__attribute__ ((__format__ (__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 */
|
||||
@@ -0,0 +1,24 @@
|
||||
/* Failure exit status
|
||||
|
||||
Copyright (C) 2002, 2003, 2005, 2006, 2007 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/>. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "exitfail.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
int volatile exit_failure = EXIT_FAILURE;
|
||||
@@ -0,0 +1,18 @@
|
||||
/* Failure exit status
|
||||
|
||||
Copyright (C) 2002 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/>. */
|
||||
|
||||
extern int volatile exit_failure;
|
||||
@@ -0,0 +1,282 @@
|
||||
/* fchdir replacement.
|
||||
Copyright (C) 2006, 2007 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/>. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
/* Specification. */
|
||||
#include <unistd.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#include "canonicalize.h"
|
||||
#include "dirfd.h"
|
||||
|
||||
/* This replacement assumes that a directory is not renamed while opened
|
||||
through a file descriptor. */
|
||||
|
||||
/* Array of file descriptors opened. If it points to a directory, it stores
|
||||
info about this directory; otherwise it stores an errno value of ENOTDIR. */
|
||||
typedef struct
|
||||
{
|
||||
char *name; /* Absolute name of the directory, or NULL. */
|
||||
int saved_errno; /* If name == NULL: The error code describing the failure
|
||||
reason. */
|
||||
} 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. */
|
||||
static void
|
||||
ensure_dirs_slot (size_t fd)
|
||||
{
|
||||
if (fd >= dirs_allocated)
|
||||
{
|
||||
size_t new_allocated;
|
||||
dir_info_t *new_dirs;
|
||||
size_t i;
|
||||
|
||||
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 (dir_info_t))
|
||||
: (dir_info_t *) malloc (new_allocated * sizeof (dir_info_t)));
|
||||
if (new_dirs != NULL)
|
||||
{
|
||||
for (i = dirs_allocated; i < new_allocated; i++)
|
||||
{
|
||||
new_dirs[i].name = NULL;
|
||||
new_dirs[i].saved_errno = ENOTDIR;
|
||||
}
|
||||
dirs = new_dirs;
|
||||
dirs_allocated = new_allocated;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Override open() and close(), to keep track of the open file descriptors. */
|
||||
|
||||
int
|
||||
rpl_close (int fd)
|
||||
#undef close
|
||||
{
|
||||
int retval = close (fd);
|
||||
|
||||
if (retval >= 0 && fd >= 0 && fd < dirs_allocated)
|
||||
{
|
||||
if (dirs[fd].name != NULL)
|
||||
free (dirs[fd].name);
|
||||
dirs[fd].name = NULL;
|
||||
dirs[fd].saved_errno = ENOTDIR;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
int
|
||||
rpl_open (const char *filename, int flags, ...)
|
||||
#undef open
|
||||
{
|
||||
mode_t mode;
|
||||
int fd;
|
||||
struct stat statbuf;
|
||||
|
||||
mode = 0;
|
||||
if (flags & O_CREAT)
|
||||
{
|
||||
va_list arg;
|
||||
va_start (arg, flags);
|
||||
|
||||
/* If mode_t is narrower than int, use the promoted type (int),
|
||||
not mode_t. Use sizeof to guess whether mode_t is narrower;
|
||||
we don't know of any practical counterexamples. */
|
||||
mode = (sizeof (mode_t) < sizeof (int)
|
||||
? va_arg (arg, int)
|
||||
: va_arg (arg, mode_t));
|
||||
|
||||
va_end (arg);
|
||||
}
|
||||
#if defined GNULIB_OPEN && ((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__)
|
||||
if (strcmp (filename, "/dev/null") == 0)
|
||||
filename = "NUL";
|
||||
#endif
|
||||
fd = open (filename, flags, mode);
|
||||
if (fd >= 0)
|
||||
{
|
||||
ensure_dirs_slot (fd);
|
||||
if (fd < dirs_allocated
|
||||
&& fstat (fd, &statbuf) >= 0 && S_ISDIR (statbuf.st_mode))
|
||||
{
|
||||
dirs[fd].name = canonicalize_file_name (filename);
|
||||
if (dirs[fd].name == NULL)
|
||||
dirs[fd].saved_errno = errno;
|
||||
}
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
||||
/* Override opendir() and closedir(), to keep track of the open file
|
||||
descriptors. Needed because there is a function dirfd(). */
|
||||
|
||||
int
|
||||
rpl_closedir (DIR *dp)
|
||||
#undef closedir
|
||||
{
|
||||
int fd = dirfd (dp);
|
||||
int retval = closedir (dp);
|
||||
|
||||
if (retval >= 0 && fd >= 0 && fd < dirs_allocated)
|
||||
{
|
||||
if (dirs[fd].name != NULL)
|
||||
free (dirs[fd].name);
|
||||
dirs[fd].name = NULL;
|
||||
dirs[fd].saved_errno = ENOTDIR;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
DIR *
|
||||
rpl_opendir (const char *filename)
|
||||
#undef opendir
|
||||
{
|
||||
DIR *dp;
|
||||
|
||||
dp = opendir (filename);
|
||||
if (dp != NULL)
|
||||
{
|
||||
int fd = dirfd (dp);
|
||||
if (fd >= 0)
|
||||
{
|
||||
ensure_dirs_slot (fd);
|
||||
if (fd < dirs_allocated)
|
||||
{
|
||||
dirs[fd].name = canonicalize_file_name (filename);
|
||||
if (dirs[fd].name == NULL)
|
||||
dirs[fd].saved_errno = errno;
|
||||
}
|
||||
}
|
||||
}
|
||||
return dp;
|
||||
}
|
||||
|
||||
/* Override dup() and dup2(), to keep track of open file descriptors. */
|
||||
|
||||
int
|
||||
rpl_dup (int oldfd)
|
||||
#undef dup
|
||||
{
|
||||
int newfd = dup (oldfd);
|
||||
|
||||
if (oldfd >= 0 && newfd >= 0)
|
||||
{
|
||||
ensure_dirs_slot (newfd);
|
||||
if (newfd < dirs_allocated)
|
||||
{
|
||||
if (oldfd < dirs_allocated)
|
||||
{
|
||||
if (dirs[oldfd].name != NULL)
|
||||
{
|
||||
dirs[newfd].name = strdup (dirs[oldfd].name);
|
||||
if (dirs[newfd].name == NULL)
|
||||
dirs[newfd].saved_errno = ENOMEM;
|
||||
}
|
||||
else
|
||||
{
|
||||
dirs[newfd].name = NULL;
|
||||
dirs[newfd].saved_errno = dirs[oldfd].saved_errno;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dirs[newfd].name = NULL;
|
||||
dirs[newfd].saved_errno = ENOMEM;
|
||||
}
|
||||
}
|
||||
}
|
||||
return newfd;
|
||||
}
|
||||
|
||||
int
|
||||
rpl_dup2 (int oldfd, int newfd)
|
||||
#undef dup2
|
||||
{
|
||||
int retval = dup2 (oldfd, newfd);
|
||||
|
||||
if (retval >= 0 && oldfd >= 0 && newfd >= 0 && newfd != oldfd)
|
||||
{
|
||||
ensure_dirs_slot (newfd);
|
||||
if (newfd < dirs_allocated)
|
||||
{
|
||||
if (oldfd < dirs_allocated)
|
||||
{
|
||||
if (dirs[oldfd].name != NULL)
|
||||
{
|
||||
dirs[newfd].name = strdup (dirs[oldfd].name);
|
||||
if (dirs[newfd].name == NULL)
|
||||
dirs[newfd].saved_errno = ENOMEM;
|
||||
}
|
||||
else
|
||||
{
|
||||
dirs[newfd].name = NULL;
|
||||
dirs[newfd].saved_errno = dirs[oldfd].saved_errno;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dirs[newfd].name = NULL;
|
||||
dirs[newfd].saved_errno = ENOMEM;
|
||||
}
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Implement fchdir() in terms of chdir(). */
|
||||
|
||||
int
|
||||
fchdir (int fd)
|
||||
{
|
||||
if (fd >= 0)
|
||||
{
|
||||
if (fd < dirs_allocated)
|
||||
{
|
||||
if (dirs[fd].name != NULL)
|
||||
return chdir (dirs[fd].name);
|
||||
else
|
||||
{
|
||||
errno = dirs[fd].saved_errno;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/* Change the protections of file relative to an open directory.
|
||||
Copyright (C) 2006 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/>. */
|
||||
|
||||
/* written by Jim Meyering */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "openat.h"
|
||||
#include "dirname.h" /* solely for definition of IS_ABSOLUTE_FILE_NAME */
|
||||
#include "save-cwd.h"
|
||||
#include "openat-priv.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, mode_t m) { 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 mkdir/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 flag == 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"
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/* This function serves as replacement for a missing fchownat function,
|
||||
as well as a work around for the fchownat bug in glibc-2.4:
|
||||
<http://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 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/>. */
|
||||
|
||||
/* written by Jim Meyering */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "openat.h"
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include "dirname.h" /* solely for definition of IS_ABSOLUTE_FILE_NAME */
|
||||
#include "save-cwd.h"
|
||||
#include "openat-priv.h"
|
||||
|
||||
/* 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 mkdir/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 flag == 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"
|
||||
@@ -0,0 +1,27 @@
|
||||
/* Like fcntl.h, but redefine some names to avoid glitches.
|
||||
|
||||
Copyright (C) 2005 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/>. */
|
||||
|
||||
/* Written by Paul Eggert. */
|
||||
|
||||
#include <fcntl.h>
|
||||
#include "fcntl-safer.h"
|
||||
|
||||
#undef open
|
||||
#define open open_safer
|
||||
|
||||
#undef creat
|
||||
#define creat creat_safer
|
||||
@@ -0,0 +1,23 @@
|
||||
/* Invoke fcntl-like functions, but avoid some glitches.
|
||||
|
||||
Copyright (C) 2005 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/>. */
|
||||
|
||||
/* Written by Paul Eggert. */
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
int open_safer (char const *, int, ...);
|
||||
int creat_safer (char const *, mode_t);
|
||||
@@ -0,0 +1,121 @@
|
||||
/* DO NOT EDIT! GENERATED AUTOMATICALLY! */
|
||||
/* Like <fcntl.h>, but with non-working flags defined to 0.
|
||||
|
||||
Copyright (C) 2006-2007 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/>. */
|
||||
|
||||
/* written by Paul Eggert */
|
||||
|
||||
#ifndef _GL_FCNTL_H
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
/* The include_next requires a split double-inclusion guard. */
|
||||
#include_next <fcntl.h>
|
||||
|
||||
#ifndef _GL_FCNTL_H
|
||||
#define _GL_FCNTL_H
|
||||
|
||||
|
||||
/* Declare overridden functions. */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if (0 && 0) || defined FCHDIR_REPLACEMENT
|
||||
# define open rpl_open
|
||||
extern int open (const char *filename, int flags, ...);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* Fix up the O_* macros. */
|
||||
|
||||
#if !defined O_DIRECT && defined O_DIRECTIO
|
||||
/* Tru64 spells it `O_DIRECTIO'. */
|
||||
# define O_DIRECT O_DIRECTIO
|
||||
#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_NDELAY
|
||||
# define O_NDELAY 0
|
||||
#endif
|
||||
|
||||
#ifndef O_NOATIME
|
||||
# define O_NOATIME 0
|
||||
#endif
|
||||
|
||||
#ifndef O_NONBLOCK
|
||||
# define O_NONBLOCK O_NDELAY
|
||||
#endif
|
||||
|
||||
#ifndef O_NOCTTY
|
||||
# define O_NOCTTY 0
|
||||
#endif
|
||||
|
||||
#ifndef O_NOFOLLOW
|
||||
# define O_NOFOLLOW 0
|
||||
#endif
|
||||
|
||||
#ifndef O_NOLINKS
|
||||
# define O_NOLINKS 0
|
||||
#endif
|
||||
|
||||
#ifndef O_RSYNC
|
||||
# define O_RSYNC 0
|
||||
#endif
|
||||
|
||||
#ifndef O_SYNC
|
||||
# define O_SYNC 0
|
||||
#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
|
||||
|
||||
#ifdef __BEOS__
|
||||
/* BeOS 5 has 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
|
||||
|
||||
|
||||
#endif /* _GL_FCNTL_H */
|
||||
#endif /* _GL_FCNTL_H */
|
||||
@@ -0,0 +1,120 @@
|
||||
/* Like <fcntl.h>, but with non-working flags defined to 0.
|
||||
|
||||
Copyright (C) 2006-2007 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/>. */
|
||||
|
||||
/* written by Paul Eggert */
|
||||
|
||||
#ifndef _GL_FCNTL_H
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
/* The include_next requires a split double-inclusion guard. */
|
||||
#@INCLUDE_NEXT@ @NEXT_FCNTL_H@
|
||||
|
||||
#ifndef _GL_FCNTL_H
|
||||
#define _GL_FCNTL_H
|
||||
|
||||
|
||||
/* Declare overridden functions. */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if (@GNULIB_OPEN@ && @REPLACE_OPEN@) || defined FCHDIR_REPLACEMENT
|
||||
# define open rpl_open
|
||||
extern int open (const char *filename, int flags, ...);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* Fix up the O_* macros. */
|
||||
|
||||
#if !defined O_DIRECT && defined O_DIRECTIO
|
||||
/* Tru64 spells it `O_DIRECTIO'. */
|
||||
# define O_DIRECT O_DIRECTIO
|
||||
#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_NDELAY
|
||||
# define O_NDELAY 0
|
||||
#endif
|
||||
|
||||
#ifndef O_NOATIME
|
||||
# define O_NOATIME 0
|
||||
#endif
|
||||
|
||||
#ifndef O_NONBLOCK
|
||||
# define O_NONBLOCK O_NDELAY
|
||||
#endif
|
||||
|
||||
#ifndef O_NOCTTY
|
||||
# define O_NOCTTY 0
|
||||
#endif
|
||||
|
||||
#ifndef O_NOFOLLOW
|
||||
# define O_NOFOLLOW 0
|
||||
#endif
|
||||
|
||||
#ifndef O_NOLINKS
|
||||
# define O_NOLINKS 0
|
||||
#endif
|
||||
|
||||
#ifndef O_RSYNC
|
||||
# define O_RSYNC 0
|
||||
#endif
|
||||
|
||||
#ifndef O_SYNC
|
||||
# define O_SYNC 0
|
||||
#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
|
||||
|
||||
#ifdef __BEOS__
|
||||
/* BeOS 5 has 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
|
||||
|
||||
|
||||
#endif /* _GL_FCNTL_H */
|
||||
#endif /* _GL_FCNTL_H */
|
||||
@@ -0,0 +1,56 @@
|
||||
/* Return a safer copy of a file descriptor.
|
||||
|
||||
Copyright (C) 2005, 2006 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/>. */
|
||||
|
||||
/* Written by Paul Eggert. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "unistd-safer.h"
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <unistd.h>
|
||||
#ifndef STDIN_FILENO
|
||||
# define STDIN_FILENO 0
|
||||
#endif
|
||||
#ifndef STDERR_FILENO
|
||||
# define STDERR_FILENO 2
|
||||
#endif
|
||||
|
||||
/* Return FD, unless FD would be a copy of standard input, output, or
|
||||
error; in that case, return a duplicate of FD, closing FD. On
|
||||
failure to duplicate, close FD, set errno, and return -1. Preserve
|
||||
errno if FD is negative, so that the caller can always inspect
|
||||
errno when the returned value is negative.
|
||||
|
||||
This function is usefully wrapped around functions that return file
|
||||
descriptors, e.g., fd_safer (open ("file", O_RDONLY)). */
|
||||
|
||||
int
|
||||
fd_safer (int fd)
|
||||
{
|
||||
if (STDIN_FILENO <= fd && fd <= STDERR_FILENO)
|
||||
{
|
||||
int f = dup_safer (fd);
|
||||
int e = errno;
|
||||
close (fd);
|
||||
errno = e;
|
||||
fd = f;
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
/* fflush.c -- allow flushing input streams
|
||||
Copyright (C) 2007 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/>. */
|
||||
|
||||
/* Written by Eric Blake. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
/* Specification. */
|
||||
#include <stdio.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "freading.h"
|
||||
#include "fpurge.h"
|
||||
|
||||
#undef fflush
|
||||
|
||||
/* Flush all pending data on STREAM according to POSIX rules. Both
|
||||
output and seekable input streams are supported. */
|
||||
int
|
||||
rpl_fflush (FILE *stream)
|
||||
{
|
||||
int result;
|
||||
off_t pos;
|
||||
|
||||
/* When stream is NULL, POSIX and C99 only require flushing of "output
|
||||
streams and update streams in which the most recent operation was not
|
||||
input", and all implementations do this.
|
||||
|
||||
When stream is "an output stream or an update stream in which the most
|
||||
recent operation was not input", POSIX and C99 requires that fflush
|
||||
writes out any buffered data, and all implementations do this.
|
||||
|
||||
When stream is, however, an input stream or an update stream in
|
||||
which the most recent operation was input, C99 specifies nothing,
|
||||
and POSIX only specifies behavior if the stream is seekable.
|
||||
mingw, in particular, drops the input buffer, leaving the file
|
||||
descriptor positioned at the end of the input buffer. I.e. ftell
|
||||
(stream) is lost. We don't want to call the implementation's
|
||||
fflush in this case.
|
||||
|
||||
We test ! freading (stream) here, rather than fwriting (stream), because
|
||||
what we need to know is whether the stream holds a "read buffer", and on
|
||||
mingw this is indicated by _IOREAD, regardless of _IOWRT. */
|
||||
if (stream == NULL || ! freading (stream))
|
||||
return fflush (stream);
|
||||
|
||||
/* POSIX does not specify fflush behavior for non-seekable input
|
||||
streams. Some implementations purge unread data, some return
|
||||
EBADF, some do nothing. */
|
||||
pos = ftello (stream);
|
||||
if (pos == -1)
|
||||
{
|
||||
errno = EBADF;
|
||||
return EOF;
|
||||
}
|
||||
|
||||
/* To get here, we must be flushing a seekable input stream, so the
|
||||
semantics of fpurge are now appropriate to clear the buffer. To
|
||||
avoid losing data, the lseek is also necessary. */
|
||||
result = fpurge (stream);
|
||||
if (result != 0)
|
||||
return result;
|
||||
|
||||
#if defined __sferror && defined __SNPT /* FreeBSD, NetBSD, OpenBSD, MacOS X, Cygwin */
|
||||
|
||||
{
|
||||
/* Disable seek optimization for the next fseeko call. This tells the
|
||||
following fseeko call to seek to the desired position directly, rather
|
||||
than to seek to a block-aligned boundary. */
|
||||
int saved_flags = stream->_flags & (__SOPT | __SNPT);
|
||||
stream->_flags = (stream->_flags & ~__SOPT) | __SNPT;
|
||||
|
||||
result = fseeko (stream, pos, SEEK_SET);
|
||||
|
||||
stream->_flags = (stream->_flags & ~(__SOPT | __SNPT)) | saved_flags;
|
||||
}
|
||||
return result;
|
||||
|
||||
#else
|
||||
|
||||
pos = lseek (fileno (stream), pos, SEEK_SET);
|
||||
if (pos == -1)
|
||||
return EOF;
|
||||
/* After a successful lseek, update the file descriptor's position cache
|
||||
in the stream. */
|
||||
# if defined __sferror /* FreeBSD, NetBSD, OpenBSD, MacOS X, Cygwin */
|
||||
stream->_offset = pos;
|
||||
stream->_flags |= __SOFF;
|
||||
# endif
|
||||
|
||||
return 0;
|
||||
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/* Specialized functions to manipulate a set of files.
|
||||
Copyright (C) 2007 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/>. */
|
||||
|
||||
/* written by Jim Meyering */
|
||||
|
||||
#include <config.h>
|
||||
#include "file-set.h"
|
||||
|
||||
#include "hash-triple.h"
|
||||
#include "xalloc.h"
|
||||
|
||||
/* Record file, FILE, and dev/ino from *STATS, in the hash table, HT.
|
||||
If HT is NULL, return immediately.
|
||||
If memory allocation fails, exit immediately. */
|
||||
void
|
||||
record_file (Hash_table *ht, char const *file, struct stat const *stats)
|
||||
{
|
||||
struct F_triple *ent;
|
||||
|
||||
if (ht == NULL)
|
||||
return;
|
||||
|
||||
ent = xmalloc (sizeof *ent);
|
||||
ent->name = xstrdup (file);
|
||||
ent->st_ino = stats->st_ino;
|
||||
ent->st_dev = stats->st_dev;
|
||||
|
||||
{
|
||||
struct F_triple *ent_from_table = hash_insert (ht, ent);
|
||||
if (ent_from_table == NULL)
|
||||
{
|
||||
/* Insertion failed due to lack of memory. */
|
||||
xalloc_die ();
|
||||
}
|
||||
|
||||
if (ent_from_table != ent)
|
||||
{
|
||||
/* There was alread a matching entry in the table, so ENT was
|
||||
not inserted. Free it. */
|
||||
triple_free (ent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Return true if there is an entry in hash table, HT,
|
||||
for the file described by FILE and STATS. */
|
||||
bool
|
||||
seen_file (Hash_table const *ht, char const *file,
|
||||
struct stat const *stats)
|
||||
{
|
||||
struct F_triple new_ent;
|
||||
|
||||
if (ht == NULL)
|
||||
return false;
|
||||
|
||||
new_ent.name = (char *) file;
|
||||
new_ent.st_ino = stats->st_ino;
|
||||
new_ent.st_dev = stats->st_dev;
|
||||
|
||||
return !!hash_lookup (ht, &new_ent);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "hash.h"
|
||||
|
||||
extern void record_file (Hash_table *ht, char const *file,
|
||||
struct stat const *stats)
|
||||
__attribute__((nonnull(2, 3)));
|
||||
|
||||
extern bool seen_file (Hash_table const *ht, char const *file,
|
||||
struct stat const *stats);
|
||||
@@ -1,10 +1,12 @@
|
||||
/* Convert file size to number of blocks on System V-like machines.
|
||||
Copyright (C) 1990 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
Copyright (C) 1990, 1997, 1998, 1999, 2004, 2005, 2006 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.
|
||||
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
|
||||
@@ -12,41 +14,43 @@
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* Written by Brian L. Matthews, [email protected]. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#if !defined (HAVE_ST_BLOCKS) && !defined(_POSIX_SOURCE)
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#ifndef NINDIR
|
||||
/* Some SysV's, like Irix, seem to lack these. Hope they're correct. */
|
||||
/* Size of a indirect block, in bytes. */
|
||||
#ifndef BSIZE
|
||||
#define BSIZE 1024
|
||||
#if HAVE_SYS_PARAM_H
|
||||
# include <sys/param.h>
|
||||
#endif
|
||||
|
||||
#if !HAVE_STRUCT_STAT_ST_BLOCKS && !defined _POSIX_SOURCE && defined BSIZE
|
||||
|
||||
# include <unistd.h>
|
||||
|
||||
# ifndef NINDIR
|
||||
|
||||
# if defined __DJGPP__
|
||||
typedef long daddr_t; /* for disk address */
|
||||
# endif
|
||||
|
||||
/* Some SysV's, like Irix, seem to lack this. Hope it's correct. */
|
||||
/* Number of inode pointers per indirect block. */
|
||||
#define NINDIR (BSIZE/sizeof(daddr_t))
|
||||
#endif /* !NINDIR */
|
||||
# define NINDIR (BSIZE / sizeof (daddr_t))
|
||||
# endif /* !NINDIR */
|
||||
|
||||
/* Number of direct block addresses in an inode. */
|
||||
#define NDIR 10
|
||||
# define NDIR 10
|
||||
|
||||
/* Return the number of 512-byte blocks in a file of SIZE bytes. */
|
||||
|
||||
long
|
||||
st_blocks (size)
|
||||
long size;
|
||||
off_t
|
||||
st_blocks (off_t size)
|
||||
{
|
||||
long datablks = (size + 512 - 1) / 512;
|
||||
long indrblks = 0;
|
||||
off_t datablks = size / 512 + (size % 512 != 0);
|
||||
off_t indrblks = 0;
|
||||
|
||||
if (datablks > NDIR)
|
||||
{
|
||||
@@ -63,4 +67,8 @@ st_blocks (size)
|
||||
|
||||
return datablks + indrblks;
|
||||
}
|
||||
#else
|
||||
/* This declaration is solely to ensure that after preprocessing
|
||||
this file is never empty. */
|
||||
typedef int textutils_fileblocks_unused;
|
||||
#endif
|
||||
@@ -0,0 +1,180 @@
|
||||
/* filemode.c -- make a string describing file modes
|
||||
|
||||
Copyright (C) 1985, 1990, 1993, 1998-2000, 2004, 2006 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/>. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "filemode.h"
|
||||
|
||||
/* The following is for Cray DMF (Data Migration Facility), which is a
|
||||
HSM file system. A migrated file has a `st_dm_mode' that is
|
||||
different from the normal `st_mode', so any tests for migrated
|
||||
files should use the former. */
|
||||
#if HAVE_ST_DM_MODE
|
||||
# define IS_MIGRATED_FILE(statp) \
|
||||
(S_ISOFD (statp->st_dm_mode) || S_ISOFL (statp->st_dm_mode))
|
||||
#else
|
||||
# define IS_MIGRATED_FILE(statp) 0
|
||||
#endif
|
||||
|
||||
#if ! HAVE_DECL_STRMODE
|
||||
|
||||
/* Return a character indicating the type of file described by
|
||||
file mode BITS:
|
||||
'-' regular file
|
||||
'b' block special file
|
||||
'c' character special file
|
||||
'C' high performance ("contiguous data") file
|
||||
'd' directory
|
||||
'D' door
|
||||
'l' symbolic link
|
||||
'm' multiplexed file (7th edition Unix; obsolete)
|
||||
'n' network special file (HP-UX)
|
||||
'p' fifo (named pipe)
|
||||
'P' port
|
||||
's' socket
|
||||
'w' whiteout (4.4BSD)
|
||||
'?' some other file type */
|
||||
|
||||
static char
|
||||
ftypelet (mode_t bits)
|
||||
{
|
||||
/* These are the most common, so test for them first. */
|
||||
if (S_ISREG (bits))
|
||||
return '-';
|
||||
if (S_ISDIR (bits))
|
||||
return 'd';
|
||||
|
||||
/* Other letters standardized by POSIX 1003.1-2004. */
|
||||
if (S_ISBLK (bits))
|
||||
return 'b';
|
||||
if (S_ISCHR (bits))
|
||||
return 'c';
|
||||
if (S_ISLNK (bits))
|
||||
return 'l';
|
||||
if (S_ISFIFO (bits))
|
||||
return 'p';
|
||||
|
||||
/* Other file types (though not letters) standardized by POSIX. */
|
||||
if (S_ISSOCK (bits))
|
||||
return 's';
|
||||
|
||||
/* Nonstandard file types. */
|
||||
if (S_ISCTG (bits))
|
||||
return 'C';
|
||||
if (S_ISDOOR (bits))
|
||||
return 'D';
|
||||
if (S_ISMPB (bits) || S_ISMPC (bits))
|
||||
return 'm';
|
||||
if (S_ISNWK (bits))
|
||||
return 'n';
|
||||
if (S_ISPORT (bits))
|
||||
return 'P';
|
||||
if (S_ISWHT (bits))
|
||||
return 'w';
|
||||
|
||||
return '?';
|
||||
}
|
||||
|
||||
/* Like filemodestring, but rely only on MODE. */
|
||||
|
||||
void
|
||||
strmode (mode_t mode, char *str)
|
||||
{
|
||||
str[0] = ftypelet (mode);
|
||||
str[1] = mode & S_IRUSR ? 'r' : '-';
|
||||
str[2] = mode & S_IWUSR ? 'w' : '-';
|
||||
str[3] = (mode & S_ISUID
|
||||
? (mode & S_IXUSR ? 's' : 'S')
|
||||
: (mode & S_IXUSR ? 'x' : '-'));
|
||||
str[4] = mode & S_IRGRP ? 'r' : '-';
|
||||
str[5] = mode & S_IWGRP ? 'w' : '-';
|
||||
str[6] = (mode & S_ISGID
|
||||
? (mode & S_IXGRP ? 's' : 'S')
|
||||
: (mode & S_IXGRP ? 'x' : '-'));
|
||||
str[7] = mode & S_IROTH ? 'r' : '-';
|
||||
str[8] = mode & S_IWOTH ? 'w' : '-';
|
||||
str[9] = (mode & S_ISVTX
|
||||
? (mode & S_IXOTH ? 't' : 'T')
|
||||
: (mode & S_IXOTH ? 'x' : '-'));
|
||||
str[10] = ' ';
|
||||
str[11] = '\0';
|
||||
}
|
||||
|
||||
#endif /* ! HAVE_DECL_STRMODE */
|
||||
|
||||
/* filemodestring - fill in string STR with an ls-style ASCII
|
||||
representation of the st_mode field of file stats block STATP.
|
||||
12 characters are stored in STR.
|
||||
The characters stored in STR are:
|
||||
|
||||
0 File type, as in ftypelet above, except that other letters are used
|
||||
for files whose type cannot be determined solely from st_mode:
|
||||
|
||||
'F' semaphore
|
||||
'M' migrated file (Cray DMF)
|
||||
'Q' message queue
|
||||
'S' shared memory object
|
||||
'T' typed memory object
|
||||
|
||||
1 'r' if the owner may read, '-' otherwise.
|
||||
|
||||
2 'w' if the owner may write, '-' otherwise.
|
||||
|
||||
3 'x' if the owner may execute, 's' if the file is
|
||||
set-user-id, '-' otherwise.
|
||||
'S' if the file is set-user-id, but the execute
|
||||
bit isn't set.
|
||||
|
||||
4 'r' if group members may read, '-' otherwise.
|
||||
|
||||
5 'w' if group members may write, '-' otherwise.
|
||||
|
||||
6 'x' if group members may execute, 's' if the file is
|
||||
set-group-id, '-' otherwise.
|
||||
'S' if it is set-group-id but not executable.
|
||||
|
||||
7 'r' if any user may read, '-' otherwise.
|
||||
|
||||
8 'w' if any user may write, '-' otherwise.
|
||||
|
||||
9 'x' if any user may execute, 't' if the file is "sticky"
|
||||
(will be retained in swap space after execution), '-'
|
||||
otherwise.
|
||||
'T' if the file is sticky but not executable.
|
||||
|
||||
10 ' ' for compatibility with 4.4BSD strmode,
|
||||
since this interface does not support ACLs.
|
||||
|
||||
11 '\0'. */
|
||||
|
||||
void
|
||||
filemodestring (struct stat const *statp, char *str)
|
||||
{
|
||||
strmode (statp->st_mode, str);
|
||||
|
||||
if (S_TYPEISSEM (statp))
|
||||
str[0] = 'F';
|
||||
else if (IS_MIGRATED_FILE (statp))
|
||||
str[0] = 'M';
|
||||
else if (S_TYPEISMQ (statp))
|
||||
str[0] = 'Q';
|
||||
else if (S_TYPEISSHM (statp))
|
||||
str[0] = 'S';
|
||||
else if (S_TYPEISTMO (statp))
|
||||
str[0] = 'T';
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/* Make a string describing file modes.
|
||||
|
||||
Copyright (C) 1998, 1999, 2003, 2006 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/>. */
|
||||
|
||||
#ifndef FILEMODE_H_
|
||||
|
||||
# include <sys/types.h>
|
||||
# include <sys/stat.h>
|
||||
|
||||
# if HAVE_DECL_STRMODE
|
||||
# include <string.h> /* FreeBSD, OpenBSD */
|
||||
# include <unistd.h> /* NetBSD */
|
||||
# else
|
||||
void strmode (mode_t mode, char *str);
|
||||
# endif
|
||||
|
||||
void filemodestring (struct stat const *statp, char *str);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,102 @@
|
||||
/* Concatenate two arbitrary file names.
|
||||
|
||||
Copyright (C) 1996-2007 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/>. */
|
||||
|
||||
/* Written by Jim Meyering. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
/* Specification. */
|
||||
#include "filenamecat.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "dirname.h"
|
||||
#include "xalloc.h"
|
||||
|
||||
#if ! HAVE_MEMPCPY && ! defined mempcpy
|
||||
# define mempcpy(D, S, N) ((void *) ((char *) memcpy (D, S, N) + (N)))
|
||||
#endif
|
||||
|
||||
/* Return the longest suffix of F that is a relative file name.
|
||||
If it has no such suffix, return the empty string. */
|
||||
|
||||
static char const *
|
||||
longest_relative_suffix (char const *f)
|
||||
{
|
||||
for (f += FILE_SYSTEM_PREFIX_LEN (f); ISSLASH (*f); f++)
|
||||
continue;
|
||||
return f;
|
||||
}
|
||||
|
||||
/* Concatenate two file name components, DIR and ABASE, in
|
||||
newly-allocated storage and return the result.
|
||||
The resulting file name F is such that the commands "ls F" and "(cd
|
||||
DIR; ls BASE)" refer to the same file, where BASE is ABASE with any
|
||||
file system prefixes and leading separators removed.
|
||||
Arrange for a directory separator if necessary between DIR and BASE
|
||||
in the result, removing any redundant separators.
|
||||
In any case, if BASE_IN_RESULT is non-NULL, set
|
||||
*BASE_IN_RESULT to point to the copy of ABASE in the returned
|
||||
concatenation. However, if ABASE begins with more than one slash,
|
||||
set *BASE_IN_RESULT to point to the sole corresponding slash that
|
||||
is copied into the result buffer.
|
||||
|
||||
Return NULL if malloc fails. */
|
||||
|
||||
char *
|
||||
mfile_name_concat (char const *dir, char const *abase, char **base_in_result)
|
||||
{
|
||||
char const *dirbase = last_component (dir);
|
||||
size_t dirbaselen = base_len (dirbase);
|
||||
size_t dirlen = dirbase - dir + dirbaselen;
|
||||
size_t needs_separator = (dirbaselen && ! ISSLASH (dirbase[dirbaselen - 1]));
|
||||
|
||||
char const *base = longest_relative_suffix (abase);
|
||||
size_t baselen = strlen (base);
|
||||
|
||||
char *p_concat = malloc (dirlen + needs_separator + baselen + 1);
|
||||
char *p;
|
||||
|
||||
if (p_concat == NULL)
|
||||
return NULL;
|
||||
|
||||
p = mempcpy (p_concat, dir, dirlen);
|
||||
*p = DIRECTORY_SEPARATOR;
|
||||
p += needs_separator;
|
||||
|
||||
if (base_in_result)
|
||||
*base_in_result = p - IS_ABSOLUTE_FILE_NAME (abase);
|
||||
|
||||
p = mempcpy (p, base, baselen);
|
||||
*p = '\0';
|
||||
|
||||
return p_concat;
|
||||
}
|
||||
|
||||
/* Just like mfile_name_concat, above, except, rather than
|
||||
returning NULL upon malloc failure, here, we report the
|
||||
"memory exhausted" condition and exit. */
|
||||
|
||||
char *
|
||||
file_name_concat (char const *dir, char const *abase, char **base_in_result)
|
||||
{
|
||||
char *p = mfile_name_concat (dir, abase, base_in_result);
|
||||
if (p == NULL)
|
||||
xalloc_die ();
|
||||
return p;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/* Concatenate two arbitrary file names.
|
||||
|
||||
Copyright (C) 1996, 1997, 2003, 2005, 2007 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/>. */
|
||||
|
||||
/* Written by Jim Meyering. */
|
||||
|
||||
char *file_name_concat (char const *dir, char const *base,
|
||||
char **base_in_result);
|
||||
|
||||
char *mfile_name_concat (char const *dir, char const *base,
|
||||
char **base_in_result);
|
||||
@@ -0,0 +1,354 @@
|
||||
/* Copyright (C) 1991,1992,1993,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007
|
||||
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, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#ifndef _LIBC
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
/* Enable GNU extensions in fnmatch.h. */
|
||||
#ifndef _GNU_SOURCE
|
||||
# define _GNU_SOURCE 1
|
||||
#endif
|
||||
|
||||
#if ! defined __builtin_expect && __GNUC__ < 3
|
||||
# define __builtin_expect(expr, expected) (expr)
|
||||
#endif
|
||||
|
||||
#include <fnmatch.h>
|
||||
|
||||
#include <alloca.h>
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define WIDE_CHAR_SUPPORT \
|
||||
(HAVE_WCTYPE_H && HAVE_BTOWC && HAVE_ISWCTYPE \
|
||||
&& HAVE_WMEMCHR && (HAVE_WMEMCPY || HAVE_WMEMPCPY))
|
||||
|
||||
/* For platform which support the ISO C amendement 1 functionality we
|
||||
support user defined character classes. */
|
||||
#if defined _LIBC || WIDE_CHAR_SUPPORT
|
||||
# include <wctype.h>
|
||||
# include <wchar.h>
|
||||
#endif
|
||||
|
||||
/* We need some of the locale data (the collation sequence information)
|
||||
but there is no interface to get this information in general. Therefore
|
||||
we support a correct implementation only in glibc. */
|
||||
#ifdef _LIBC
|
||||
# include "../locale/localeinfo.h"
|
||||
# include "../locale/elem-hash.h"
|
||||
# include "../locale/coll-lookup.h"
|
||||
# include <shlib-compat.h>
|
||||
|
||||
# define CONCAT(a,b) __CONCAT(a,b)
|
||||
# define mbsrtowcs __mbsrtowcs
|
||||
# define fnmatch __fnmatch
|
||||
extern int fnmatch (const char *pattern, const char *string, int flags);
|
||||
#endif
|
||||
|
||||
#ifndef SIZE_MAX
|
||||
# define SIZE_MAX ((size_t) -1)
|
||||
#endif
|
||||
|
||||
/* We often have to test for FNM_FILE_NAME and FNM_PERIOD being both set. */
|
||||
#define NO_LEADING_PERIOD(flags) \
|
||||
((flags & (FNM_FILE_NAME | FNM_PERIOD)) == (FNM_FILE_NAME | FNM_PERIOD))
|
||||
|
||||
/* Comment out all this code if we are using the GNU C Library, and are not
|
||||
actually compiling the library itself, and have not detected a bug
|
||||
in the library. This code is part of the GNU C
|
||||
Library, but also included in many other GNU distributions. Compiling
|
||||
and linking in this code is a waste when using the GNU C library
|
||||
(especially if it is a shared library). Rather than having every GNU
|
||||
program understand `configure --with-gnu-libc' and omit the object files,
|
||||
it is simpler to just do this in the source for each such file. */
|
||||
|
||||
#if defined _LIBC || !defined __GNU_LIBRARY__ || !HAVE_FNMATCH_GNU
|
||||
|
||||
|
||||
# if ! (defined isblank || (HAVE_ISBLANK && HAVE_DECL_ISBLANK))
|
||||
# define isblank(c) ((c) == ' ' || (c) == '\t')
|
||||
# endif
|
||||
|
||||
# define STREQ(s1, s2) ((strcmp (s1, s2) == 0))
|
||||
|
||||
# if defined _LIBC || WIDE_CHAR_SUPPORT
|
||||
/* The GNU C library provides support for user-defined character classes
|
||||
and the functions from ISO C amendement 1. */
|
||||
# ifdef CHARCLASS_NAME_MAX
|
||||
# define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX
|
||||
# else
|
||||
/* This shouldn't happen but some implementation might still have this
|
||||
problem. Use a reasonable default value. */
|
||||
# define CHAR_CLASS_MAX_LENGTH 256
|
||||
# endif
|
||||
|
||||
# ifdef _LIBC
|
||||
# define IS_CHAR_CLASS(string) __wctype (string)
|
||||
# else
|
||||
# define IS_CHAR_CLASS(string) wctype (string)
|
||||
# endif
|
||||
|
||||
# ifdef _LIBC
|
||||
# define ISWCTYPE(WC, WT) __iswctype (WC, WT)
|
||||
# else
|
||||
# define ISWCTYPE(WC, WT) iswctype (WC, WT)
|
||||
# endif
|
||||
|
||||
# if (HAVE_MBSTATE_T && HAVE_MBSRTOWCS) || _LIBC
|
||||
/* In this case we are implementing the multibyte character handling. */
|
||||
# define HANDLE_MULTIBYTE 1
|
||||
# endif
|
||||
|
||||
# else
|
||||
# define CHAR_CLASS_MAX_LENGTH 6 /* Namely, `xdigit'. */
|
||||
|
||||
# define IS_CHAR_CLASS(string) \
|
||||
(STREQ (string, "alpha") || STREQ (string, "upper") \
|
||||
|| STREQ (string, "lower") || STREQ (string, "digit") \
|
||||
|| STREQ (string, "alnum") || STREQ (string, "xdigit") \
|
||||
|| STREQ (string, "space") || STREQ (string, "print") \
|
||||
|| STREQ (string, "punct") || STREQ (string, "graph") \
|
||||
|| STREQ (string, "cntrl") || STREQ (string, "blank"))
|
||||
# endif
|
||||
|
||||
/* Avoid depending on library functions or files
|
||||
whose names are inconsistent. */
|
||||
|
||||
/* Global variable. */
|
||||
static int posixly_correct;
|
||||
|
||||
# ifndef internal_function
|
||||
/* Inside GNU libc we mark some function in a special way. In other
|
||||
environments simply ignore the marking. */
|
||||
# define internal_function
|
||||
# endif
|
||||
|
||||
/* Note that this evaluates C many times. */
|
||||
# define FOLD(c) ((flags & FNM_CASEFOLD) ? tolower (c) : (c))
|
||||
# define CHAR char
|
||||
# define UCHAR unsigned char
|
||||
# define INT int
|
||||
# define FCT internal_fnmatch
|
||||
# define EXT ext_match
|
||||
# define END end_pattern
|
||||
# define L_(CS) CS
|
||||
# ifdef _LIBC
|
||||
# define BTOWC(C) __btowc (C)
|
||||
# else
|
||||
# define BTOWC(C) btowc (C)
|
||||
# endif
|
||||
# define STRLEN(S) strlen (S)
|
||||
# define STRCAT(D, S) strcat (D, S)
|
||||
# ifdef _LIBC
|
||||
# define MEMPCPY(D, S, N) __mempcpy (D, S, N)
|
||||
# else
|
||||
# if HAVE_MEMPCPY
|
||||
# define MEMPCPY(D, S, N) mempcpy (D, S, N)
|
||||
# else
|
||||
# define MEMPCPY(D, S, N) ((void *) ((char *) memcpy (D, S, N) + (N)))
|
||||
# endif
|
||||
# endif
|
||||
# define MEMCHR(S, C, N) memchr (S, C, N)
|
||||
# define STRCOLL(S1, S2) strcoll (S1, S2)
|
||||
# include "fnmatch_loop.c"
|
||||
|
||||
|
||||
# if HANDLE_MULTIBYTE
|
||||
# define FOLD(c) ((flags & FNM_CASEFOLD) ? towlower (c) : (c))
|
||||
# define CHAR wchar_t
|
||||
# define UCHAR wint_t
|
||||
# define INT wint_t
|
||||
# define FCT internal_fnwmatch
|
||||
# define EXT ext_wmatch
|
||||
# define END end_wpattern
|
||||
# define L_(CS) L##CS
|
||||
# define BTOWC(C) (C)
|
||||
# ifdef _LIBC
|
||||
# define STRLEN(S) __wcslen (S)
|
||||
# define STRCAT(D, S) __wcscat (D, S)
|
||||
# define MEMPCPY(D, S, N) __wmempcpy (D, S, N)
|
||||
# else
|
||||
# define STRLEN(S) wcslen (S)
|
||||
# define STRCAT(D, S) wcscat (D, S)
|
||||
# if HAVE_WMEMPCPY
|
||||
# define MEMPCPY(D, S, N) wmempcpy (D, S, N)
|
||||
# else
|
||||
# define MEMPCPY(D, S, N) (wmemcpy (D, S, N) + (N))
|
||||
# endif
|
||||
# endif
|
||||
# define MEMCHR(S, C, N) wmemchr (S, C, N)
|
||||
# define STRCOLL(S1, S2) wcscoll (S1, S2)
|
||||
# define WIDE_CHAR_VERSION 1
|
||||
|
||||
# undef IS_CHAR_CLASS
|
||||
/* We have to convert the wide character string in a multibyte string. But
|
||||
we know that the character class names consist of alphanumeric characters
|
||||
from the portable character set, and since the wide character encoding
|
||||
for a member of the portable character set is the same code point as
|
||||
its single-byte encoding, we can use a simplified method to convert the
|
||||
string to a multibyte character string. */
|
||||
static wctype_t
|
||||
is_char_class (const wchar_t *wcs)
|
||||
{
|
||||
char s[CHAR_CLASS_MAX_LENGTH + 1];
|
||||
char *cp = s;
|
||||
|
||||
do
|
||||
{
|
||||
/* Test for a printable character from the portable character set. */
|
||||
# ifdef _LIBC
|
||||
if (*wcs < 0x20 || *wcs > 0x7e
|
||||
|| *wcs == 0x24 || *wcs == 0x40 || *wcs == 0x60)
|
||||
return (wctype_t) 0;
|
||||
# else
|
||||
switch (*wcs)
|
||||
{
|
||||
case L' ': case L'!': case L'"': case L'#': case L'%':
|
||||
case L'&': case L'\'': case L'(': case L')': case L'*':
|
||||
case L'+': case L',': case L'-': case L'.': case L'/':
|
||||
case L'0': case L'1': case L'2': case L'3': case L'4':
|
||||
case L'5': case L'6': case L'7': case L'8': case L'9':
|
||||
case L':': case L';': case L'<': case L'=': case L'>':
|
||||
case L'?':
|
||||
case L'A': case L'B': case L'C': case L'D': case L'E':
|
||||
case L'F': case L'G': case L'H': case L'I': case L'J':
|
||||
case L'K': case L'L': case L'M': case L'N': case L'O':
|
||||
case L'P': case L'Q': case L'R': case L'S': case L'T':
|
||||
case L'U': case L'V': case L'W': case L'X': case L'Y':
|
||||
case L'Z':
|
||||
case L'[': case L'\\': case L']': case L'^': case L'_':
|
||||
case L'a': case L'b': case L'c': case L'd': case L'e':
|
||||
case L'f': case L'g': case L'h': case L'i': case L'j':
|
||||
case L'k': case L'l': case L'm': case L'n': case L'o':
|
||||
case L'p': case L'q': case L'r': case L's': case L't':
|
||||
case L'u': case L'v': case L'w': case L'x': case L'y':
|
||||
case L'z': case L'{': case L'|': case L'}': case L'~':
|
||||
break;
|
||||
default:
|
||||
return (wctype_t) 0;
|
||||
}
|
||||
# endif
|
||||
|
||||
/* Avoid overrunning the buffer. */
|
||||
if (cp == s + CHAR_CLASS_MAX_LENGTH)
|
||||
return (wctype_t) 0;
|
||||
|
||||
*cp++ = (char) *wcs++;
|
||||
}
|
||||
while (*wcs != L'\0');
|
||||
|
||||
*cp = '\0';
|
||||
|
||||
# ifdef _LIBC
|
||||
return __wctype (s);
|
||||
# else
|
||||
return wctype (s);
|
||||
# endif
|
||||
}
|
||||
# define IS_CHAR_CLASS(string) is_char_class (string)
|
||||
|
||||
# include "fnmatch_loop.c"
|
||||
# endif
|
||||
|
||||
|
||||
int
|
||||
fnmatch (const char *pattern, const char *string, int flags)
|
||||
{
|
||||
# if HANDLE_MULTIBYTE
|
||||
# define ALLOCA_LIMIT 2000
|
||||
if (__builtin_expect (MB_CUR_MAX, 1) != 1)
|
||||
{
|
||||
mbstate_t ps;
|
||||
size_t patsize;
|
||||
size_t strsize;
|
||||
size_t totsize;
|
||||
wchar_t *wpattern;
|
||||
wchar_t *wstring;
|
||||
int res;
|
||||
|
||||
/* Calculate the size needed to convert the strings to
|
||||
wide characters. */
|
||||
memset (&ps, '\0', sizeof (ps));
|
||||
patsize = mbsrtowcs (NULL, &pattern, 0, &ps) + 1;
|
||||
if (__builtin_expect (patsize != 0, 1))
|
||||
{
|
||||
assert (mbsinit (&ps));
|
||||
strsize = mbsrtowcs (NULL, &string, 0, &ps) + 1;
|
||||
if (__builtin_expect (strsize != 0, 1))
|
||||
{
|
||||
assert (mbsinit (&ps));
|
||||
totsize = patsize + strsize;
|
||||
if (__builtin_expect (! (patsize <= totsize
|
||||
&& totsize <= SIZE_MAX / sizeof (wchar_t)),
|
||||
0))
|
||||
{
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Allocate room for the wide characters. */
|
||||
if (__builtin_expect (totsize < ALLOCA_LIMIT, 1))
|
||||
wpattern = (wchar_t *) alloca (totsize * sizeof (wchar_t));
|
||||
else
|
||||
{
|
||||
wpattern = malloc (totsize * sizeof (wchar_t));
|
||||
if (__builtin_expect (! wpattern, 0))
|
||||
{
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
wstring = wpattern + patsize;
|
||||
|
||||
/* Convert the strings into wide characters. */
|
||||
mbsrtowcs (wpattern, &pattern, patsize, &ps);
|
||||
assert (mbsinit (&ps));
|
||||
mbsrtowcs (wstring, &string, strsize, &ps);
|
||||
|
||||
res = internal_fnwmatch (wpattern, wstring, wstring + strsize - 1,
|
||||
flags & FNM_PERIOD, flags);
|
||||
|
||||
if (__builtin_expect (! (totsize < ALLOCA_LIMIT), 0))
|
||||
free (wpattern);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# endif /* HANDLE_MULTIBYTE */
|
||||
|
||||
return internal_fnmatch (pattern, string, string + strlen (string),
|
||||
flags & FNM_PERIOD, flags);
|
||||
}
|
||||
|
||||
# ifdef _LIBC
|
||||
# undef fnmatch
|
||||
versioned_symbol (libc, __fnmatch, fnmatch, GLIBC_2_2_3);
|
||||
# if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_2_3)
|
||||
strong_alias (__fnmatch, __fnmatch_old)
|
||||
compat_symbol (libc, __fnmatch_old, fnmatch, GLIBC_2_0);
|
||||
# endif
|
||||
libc_hidden_ver (__fnmatch, fnmatch)
|
||||
# endif
|
||||
|
||||
#endif /* _LIBC or not __GNU_LIBRARY__. */
|
||||
@@ -0,0 +1,66 @@
|
||||
/* DO NOT EDIT! GENERATED AUTOMATICALLY! */
|
||||
/* Copyright (C) 1991, 1992, 1993, 1996, 1997, 1998, 1999, 2001, 2002, 2003,
|
||||
2005, 2007 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, 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. */
|
||||
|
||||
#ifndef _FNMATCH_H
|
||||
#define _FNMATCH_H 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* We #undef these before defining them because some losing systems
|
||||
(HP-UX A.08.07 for example) define these in <unistd.h>. */
|
||||
#undef FNM_PATHNAME
|
||||
#undef FNM_NOESCAPE
|
||||
#undef FNM_PERIOD
|
||||
|
||||
/* Bits set in the FLAGS argument to `fnmatch'. */
|
||||
#define FNM_PATHNAME (1 << 0) /* No wildcard can ever match `/'. */
|
||||
#define FNM_NOESCAPE (1 << 1) /* Backslashes don't quote special chars. */
|
||||
#define FNM_PERIOD (1 << 2) /* Leading `.' is matched only explicitly. */
|
||||
|
||||
#if !defined _POSIX_C_SOURCE || _POSIX_C_SOURCE < 2 || defined _GNU_SOURCE
|
||||
# define FNM_FILE_NAME FNM_PATHNAME /* Preferred GNU name. */
|
||||
# define FNM_LEADING_DIR (1 << 3) /* Ignore `/...' after a match. */
|
||||
# define FNM_CASEFOLD (1 << 4) /* Compare without regard to case. */
|
||||
# define FNM_EXTMATCH (1 << 5) /* Use ksh-like extended matching. */
|
||||
#endif
|
||||
|
||||
/* Value returned by `fnmatch' if STRING does not match PATTERN. */
|
||||
#define FNM_NOMATCH 1
|
||||
|
||||
/* This value is returned if the implementation does not support
|
||||
`fnmatch'. Since this is not the case here it will never be
|
||||
returned but the conformance test suites still require the symbol
|
||||
to be defined. */
|
||||
#ifdef _XOPEN_SOURCE
|
||||
# define FNM_NOSYS (-1)
|
||||
#endif
|
||||
|
||||
/* Match NAME against the file name pattern PATTERN,
|
||||
returning zero if it matches, FNM_NOMATCH if not. */
|
||||
extern int fnmatch (const char *__pattern, const char *__name,
|
||||
int __flags);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* fnmatch.h */
|
||||
@@ -0,0 +1,65 @@
|
||||
/* Copyright (C) 1991, 1992, 1993, 1996, 1997, 1998, 1999, 2001, 2002, 2003,
|
||||
2005, 2007 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, 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. */
|
||||
|
||||
#ifndef _FNMATCH_H
|
||||
#define _FNMATCH_H 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* We #undef these before defining them because some losing systems
|
||||
(HP-UX A.08.07 for example) define these in <unistd.h>. */
|
||||
#undef FNM_PATHNAME
|
||||
#undef FNM_NOESCAPE
|
||||
#undef FNM_PERIOD
|
||||
|
||||
/* Bits set in the FLAGS argument to `fnmatch'. */
|
||||
#define FNM_PATHNAME (1 << 0) /* No wildcard can ever match `/'. */
|
||||
#define FNM_NOESCAPE (1 << 1) /* Backslashes don't quote special chars. */
|
||||
#define FNM_PERIOD (1 << 2) /* Leading `.' is matched only explicitly. */
|
||||
|
||||
#if !defined _POSIX_C_SOURCE || _POSIX_C_SOURCE < 2 || defined _GNU_SOURCE
|
||||
# define FNM_FILE_NAME FNM_PATHNAME /* Preferred GNU name. */
|
||||
# define FNM_LEADING_DIR (1 << 3) /* Ignore `/...' after a match. */
|
||||
# define FNM_CASEFOLD (1 << 4) /* Compare without regard to case. */
|
||||
# define FNM_EXTMATCH (1 << 5) /* Use ksh-like extended matching. */
|
||||
#endif
|
||||
|
||||
/* Value returned by `fnmatch' if STRING does not match PATTERN. */
|
||||
#define FNM_NOMATCH 1
|
||||
|
||||
/* This value is returned if the implementation does not support
|
||||
`fnmatch'. Since this is not the case here it will never be
|
||||
returned but the conformance test suites still require the symbol
|
||||
to be defined. */
|
||||
#ifdef _XOPEN_SOURCE
|
||||
# define FNM_NOSYS (-1)
|
||||
#endif
|
||||
|
||||
/* Match NAME against the file name pattern PATTERN,
|
||||
returning zero if it matches, FNM_NOMATCH if not. */
|
||||
extern int fnmatch (const char *__pattern, const char *__name,
|
||||
int __flags);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* fnmatch.h */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,67 @@
|
||||
/* Invoke fopen, but avoid some glitches.
|
||||
|
||||
Copyright (C) 2001, 2004, 2005, 2006 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/>. */
|
||||
|
||||
/* Written by Paul Eggert. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "stdio-safer.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include "unistd-safer.h"
|
||||
|
||||
#ifndef STDERR_FILENO
|
||||
# define STDERR_FILENO 2
|
||||
#endif
|
||||
|
||||
/* Like fopen, but do not return stdin, stdout, or stderr. */
|
||||
|
||||
FILE *
|
||||
fopen_safer (char const *file, char const *mode)
|
||||
{
|
||||
FILE *fp = fopen (file, mode);
|
||||
|
||||
if (fp)
|
||||
{
|
||||
int fd = fileno (fp);
|
||||
|
||||
if (0 <= fd && fd <= STDERR_FILENO)
|
||||
{
|
||||
int f = dup_safer (fd);
|
||||
|
||||
if (f < 0)
|
||||
{
|
||||
int e = errno;
|
||||
fclose (fp);
|
||||
errno = e;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (fclose (fp) != 0
|
||||
|| ! (fp = fdopen (f, mode)))
|
||||
{
|
||||
int e = errno;
|
||||
close (f);
|
||||
errno = e;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return fp;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/* fpending.c -- return the number of pending output bytes on a stream
|
||||
Copyright (C) 2000, 2004, 2006, 2007 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/>. */
|
||||
|
||||
/* Written by Jim Meyering. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "fpending.h"
|
||||
|
||||
/* Return the number of pending (aka buffered, unflushed)
|
||||
bytes on the stream, FP, that is open for writing. */
|
||||
size_t
|
||||
__fpending (FILE *fp)
|
||||
{
|
||||
return PENDING_OUTPUT_N_BYTES;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/* Declare __fpending.
|
||||
|
||||
Copyright (C) 2000, 2003, 2005, 2006 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/>.
|
||||
|
||||
Written by Jim Meyering. */
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifndef HAVE_DECL___FPENDING
|
||||
"this configure-time declaration test was not run"
|
||||
#endif
|
||||
|
||||
#if HAVE_DECL___FPENDING
|
||||
# if HAVE_STDIO_EXT_H
|
||||
# include <stdio_ext.h>
|
||||
# endif
|
||||
#else
|
||||
size_t __fpending (FILE *);
|
||||
#endif
|
||||
@@ -0,0 +1,121 @@
|
||||
/* Flushing buffers of a FILE stream.
|
||||
Copyright (C) 2007 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/>. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
/* Specification. */
|
||||
#include "fpurge.h"
|
||||
|
||||
#if HAVE___FPURGE /* glibc >= 2.2, Solaris >= 7 */
|
||||
# include <stdio_ext.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
|
||||
int
|
||||
fpurge (FILE *fp)
|
||||
{
|
||||
#if HAVE___FPURGE /* glibc >= 2.2, Solaris >= 7 */
|
||||
|
||||
__fpurge (fp);
|
||||
/* The __fpurge function does not have a return value. */
|
||||
return 0;
|
||||
|
||||
#elif HAVE_FPURGE /* FreeBSD, NetBSD, OpenBSD, MacOS X */
|
||||
|
||||
/* Call the system's fpurge function. */
|
||||
# undef fpurge
|
||||
# if !HAVE_DECL_FPURGE
|
||||
extern int fpurge (FILE *);
|
||||
# endif
|
||||
int result = fpurge (fp);
|
||||
# if defined __sferror /* FreeBSD, NetBSD, OpenBSD, MacOS X, Cygwin */
|
||||
if (result == 0)
|
||||
/* Correct the invariants that fpurge broke.
|
||||
<stdio.h> on BSD systems says:
|
||||
"The following always hold: if _flags & __SRD, _w is 0."
|
||||
If this invariant is not fulfilled and the stream is read-write but
|
||||
currently writing, subsequent putc or fputc calls will write directly
|
||||
into the buffer, although they shouldn't be allowed to. */
|
||||
if ((fp->_flags & __SRD) != 0)
|
||||
fp->_w = 0;
|
||||
# endif
|
||||
return result;
|
||||
|
||||
#else
|
||||
|
||||
/* Most systems provide FILE as a struct and the necessary bitmask in
|
||||
<stdio.h>, because they need it for implementing getc() and putc() as
|
||||
fast macros. */
|
||||
# if defined _IO_ferror_unlocked /* GNU libc, BeOS */
|
||||
fp->_IO_read_end = fp->_IO_read_ptr;
|
||||
fp->_IO_write_ptr = fp->_IO_write_base;
|
||||
/* Avoid memory leak when there is an active ungetc buffer. */
|
||||
if (fp->_IO_save_base != NULL)
|
||||
{
|
||||
free (fp->_IO_save_base);
|
||||
fp->_IO_save_base = NULL;
|
||||
}
|
||||
return 0;
|
||||
# elif defined __sferror /* FreeBSD, NetBSD, OpenBSD, MacOS X, Cygwin */
|
||||
fp->_p = fp->_bf._base;
|
||||
fp->_r = 0;
|
||||
fp->_w = ((fp->_flags & (__SLBF | __SNBF | __SRD)) == 0 /* fully buffered and not currently reading? */
|
||||
? fp->_bf._size
|
||||
: 0);
|
||||
/* Avoid memory leak when there is an active ungetc buffer. */
|
||||
# if defined __NetBSD__ || defined __OpenBSD__ /* NetBSD, OpenBSD */
|
||||
/* See <http://cvsweb.netbsd.org/bsdweb.cgi/src/lib/libc/stdio/fileext.h?rev=HEAD&content-type=text/x-cvsweb-markup>
|
||||
and <http://www.openbsd.org/cgi-bin/cvsweb/src/lib/libc/stdio/fileext.h?rev=HEAD&content-type=text/x-cvsweb-markup> */
|
||||
# define fp_ub ((struct { struct __sbuf _ub; } *) fp->_ext._base)->_ub
|
||||
# else /* FreeBSD, MacOS X, Cygwin */
|
||||
# define fp_ub fp->_ub
|
||||
# endif
|
||||
if (fp_ub._base != NULL)
|
||||
{
|
||||
if (fp_ub._base != fp->_ubuf)
|
||||
free (fp_ub._base);
|
||||
fp_ub._base = NULL;
|
||||
}
|
||||
return 0;
|
||||
# elif defined _IOERR /* AIX, HP-UX, IRIX, OSF/1, Solaris, mingw */
|
||||
fp->_ptr = fp->_base;
|
||||
if (fp->_ptr != NULL)
|
||||
fp->_cnt = 0;
|
||||
return 0;
|
||||
# elif defined __UCLIBC__ /* uClibc */
|
||||
# ifdef __STDIO_BUFFERS
|
||||
if (fp->__modeflags & __FLAG_WRITING)
|
||||
fp->__bufpos = fp->__bufstart;
|
||||
else if (fp->__modeflags & (__FLAG_READONLY | __FLAG_READING))
|
||||
fp->__bufpos = fp->__bufread;
|
||||
# endif
|
||||
return 0;
|
||||
# elif defined __QNX__ /* QNX */
|
||||
fp->_Rback = fp->_Back + sizeof (fp->_Back);
|
||||
fp->_Rsave = NULL;
|
||||
if (fp->_Mode & 0x2000 /* _MWRITE */)
|
||||
/* fp->_Buf <= fp->_Next <= fp->_Wend */
|
||||
fp->_Next = fp->_Buf;
|
||||
else
|
||||
/* fp->_Buf <= fp->_Next <= fp->_Rend */
|
||||
fp->_Rend = fp->_Next;
|
||||
return 0;
|
||||
# else
|
||||
#error "Please port gnulib fpurge.c to your platform! Look at the definitions of fflush, setvbuf and ungetc on your system, then report this to bug-gnulib."
|
||||
# endif
|
||||
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/* Flushing buffers of a FILE stream.
|
||||
Copyright (C) 2007 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/>. */
|
||||
|
||||
#ifndef _GL_FPURGE_H
|
||||
#define _GL_FPURGE_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Discard all pending buffered I/O on the stream STREAM.
|
||||
STREAM must not be wide-character oriented.
|
||||
Return 0 if successful. Upon error, return -1 and set errno. */
|
||||
#if HAVE_FPURGE
|
||||
# define fpurge rpl_fpurge
|
||||
#endif
|
||||
extern int fpurge (FILE *stream);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _GL_FPURGE_H */
|
||||
@@ -0,0 +1,66 @@
|
||||
/* Retrieve information about a FILE stream.
|
||||
Copyright (C) 2007 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/>. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
/* Specification. */
|
||||
#include "freadahead.h"
|
||||
|
||||
size_t
|
||||
freadahead (FILE *fp)
|
||||
{
|
||||
#if defined _IO_ferror_unlocked /* GNU libc, BeOS */
|
||||
if (fp->_IO_write_ptr > fp->_IO_write_base)
|
||||
return 0;
|
||||
return fp->_IO_read_end - fp->_IO_read_ptr;
|
||||
#elif defined __sferror /* FreeBSD, NetBSD, OpenBSD, MacOS X, Cygwin */
|
||||
if ((fp->_flags & __SWR) != 0 || fp->_r < 0)
|
||||
return 0;
|
||||
return fp->_r;
|
||||
#elif defined _IOERR /* AIX, HP-UX, IRIX, OSF/1, Solaris, mingw */
|
||||
# if defined __sun && defined _LP64 /* Solaris/{SPARC,AMD64} 64-bit */
|
||||
# define fp_ ((struct { unsigned char *_ptr; \
|
||||
unsigned char *_base; \
|
||||
unsigned char *_end; \
|
||||
long _cnt; \
|
||||
int _file; \
|
||||
unsigned int _flag; \
|
||||
} *) fp)
|
||||
if ((fp_->_flag & _IOWRT) != 0)
|
||||
return 0;
|
||||
return fp_->_cnt;
|
||||
# else
|
||||
if ((fp->_flag & _IOWRT) != 0)
|
||||
return 0;
|
||||
return fp->_cnt;
|
||||
# endif
|
||||
#elif defined __UCLIBC__ /* uClibc */
|
||||
# ifdef __STDIO_BUFFERS
|
||||
if (fp->__modeflags & __FLAG_WRITING)
|
||||
return 0;
|
||||
return fp->__bufread - fp->__bufpos;
|
||||
# else
|
||||
return 0;
|
||||
# endif
|
||||
#elif defined __QNX__ /* QNX */
|
||||
if ((fp->_Mode & 0x2000 /* _MWRITE */) != 0)
|
||||
return 0;
|
||||
/* fp->_Buf <= fp->_Next <= fp->_Rend */
|
||||
return fp->_Rend - fp->_Next;
|
||||
#else
|
||||
#error "Please port gnulib freadahead.c to your platform! Look at the definition of fflush, fread on your system, then report this to bug-gnulib."
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/* Retrieve information about a FILE stream.
|
||||
Copyright (C) 2007 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/>. */
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Assuming the stream STREAM is open for reading:
|
||||
Return the number of bytes waiting in the input buffer of STREAM.
|
||||
|
||||
If this number is 0 and the stream is not currently writing,
|
||||
fflush (STREAM) is known to be a no-op.
|
||||
|
||||
STREAM must not be wide-character oriented. */
|
||||
|
||||
extern size_t freadahead (FILE *stream);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,50 @@
|
||||
/* Retrieve information about a FILE stream.
|
||||
Copyright (C) 2007 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/>. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
/* Specification. */
|
||||
#include "freading.h"
|
||||
|
||||
/* Don't use glibc's __freading function in glibc < 2.7, see
|
||||
<http://sourceware.org/bugzilla/show_bug.cgi?id=4359> */
|
||||
#if !(HAVE___FREADING && (!defined __GLIBC__ || __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 7)))
|
||||
|
||||
bool
|
||||
freading (FILE *fp)
|
||||
{
|
||||
/* Most systems provide FILE as a struct and the necessary bitmask in
|
||||
<stdio.h>, because they need it for implementing getc() and putc() as
|
||||
fast macros. */
|
||||
#if defined _IO_ferror_unlocked /* GNU libc, BeOS */
|
||||
return ((fp->_flags & _IO_NO_WRITES) != 0
|
||||
|| ((fp->_flags & (_IO_NO_READS | _IO_CURRENTLY_PUTTING)) == 0
|
||||
&& fp->_IO_read_base != NULL));
|
||||
#elif defined __sferror /* FreeBSD, NetBSD, OpenBSD, MacOS X, Cygwin */
|
||||
return (fp->_flags & __SRD) != 0;
|
||||
#elif defined _IOERR /* AIX, HP-UX, IRIX, OSF/1, Solaris, mingw */
|
||||
return (fp->_flag & _IOREAD) != 0;
|
||||
#elif defined __UCLIBC__ /* uClibc */
|
||||
return (fp->__modeflags & (__FLAG_READONLY | __FLAG_READING)) != 0;
|
||||
#elif defined __QNX__ /* QNX */
|
||||
return ((fp->_Mode & 0x2 /* _MOPENW */) == 0
|
||||
|| (fp->_Mode & 0x1000 /* _MREAD */) != 0);
|
||||
#else
|
||||
#error "Please port gnulib freading.c to your platform!"
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,53 @@
|
||||
/* Retrieve information about a FILE stream.
|
||||
Copyright (C) 2007 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/>. */
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* Return true if the stream STREAM is opened read-only, or if the
|
||||
last operation on the stream was a read operation. Return false if
|
||||
the stream is opened write-only or append-only, or if it supports
|
||||
writing and there is no current read operation (such as fputc).
|
||||
|
||||
freading and fwriting will never both be true. If STREAM supports
|
||||
both reads and writes, then:
|
||||
- both freading and fwriting might be false when the stream is first
|
||||
opened, after read encounters EOF, or after fflush,
|
||||
- freading might be false or true and fwriting might be false
|
||||
after repositioning (such as fseek, fsetpos, or rewind),
|
||||
depending on the underlying implementation.
|
||||
|
||||
STREAM must not be wide-character oriented. */
|
||||
|
||||
#if HAVE___FREADING && (!defined __GLIBC__ || __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 7))
|
||||
/* Solaris >= 7, not glibc >= 2.2, but glibc >= 2.7 */
|
||||
|
||||
# include <stdio_ext.h>
|
||||
# define freading(stream) (__freading (stream) != 0)
|
||||
|
||||
#else
|
||||
|
||||
# ifdef __cplusplus
|
||||
extern "C" {
|
||||
# endif
|
||||
|
||||
extern bool freading (FILE *stream);
|
||||
|
||||
# ifdef __cplusplus
|
||||
}
|
||||
# endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,120 @@
|
||||
/* An fseeko() function that, together with fflush(), is POSIX compliant.
|
||||
Copyright (C) 2007 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, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
/* Specification. */
|
||||
#include <stdio.h>
|
||||
|
||||
/* Get off_t and lseek. */
|
||||
#include <unistd.h>
|
||||
|
||||
#undef fseeko
|
||||
#if !HAVE_FSEEKO
|
||||
# undef fseek
|
||||
# define fseeko fseek
|
||||
#endif
|
||||
|
||||
int
|
||||
rpl_fseeko (FILE *fp, off_t offset, int whence)
|
||||
{
|
||||
#if LSEEK_PIPE_BROKEN
|
||||
/* mingw gives bogus answers rather than failure on non-seekable files. */
|
||||
if (lseek (fileno (fp), 0, SEEK_CUR) == -1)
|
||||
return EOF;
|
||||
#endif
|
||||
|
||||
/* These tests are based on fpurge.c. */
|
||||
#if defined _IO_ferror_unlocked /* GNU libc, BeOS */
|
||||
if (fp->_IO_read_end == fp->_IO_read_ptr
|
||||
&& fp->_IO_write_ptr == fp->_IO_write_base
|
||||
&& fp->_IO_save_base == NULL)
|
||||
#elif defined __sferror /* FreeBSD, NetBSD, OpenBSD, MacOS X, Cygwin */
|
||||
# if defined __NetBSD__ || defined __OpenBSD__ /* NetBSD, OpenBSD */
|
||||
/* See <http://cvsweb.netbsd.org/bsdweb.cgi/src/lib/libc/stdio/fileext.h?rev=HEAD&content-type=text/x-cvsweb-markup>
|
||||
and <http://www.openbsd.org/cgi-bin/cvsweb/src/lib/libc/stdio/fileext.h?rev=HEAD&content-type=text/x-cvsweb-markup> */
|
||||
# define fp_ub ((struct { struct __sbuf _ub; } *) fp->_ext._base)->_ub
|
||||
# else /* FreeBSD, MacOS X, Cygwin */
|
||||
# define fp_ub fp->_ub
|
||||
# endif
|
||||
# if defined __SL64 && defined __SCLE /* Cygwin */
|
||||
if ((fp->_flags & __SL64) == 0)
|
||||
{
|
||||
/* Cygwin 1.5.0 through 1.5.24 failed to open stdin in 64-bit
|
||||
mode; but has an fseeko that requires 64-bit mode. */
|
||||
FILE *tmp = fopen ("/dev/null", "r");
|
||||
if (!tmp)
|
||||
return -1;
|
||||
fp->_flags |= __SL64;
|
||||
fp->_seek64 = tmp->_seek64;
|
||||
fclose (tmp);
|
||||
}
|
||||
# endif
|
||||
if (fp->_p == fp->_bf._base
|
||||
&& fp->_r == 0
|
||||
&& fp->_w == ((fp->_flags & (__SLBF | __SNBF | __SRD)) == 0 /* fully buffered and not currently reading? */
|
||||
? fp->_bf._size
|
||||
: 0)
|
||||
&& fp_ub._base == NULL)
|
||||
#elif defined _IOERR /* AIX, HP-UX, IRIX, OSF/1, Solaris, mingw */
|
||||
# if defined __sun && defined _LP64 /* Solaris/{SPARC,AMD64} 64-bit */
|
||||
# define fp_ ((struct { unsigned char *_ptr; \
|
||||
unsigned char *_base; \
|
||||
unsigned char *_end; \
|
||||
long _cnt; \
|
||||
int _file; \
|
||||
unsigned int _flag; \
|
||||
} *) fp)
|
||||
if (fp_->_ptr == fp_->_base
|
||||
&& (fp_->_ptr == NULL || fp_->_cnt == 0))
|
||||
# else
|
||||
if (fp->_ptr == fp->_base
|
||||
&& (fp->_ptr == NULL || fp->_cnt == 0))
|
||||
# endif
|
||||
#elif defined __UCLIBC__ /* uClibc */
|
||||
if (((fp->__modeflags & __FLAG_WRITING) == 0
|
||||
|| fp->__bufpos == fp->__bufstart)
|
||||
&& ((fp->__modeflags & (__FLAG_READONLY | __FLAG_READING)) == 0
|
||||
|| fp->__bufpos == fp->__bufread))
|
||||
#elif defined __QNX__ /* QNX */
|
||||
if ((fp->_Mode & _MWRITE ? fp->_Next == fp->_Buf : fp->_Next == fp->_Rend)
|
||||
&& fp->_Rback == fp->_Back + sizeof (fp->_Back)
|
||||
&& fp->_Rsave == NULL)
|
||||
#else
|
||||
#error "Please port gnulib fseeko.c to your platform! Look at the code in fpurge.c, then report this to bug-gnulib."
|
||||
#endif
|
||||
{
|
||||
off_t pos = lseek (fileno (fp), offset, whence);
|
||||
if (pos == -1)
|
||||
{
|
||||
#if defined __sferror /* FreeBSD, NetBSD, OpenBSD, MacOS X, Cygwin */
|
||||
fp->_flags &= ~__SOFF;
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined __sferror /* FreeBSD, NetBSD, OpenBSD, MacOS X, Cygwin */
|
||||
fp->_offset = pos;
|
||||
fp->_flags |= __SOFF;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
return fseeko (fp, offset, whence);
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/* Work around an fstatat bug on Solaris 9.
|
||||
|
||||
Copyright (C) 2006 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/>. */
|
||||
|
||||
/* Written by Paul Eggert and Jim Meyering. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#define COMPILING_FSTATAT 1
|
||||
#include "openat.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
/* fstatat should always follow symbolic links that end in /, but on
|
||||
Solaris 9 it doesn't if AT_SYMLINK_NOFOLLOW is specified. This is
|
||||
the same problem that lstat.c addresses, so solve it in a similar
|
||||
way. */
|
||||
|
||||
int
|
||||
rpl_fstatat (int fd, char const *file, struct stat *st, int flag)
|
||||
{
|
||||
int result = fstatat (fd, file, st, flag);
|
||||
|
||||
if (result == 0 && (flag & AT_SYMLINK_NOFOLLOW) && S_ISLNK (st->st_mode)
|
||||
&& file[strlen (file) - 1] == '/')
|
||||
{
|
||||
/* FILE refers to a symbolic link and the name ends with a slash.
|
||||
Get info about the link's referent. */
|
||||
result = fstatat (fd, file, st, flag & ~AT_SYMLINK_NOFOLLOW);
|
||||
if (result == 0 && ! S_ISDIR (st->st_mode))
|
||||
{
|
||||
/* fstatat succeeded and FILE references a non-directory.
|
||||
But it was specified via a name including a trailing
|
||||
slash. Fail with errno set to ENOTDIR to indicate the
|
||||
contradiction. */
|
||||
errno = ENOTDIR;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/* An ftello() function that works around platform bugs.
|
||||
Copyright (C) 2007 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/>. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
/* Specification. */
|
||||
#include <stdio.h>
|
||||
|
||||
/* Get lseek. */
|
||||
#include <unistd.h>
|
||||
|
||||
#undef ftello
|
||||
#if !HAVE_FTELLO
|
||||
# undef ftell
|
||||
# define ftello ftell
|
||||
#endif
|
||||
|
||||
off_t
|
||||
rpl_ftello (FILE *fp)
|
||||
{
|
||||
#if LSEEK_PIPE_BROKEN
|
||||
/* mingw gives bogus answers rather than failure on non-seekable files. */
|
||||
if (lseek (fileno (fp), 0, SEEK_CUR) == -1)
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
#if defined __SL64 && defined __SCLE /* Cygwin */
|
||||
if ((fp->_flags & __SL64) == 0)
|
||||
{
|
||||
/* Cygwin 1.5.0 through 1.5.24 failed to open stdin in 64-bit
|
||||
mode; but has an ftello that requires 64-bit mode. */
|
||||
FILE *tmp = fopen ("/dev/null", "r");
|
||||
if (!tmp)
|
||||
return -1;
|
||||
fp->_flags |= __SL64;
|
||||
fp->_seek64 = tmp->_seek64;
|
||||
fclose (tmp);
|
||||
}
|
||||
#endif
|
||||
return ftello (fp);
|
||||
}
|
||||
@@ -0,0 +1,427 @@
|
||||
/* Copyright (C) 1991,92,93,94,95,96,97,98,99,2004,2005,2006,2007 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 <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#if !_LIBC
|
||||
# include <config.h>
|
||||
# include <unistd.h>
|
||||
# include "dirfd.h"
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include <fcntl.h> /* For AT_FDCWD on Solaris 9. */
|
||||
|
||||
#ifndef __set_errno
|
||||
# define __set_errno(val) (errno = (val))
|
||||
#endif
|
||||
|
||||
#include <dirent.h>
|
||||
#ifndef _D_EXACT_NAMLEN
|
||||
# define _D_EXACT_NAMLEN(d) strlen ((d)->d_name)
|
||||
#endif
|
||||
#ifndef _D_ALLOC_NAMLEN
|
||||
# define _D_ALLOC_NAMLEN(d) (_D_EXACT_NAMLEN (d) + 1)
|
||||
#endif
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#if _LIBC
|
||||
# ifndef mempcpy
|
||||
# define mempcpy __mempcpy
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
/* 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 0 < AT_FDCWD && AT_FDCWD == 0xffd19553
|
||||
# undef AT_FDCWD
|
||||
# define AT_FDCWD (-3041965)
|
||||
#endif
|
||||
|
||||
#ifdef ENAMETOOLONG
|
||||
# define is_ENAMETOOLONG(x) ((x) == ENAMETOOLONG)
|
||||
#else
|
||||
# define is_ENAMETOOLONG(x) 0
|
||||
#endif
|
||||
|
||||
#ifndef MAX
|
||||
# define MAX(a, b) ((a) < (b) ? (b) : (a))
|
||||
#endif
|
||||
#ifndef MIN
|
||||
# define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
#ifndef PATH_MAX
|
||||
# ifdef MAXPATHLEN
|
||||
# define PATH_MAX MAXPATHLEN
|
||||
# else
|
||||
# define PATH_MAX 1024
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if D_INO_IN_DIRENT
|
||||
# define MATCHING_INO(dp, ino) ((dp)->d_ino == (ino))
|
||||
#else
|
||||
# define MATCHING_INO(dp, ino) true
|
||||
#endif
|
||||
|
||||
#if !_LIBC
|
||||
# define __getcwd rpl_getcwd
|
||||
# define __lstat lstat
|
||||
# define __closedir closedir
|
||||
# define __opendir opendir
|
||||
# define __readdir readdir
|
||||
#endif
|
||||
|
||||
/* The results of opendir() in this file are not used with dirfd and fchdir,
|
||||
therefore save some unnecessary recursion in fchdir.c. */
|
||||
#undef opendir
|
||||
#undef closedir
|
||||
|
||||
/* Get the name of the current working directory, and put it in SIZE
|
||||
bytes of BUF. Returns NULL if the directory couldn't be determined or
|
||||
SIZE was too small. If successful, returns BUF. In GNU, if BUF is
|
||||
NULL, an array is allocated with `malloc'; the array is SIZE bytes long,
|
||||
unless SIZE == 0, in which case it is as big as necessary. */
|
||||
|
||||
char *
|
||||
__getcwd (char *buf, size_t size)
|
||||
{
|
||||
/* Lengths of big file name components and entire file names, and a
|
||||
deep level of file name nesting. These numbers are not upper
|
||||
bounds; they are merely large values suitable for initial
|
||||
allocations, designed to be large enough for most real-world
|
||||
uses. */
|
||||
enum
|
||||
{
|
||||
BIG_FILE_NAME_COMPONENT_LENGTH = 255,
|
||||
BIG_FILE_NAME_LENGTH = MIN (4095, PATH_MAX - 1),
|
||||
DEEP_NESTING = 100
|
||||
};
|
||||
|
||||
#ifdef AT_FDCWD
|
||||
int fd = AT_FDCWD;
|
||||
bool fd_needs_closing = false;
|
||||
#else
|
||||
char dots[DEEP_NESTING * sizeof ".." + BIG_FILE_NAME_COMPONENT_LENGTH + 1];
|
||||
char *dotlist = dots;
|
||||
size_t dotsize = sizeof dots;
|
||||
size_t dotlen = 0;
|
||||
#endif
|
||||
DIR *dirstream = NULL;
|
||||
dev_t rootdev, thisdev;
|
||||
ino_t rootino, thisino;
|
||||
char *dir;
|
||||
register char *dirp;
|
||||
struct stat st;
|
||||
size_t allocated = size;
|
||||
size_t used;
|
||||
|
||||
#if HAVE_PARTLY_WORKING_GETCWD
|
||||
/* The system getcwd works, except it sometimes fails when it
|
||||
shouldn't, setting errno to ERANGE, ENAMETOOLONG, or ENOENT. If
|
||||
AT_FDCWD is not defined, the algorithm below is O(N**2) and this
|
||||
is much slower than the system getcwd (at least on GNU/Linux).
|
||||
So trust the system getcwd's results unless they look
|
||||
suspicious.
|
||||
|
||||
Use the system getcwd even if we have openat support, since the
|
||||
system getcwd works even when a parent is unreadable, while the
|
||||
openat-based approach does not. */
|
||||
|
||||
# undef getcwd
|
||||
dir = getcwd (buf, size);
|
||||
if (dir || (errno != ERANGE && !is_ENAMETOOLONG (errno) && errno != ENOENT))
|
||||
return dir;
|
||||
#endif
|
||||
|
||||
if (size == 0)
|
||||
{
|
||||
if (buf != NULL)
|
||||
{
|
||||
__set_errno (EINVAL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
allocated = BIG_FILE_NAME_LENGTH + 1;
|
||||
}
|
||||
|
||||
if (buf == NULL)
|
||||
{
|
||||
dir = malloc (allocated);
|
||||
if (dir == NULL)
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
dir = buf;
|
||||
|
||||
dirp = dir + allocated;
|
||||
*--dirp = '\0';
|
||||
|
||||
if (__lstat (".", &st) < 0)
|
||||
goto lose;
|
||||
thisdev = st.st_dev;
|
||||
thisino = st.st_ino;
|
||||
|
||||
if (__lstat ("/", &st) < 0)
|
||||
goto lose;
|
||||
rootdev = st.st_dev;
|
||||
rootino = st.st_ino;
|
||||
|
||||
while (!(thisdev == rootdev && thisino == rootino))
|
||||
{
|
||||
struct dirent *d;
|
||||
dev_t dotdev;
|
||||
ino_t dotino;
|
||||
bool mount_point;
|
||||
int parent_status;
|
||||
size_t dirroom;
|
||||
size_t namlen;
|
||||
bool use_d_ino = true;
|
||||
|
||||
/* Look at the parent directory. */
|
||||
#ifdef AT_FDCWD
|
||||
fd = openat (fd, "..", O_RDONLY);
|
||||
if (fd < 0)
|
||||
goto lose;
|
||||
fd_needs_closing = true;
|
||||
parent_status = fstat (fd, &st);
|
||||
#else
|
||||
dotlist[dotlen++] = '.';
|
||||
dotlist[dotlen++] = '.';
|
||||
dotlist[dotlen] = '\0';
|
||||
parent_status = __lstat (dotlist, &st);
|
||||
#endif
|
||||
if (parent_status != 0)
|
||||
goto lose;
|
||||
|
||||
if (dirstream && __closedir (dirstream) != 0)
|
||||
{
|
||||
dirstream = NULL;
|
||||
goto lose;
|
||||
}
|
||||
|
||||
/* Figure out if this directory is a mount point. */
|
||||
dotdev = st.st_dev;
|
||||
dotino = st.st_ino;
|
||||
mount_point = dotdev != thisdev;
|
||||
|
||||
/* Search for the last directory. */
|
||||
#ifdef AT_FDCWD
|
||||
dirstream = fdopendir (fd);
|
||||
if (dirstream == NULL)
|
||||
goto lose;
|
||||
/* Reset fd. It may have been closed by fdopendir. */
|
||||
fd = dirfd (dirstream);
|
||||
fd_needs_closing = false;
|
||||
#else
|
||||
dirstream = __opendir (dotlist);
|
||||
if (dirstream == NULL)
|
||||
goto lose;
|
||||
dotlist[dotlen++] = '/';
|
||||
#endif
|
||||
for (;;)
|
||||
{
|
||||
/* Clear errno to distinguish EOF from error if readdir returns
|
||||
NULL. */
|
||||
__set_errno (0);
|
||||
d = __readdir (dirstream);
|
||||
|
||||
/* When we've iterated through all directory entries without finding
|
||||
one with a matching d_ino, rewind the stream and consider each
|
||||
name again, but this time, using lstat. This is necessary in a
|
||||
chroot on at least one system (glibc-2.3.6 + linux 2.6.12), where
|
||||
.., ../.., ../../.., etc. all had the same device number, yet the
|
||||
d_ino values for entries in / did not match those obtained
|
||||
via lstat. */
|
||||
if (d == NULL && errno == 0 && use_d_ino)
|
||||
{
|
||||
use_d_ino = false;
|
||||
rewinddir (dirstream);
|
||||
d = __readdir (dirstream);
|
||||
}
|
||||
|
||||
if (d == NULL)
|
||||
{
|
||||
if (errno == 0)
|
||||
/* EOF on dirstream, which can mean e.g., that the current
|
||||
directory has been removed. */
|
||||
__set_errno (ENOENT);
|
||||
goto lose;
|
||||
}
|
||||
if (d->d_name[0] == '.' &&
|
||||
(d->d_name[1] == '\0' ||
|
||||
(d->d_name[1] == '.' && d->d_name[2] == '\0')))
|
||||
continue;
|
||||
|
||||
if (use_d_ino)
|
||||
{
|
||||
bool match = (MATCHING_INO (d, thisino) || mount_point);
|
||||
if (! match)
|
||||
continue;
|
||||
}
|
||||
|
||||
{
|
||||
int entry_status;
|
||||
#ifdef AT_FDCWD
|
||||
entry_status = fstatat (fd, d->d_name, &st, AT_SYMLINK_NOFOLLOW);
|
||||
#else
|
||||
/* Compute size needed for this file name, or for the file
|
||||
name ".." in the same directory, whichever is larger.
|
||||
Room for ".." might be needed the next time through
|
||||
the outer loop. */
|
||||
size_t name_alloc = _D_ALLOC_NAMLEN (d);
|
||||
size_t filesize = dotlen + MAX (sizeof "..", name_alloc);
|
||||
|
||||
if (filesize < dotlen)
|
||||
goto memory_exhausted;
|
||||
|
||||
if (dotsize < filesize)
|
||||
{
|
||||
/* My, what a deep directory tree you have, Grandma. */
|
||||
size_t newsize = MAX (filesize, dotsize * 2);
|
||||
size_t i;
|
||||
if (newsize < dotsize)
|
||||
goto memory_exhausted;
|
||||
if (dotlist != dots)
|
||||
free (dotlist);
|
||||
dotlist = malloc (newsize);
|
||||
if (dotlist == NULL)
|
||||
goto lose;
|
||||
dotsize = newsize;
|
||||
|
||||
i = 0;
|
||||
do
|
||||
{
|
||||
dotlist[i++] = '.';
|
||||
dotlist[i++] = '.';
|
||||
dotlist[i++] = '/';
|
||||
}
|
||||
while (i < dotlen);
|
||||
}
|
||||
|
||||
memcpy (dotlist + dotlen, d->d_name, _D_ALLOC_NAMLEN (d));
|
||||
entry_status = __lstat (dotlist, &st);
|
||||
#endif
|
||||
/* We don't fail here if we cannot stat() a directory entry.
|
||||
This can happen when (network) file systems fail. If this
|
||||
entry is in fact the one we are looking for we will find
|
||||
out soon as we reach the end of the directory without
|
||||
having found anything. */
|
||||
if (entry_status == 0 && S_ISDIR (st.st_mode)
|
||||
&& st.st_dev == thisdev && st.st_ino == thisino)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
dirroom = dirp - dir;
|
||||
namlen = _D_EXACT_NAMLEN (d);
|
||||
|
||||
if (dirroom <= namlen)
|
||||
{
|
||||
if (size != 0)
|
||||
{
|
||||
__set_errno (ERANGE);
|
||||
goto lose;
|
||||
}
|
||||
else
|
||||
{
|
||||
char *tmp;
|
||||
size_t oldsize = allocated;
|
||||
|
||||
allocated += MAX (allocated, namlen);
|
||||
if (allocated < oldsize
|
||||
|| ! (tmp = realloc (dir, allocated)))
|
||||
goto memory_exhausted;
|
||||
|
||||
/* Move current contents up to the end of the buffer.
|
||||
This is guaranteed to be non-overlapping. */
|
||||
dirp = memcpy (tmp + allocated - (oldsize - dirroom),
|
||||
tmp + dirroom,
|
||||
oldsize - dirroom);
|
||||
dir = tmp;
|
||||
}
|
||||
}
|
||||
dirp -= namlen;
|
||||
memcpy (dirp, d->d_name, namlen);
|
||||
*--dirp = '/';
|
||||
|
||||
thisdev = dotdev;
|
||||
thisino = dotino;
|
||||
}
|
||||
|
||||
if (dirstream && __closedir (dirstream) != 0)
|
||||
{
|
||||
dirstream = NULL;
|
||||
goto lose;
|
||||
}
|
||||
|
||||
if (dirp == &dir[allocated - 1])
|
||||
*--dirp = '/';
|
||||
|
||||
#ifndef AT_FDCWD
|
||||
if (dotlist != dots)
|
||||
free (dotlist);
|
||||
#endif
|
||||
|
||||
used = dir + allocated - dirp;
|
||||
memmove (dir, dirp, used);
|
||||
|
||||
if (size == 0)
|
||||
/* Ensure that the buffer is only as large as necessary. */
|
||||
buf = realloc (dir, used);
|
||||
|
||||
if (buf == NULL)
|
||||
/* Either buf was NULL all along, or `realloc' failed but
|
||||
we still have the original string. */
|
||||
buf = dir;
|
||||
|
||||
return buf;
|
||||
|
||||
memory_exhausted:
|
||||
__set_errno (ENOMEM);
|
||||
lose:
|
||||
{
|
||||
int save = errno;
|
||||
if (dirstream)
|
||||
__closedir (dirstream);
|
||||
#ifdef AT_FDCWD
|
||||
if (fd_needs_closing)
|
||||
close (fd);
|
||||
#else
|
||||
if (dotlist != dots)
|
||||
free (dotlist);
|
||||
#endif
|
||||
if (buf == NULL)
|
||||
free (dir);
|
||||
__set_errno (save);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef weak_alias
|
||||
weak_alias (__getcwd, getcwd)
|
||||
#endif
|
||||
@@ -0,0 +1,133 @@
|
||||
/* getdelim.c --- Implementation of replacement getdelim function.
|
||||
Copyright (C) 1994, 1996, 1997, 1998, 2001, 2003, 2005, 2006, 2007 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, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
/* Ported from glibc by Simon Josefsson. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifndef SIZE_MAX
|
||||
# define SIZE_MAX ((size_t) -1)
|
||||
#endif
|
||||
#ifndef SSIZE_MAX
|
||||
# define SSIZE_MAX ((ssize_t) (SIZE_MAX / 2))
|
||||
#endif
|
||||
#if !HAVE_FLOCKFILE
|
||||
# undef flockfile
|
||||
# define flockfile(x) ((void) 0)
|
||||
#endif
|
||||
#if !HAVE_FUNLOCKFILE
|
||||
# undef funlockfile
|
||||
# define funlockfile(x) ((void) 0)
|
||||
#endif
|
||||
|
||||
/* Some systems, like OSF/1 4.0 and Woe32, don't have EOVERFLOW. */
|
||||
#ifndef EOVERFLOW
|
||||
# define EOVERFLOW E2BIG
|
||||
#endif
|
||||
|
||||
/* Read up to (and including) a DELIMITER from FP into *LINEPTR (and
|
||||
NUL-terminate it). *LINEPTR is a pointer returned from malloc (or
|
||||
NULL), pointing to *N characters of space. It is realloc'ed as
|
||||
necessary. Returns the number of characters read (not including
|
||||
the null terminator), or -1 on error or EOF. */
|
||||
|
||||
ssize_t
|
||||
getdelim (char **lineptr, size_t *n, int delimiter, FILE *fp)
|
||||
{
|
||||
ssize_t result;
|
||||
size_t cur_len = 0;
|
||||
|
||||
if (lineptr == NULL || n == NULL || fp == NULL)
|
||||
{
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
flockfile (fp);
|
||||
|
||||
if (*lineptr == NULL || *n == 0)
|
||||
{
|
||||
*n = 120;
|
||||
*lineptr = (char *) realloc (*lineptr, *n);
|
||||
if (*lineptr == NULL)
|
||||
{
|
||||
result = -1;
|
||||
goto unlock_return;
|
||||
}
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
int i;
|
||||
|
||||
i = getc (fp);
|
||||
if (i == EOF)
|
||||
{
|
||||
result = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Make enough space for len+1 (for final NUL) bytes. */
|
||||
if (cur_len + 1 >= *n)
|
||||
{
|
||||
size_t needed_max =
|
||||
SSIZE_MAX < SIZE_MAX ? (size_t) SSIZE_MAX + 1 : SIZE_MAX;
|
||||
size_t needed = 2 * *n + 1; /* Be generous. */
|
||||
char *new_lineptr;
|
||||
|
||||
if (needed_max < needed)
|
||||
needed = needed_max;
|
||||
if (cur_len + 1 >= needed)
|
||||
{
|
||||
result = -1;
|
||||
errno = EOVERFLOW;
|
||||
goto unlock_return;
|
||||
}
|
||||
|
||||
new_lineptr = (char *) realloc (*lineptr, needed);
|
||||
if (new_lineptr == NULL)
|
||||
{
|
||||
result = -1;
|
||||
goto unlock_return;
|
||||
}
|
||||
|
||||
*lineptr = new_lineptr;
|
||||
*n = needed;
|
||||
}
|
||||
|
||||
(*lineptr)[cur_len] = i;
|
||||
cur_len++;
|
||||
|
||||
if (i == delimiter)
|
||||
break;
|
||||
}
|
||||
(*lineptr)[cur_len] = '\0';
|
||||
result = cur_len ? cur_len : result;
|
||||
|
||||
unlock_return:
|
||||
funlockfile (fp); /* doesn't set errno */
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/* getline.c --- Implementation of replacement getline function.
|
||||
Copyright (C) 2005, 2006, 2007 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, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
/* Written by Simon Josefsson. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
ssize_t
|
||||
getline (char **lineptr, size_t *n, FILE *stream)
|
||||
{
|
||||
return getdelim (lineptr, n, '\n', stream);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,225 @@
|
||||
/* Declarations for getopt.
|
||||
Copyright (C) 1989-1994,1996-1999,2001,2003,2004,2005,2006,2007
|
||||
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 <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _GETOPT_H
|
||||
|
||||
#ifndef __need_getopt
|
||||
# define _GETOPT_H 1
|
||||
#endif
|
||||
|
||||
/* Standalone applications should #define __GETOPT_PREFIX to an
|
||||
identifier that prefixes the external functions and variables
|
||||
defined in this header. When this happens, include the
|
||||
headers that might declare getopt so that they will not cause
|
||||
confusion if included after this file. Then systematically rename
|
||||
identifiers so that they do not collide with the system functions
|
||||
and variables. Renaming avoids problems with some compilers and
|
||||
linkers. */
|
||||
#if defined __GETOPT_PREFIX && !defined __need_getopt
|
||||
# include <stdlib.h>
|
||||
# include <stdio.h>
|
||||
# include <unistd.h>
|
||||
# undef __need_getopt
|
||||
# undef getopt
|
||||
# undef getopt_long
|
||||
# undef getopt_long_only
|
||||
# undef optarg
|
||||
# undef opterr
|
||||
# undef optind
|
||||
# undef optopt
|
||||
# define __GETOPT_CONCAT(x, y) x ## y
|
||||
# define __GETOPT_XCONCAT(x, y) __GETOPT_CONCAT (x, y)
|
||||
# define __GETOPT_ID(y) __GETOPT_XCONCAT (__GETOPT_PREFIX, y)
|
||||
# define getopt __GETOPT_ID (getopt)
|
||||
# define getopt_long __GETOPT_ID (getopt_long)
|
||||
# define getopt_long_only __GETOPT_ID (getopt_long_only)
|
||||
# define optarg __GETOPT_ID (optarg)
|
||||
# define opterr __GETOPT_ID (opterr)
|
||||
# define optind __GETOPT_ID (optind)
|
||||
# define optopt __GETOPT_ID (optopt)
|
||||
#endif
|
||||
|
||||
/* Standalone applications get correct prototypes for getopt_long and
|
||||
getopt_long_only; they declare "char **argv". libc uses prototypes
|
||||
with "char *const *argv" that are incorrect because getopt_long and
|
||||
getopt_long_only can permute argv; this is required for backward
|
||||
compatibility (e.g., for LSB 2.0.1).
|
||||
|
||||
This used to be `#if defined __GETOPT_PREFIX && !defined __need_getopt',
|
||||
but it caused redefinition warnings if both unistd.h and getopt.h were
|
||||
included, since unistd.h includes getopt.h having previously defined
|
||||
__need_getopt.
|
||||
|
||||
The only place where __getopt_argv_const is used is in definitions
|
||||
of getopt_long and getopt_long_only below, but these are visible
|
||||
only if __need_getopt is not defined, so it is quite safe to rewrite
|
||||
the conditional as follows:
|
||||
*/
|
||||
#if !defined __need_getopt
|
||||
# if defined __GETOPT_PREFIX
|
||||
# define __getopt_argv_const /* empty */
|
||||
# else
|
||||
# define __getopt_argv_const const
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* If __GNU_LIBRARY__ is not already defined, either we are being used
|
||||
standalone, or this is the first header included in the source file.
|
||||
If we are being used with glibc, we need to include <features.h>, but
|
||||
that does not exist if we are standalone. So: if __GNU_LIBRARY__ is
|
||||
not defined, include <ctype.h>, which will pull in <features.h> for us
|
||||
if it's from glibc. (Why ctype.h? It's guaranteed to exist and it
|
||||
doesn't flood the namespace with stuff the way some other headers do.) */
|
||||
#if !defined __GNU_LIBRARY__
|
||||
# include <ctype.h>
|
||||
#endif
|
||||
|
||||
#ifndef __THROW
|
||||
# ifndef __GNUC_PREREQ
|
||||
# define __GNUC_PREREQ(maj, min) (0)
|
||||
# endif
|
||||
# if defined __cplusplus && __GNUC_PREREQ (2,8)
|
||||
# define __THROW throw ()
|
||||
# else
|
||||
# define __THROW
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* For communication from `getopt' to the caller.
|
||||
When `getopt' finds an option that takes an argument,
|
||||
the argument value is returned here.
|
||||
Also, when `ordering' is RETURN_IN_ORDER,
|
||||
each non-option ARGV-element is returned here. */
|
||||
|
||||
extern char *optarg;
|
||||
|
||||
/* Index in ARGV of the next element to be scanned.
|
||||
This is used for communication to and from the caller
|
||||
and for communication between successive calls to `getopt'.
|
||||
|
||||
On entry to `getopt', zero means this is the first call; initialize.
|
||||
|
||||
When `getopt' returns -1, this is the index of the first of the
|
||||
non-option elements that the caller should itself scan.
|
||||
|
||||
Otherwise, `optind' communicates from one call to the next
|
||||
how much of ARGV has been scanned so far. */
|
||||
|
||||
extern int optind;
|
||||
|
||||
/* Callers store zero here to inhibit the error message `getopt' prints
|
||||
for unrecognized options. */
|
||||
|
||||
extern int opterr;
|
||||
|
||||
/* Set to an option character which was unrecognized. */
|
||||
|
||||
extern int optopt;
|
||||
|
||||
#ifndef __need_getopt
|
||||
/* Describe the long-named options requested by the application.
|
||||
The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
|
||||
of `struct option' terminated by an element containing a name which is
|
||||
zero.
|
||||
|
||||
The field `has_arg' is:
|
||||
no_argument (or 0) if the option does not take an argument,
|
||||
required_argument (or 1) if the option requires an argument,
|
||||
optional_argument (or 2) if the option takes an optional argument.
|
||||
|
||||
If the field `flag' is not NULL, it points to a variable that is set
|
||||
to the value given in the field `val' when the option is found, but
|
||||
left unchanged if the option is not found.
|
||||
|
||||
To have a long-named option do something other than set an `int' to
|
||||
a compiled-in constant, such as set a value from `optarg', set the
|
||||
option's `flag' field to zero and its `val' field to a nonzero
|
||||
value (the equivalent single-letter option character, if there is
|
||||
one). For long options that have a zero `flag' field, `getopt'
|
||||
returns the contents of the `val' field. */
|
||||
|
||||
struct option
|
||||
{
|
||||
const char *name;
|
||||
/* has_arg can't be an enum because some compilers complain about
|
||||
type mismatches in all the code that assumes it is an int. */
|
||||
int has_arg;
|
||||
int *flag;
|
||||
int val;
|
||||
};
|
||||
|
||||
/* Names for the values of the `has_arg' field of `struct option'. */
|
||||
|
||||
# define no_argument 0
|
||||
# define required_argument 1
|
||||
# define optional_argument 2
|
||||
#endif /* need getopt */
|
||||
|
||||
|
||||
/* Get definitions and prototypes for functions to process the
|
||||
arguments in ARGV (ARGC of them, minus the program name) for
|
||||
options given in OPTS.
|
||||
|
||||
Return the option character from OPTS just read. Return -1 when
|
||||
there are no more options. For unrecognized options, or options
|
||||
missing arguments, `optopt' is set to the option letter, and '?' is
|
||||
returned.
|
||||
|
||||
The OPTS string is a list of characters which are recognized option
|
||||
letters, optionally followed by colons, specifying that that letter
|
||||
takes an argument, to be placed in `optarg'.
|
||||
|
||||
If a letter in OPTS is followed by two colons, its argument is
|
||||
optional. This behavior is specific to the GNU `getopt'.
|
||||
|
||||
The argument `--' causes premature termination of argument
|
||||
scanning, explicitly telling `getopt' that there are no more
|
||||
options.
|
||||
|
||||
If OPTS begins with `-', then non-option arguments are treated as
|
||||
arguments to the option '\1'. This behavior is specific to the GNU
|
||||
`getopt'. If OPTS begins with `+', or POSIXLY_CORRECT is set in
|
||||
the environment, then do not permute arguments. */
|
||||
|
||||
extern int getopt (int ___argc, char *const *___argv, const char *__shortopts)
|
||||
__THROW;
|
||||
|
||||
#ifndef __need_getopt
|
||||
extern int getopt_long (int ___argc, char *__getopt_argv_const *___argv,
|
||||
const char *__shortopts,
|
||||
const struct option *__longopts, int *__longind)
|
||||
__THROW;
|
||||
extern int getopt_long_only (int ___argc, char *__getopt_argv_const *___argv,
|
||||
const char *__shortopts,
|
||||
const struct option *__longopts, int *__longind)
|
||||
__THROW;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Make sure we later can get all the definitions and declarations. */
|
||||
#undef __need_getopt
|
||||
|
||||
#endif /* getopt.h */
|
||||
@@ -1,11 +1,12 @@
|
||||
/* getopt_long and getopt_long_only entry points for GNU getopt.
|
||||
Copyright (C) 1987, 88, 89, 90, 91, 92, 1993, 1994
|
||||
Free Software Foundation, Inc.
|
||||
Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98,2004,2006
|
||||
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 2, or (at your option) any
|
||||
later version.
|
||||
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
|
||||
@@ -13,42 +14,22 @@
|
||||
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, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include "getopt.h"
|
||||
|
||||
#if !defined (__STDC__) || !__STDC__
|
||||
/* This is a separate conditional since some stdc systems
|
||||
reject `defined (const)'. */
|
||||
#ifndef const
|
||||
#define const
|
||||
#endif
|
||||
#ifdef _LIBC
|
||||
# include <getopt.h>
|
||||
#else
|
||||
# include <config.h>
|
||||
# include "getopt.h"
|
||||
#endif
|
||||
#include "getopt_int.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/* Comment out all this code if we are using the GNU C Library, and are not
|
||||
actually compiling the library itself. This code is part of the GNU C
|
||||
Library, but also included in many other GNU distributions. Compiling
|
||||
and linking in this code is a waste when using the GNU C library
|
||||
(especially if it is a shared library). Rather than having every GNU
|
||||
program understand `configure --with-gnu-libc' and omit the object files,
|
||||
it is simpler to just do this in the source for each such file. */
|
||||
|
||||
#if defined (_LIBC) || !defined (__GNU_LIBRARY__)
|
||||
|
||||
|
||||
/* This needs to come after some library #include
|
||||
to get __GNU_LIBRARY__ defined. */
|
||||
#ifdef __GNU_LIBRARY__
|
||||
#include <stdlib.h>
|
||||
#else
|
||||
char *getenv ();
|
||||
#endif
|
||||
|
||||
#ifndef NULL
|
||||
@@ -56,14 +37,20 @@ char *getenv ();
|
||||
#endif
|
||||
|
||||
int
|
||||
getopt_long (argc, argv, options, long_options, opt_index)
|
||||
int argc;
|
||||
char *const *argv;
|
||||
const char *options;
|
||||
const struct option *long_options;
|
||||
int *opt_index;
|
||||
getopt_long (int argc, char *__getopt_argv_const *argv, const char *options,
|
||||
const struct option *long_options, int *opt_index)
|
||||
{
|
||||
return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
|
||||
return _getopt_internal (argc, (char **) argv, options, long_options,
|
||||
opt_index, 0, 0);
|
||||
}
|
||||
|
||||
int
|
||||
_getopt_long_r (int argc, char **argv, const char *options,
|
||||
const struct option *long_options, int *opt_index,
|
||||
struct _getopt_data *d)
|
||||
{
|
||||
return _getopt_internal_r (argc, argv, options, long_options, opt_index,
|
||||
0, 0, d);
|
||||
}
|
||||
|
||||
/* Like getopt_long, but '-' as well as '--' can indicate a long option.
|
||||
@@ -72,27 +59,30 @@ getopt_long (argc, argv, options, long_options, opt_index)
|
||||
instead. */
|
||||
|
||||
int
|
||||
getopt_long_only (argc, argv, options, long_options, opt_index)
|
||||
int argc;
|
||||
char *const *argv;
|
||||
const char *options;
|
||||
const struct option *long_options;
|
||||
int *opt_index;
|
||||
getopt_long_only (int argc, char *__getopt_argv_const *argv,
|
||||
const char *options,
|
||||
const struct option *long_options, int *opt_index)
|
||||
{
|
||||
return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
|
||||
return _getopt_internal (argc, (char **) argv, options, long_options,
|
||||
opt_index, 1, 0);
|
||||
}
|
||||
|
||||
int
|
||||
_getopt_long_only_r (int argc, char **argv, const char *options,
|
||||
const struct option *long_options, int *opt_index,
|
||||
struct _getopt_data *d)
|
||||
{
|
||||
return _getopt_internal_r (argc, argv, options, long_options, opt_index,
|
||||
1, 0, d);
|
||||
}
|
||||
|
||||
#endif /* _LIBC or not __GNU_LIBRARY__. */
|
||||
|
||||
#ifdef TEST
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
int
|
||||
main (argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
int c;
|
||||
int digit_optind = 0;
|
||||
@@ -114,7 +104,7 @@ main (argc, argv)
|
||||
|
||||
c = getopt_long (argc, argv, "abc:d:0123456789",
|
||||
long_options, &option_index);
|
||||
if (c == EOF)
|
||||
if (c == -1)
|
||||
break;
|
||||
|
||||
switch (c)
|
||||
@@ -0,0 +1,130 @@
|
||||
/* Internal declarations for getopt.
|
||||
Copyright (C) 1989-1994,1996-1999,2001,2003,2004
|
||||
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 <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _GETOPT_INT_H
|
||||
#define _GETOPT_INT_H 1
|
||||
|
||||
extern int _getopt_internal (int ___argc, char **___argv,
|
||||
const char *__shortopts,
|
||||
const struct option *__longopts, int *__longind,
|
||||
int __long_only, int __posixly_correct);
|
||||
|
||||
|
||||
/* Reentrant versions which can handle parsing multiple argument
|
||||
vectors at the same time. */
|
||||
|
||||
/* Data type for reentrant functions. */
|
||||
struct _getopt_data
|
||||
{
|
||||
/* These have exactly the same meaning as the corresponding global
|
||||
variables, except that they are used for the reentrant
|
||||
versions of getopt. */
|
||||
int optind;
|
||||
int opterr;
|
||||
int optopt;
|
||||
char *optarg;
|
||||
|
||||
/* Internal members. */
|
||||
|
||||
/* True if the internal members have been initialized. */
|
||||
int __initialized;
|
||||
|
||||
/* The next char to be scanned in the option-element
|
||||
in which the last option character we returned was found.
|
||||
This allows us to pick up the scan where we left off.
|
||||
|
||||
If this is zero, or a null string, it means resume the scan
|
||||
by advancing to the next ARGV-element. */
|
||||
char *__nextchar;
|
||||
|
||||
/* Describe how to deal with options that follow non-option ARGV-elements.
|
||||
|
||||
If the caller did not specify anything,
|
||||
the default is REQUIRE_ORDER if the environment variable
|
||||
POSIXLY_CORRECT is defined, PERMUTE otherwise.
|
||||
|
||||
REQUIRE_ORDER means don't recognize them as options;
|
||||
stop option processing when the first non-option is seen.
|
||||
This is what Unix does.
|
||||
This mode of operation is selected by either setting the environment
|
||||
variable POSIXLY_CORRECT, or using `+' as the first character
|
||||
of the list of option characters, or by calling getopt.
|
||||
|
||||
PERMUTE is the default. We permute the contents of ARGV as we
|
||||
scan, so that eventually all the non-options are at the end.
|
||||
This allows options to be given in any order, even with programs
|
||||
that were not written to expect this.
|
||||
|
||||
RETURN_IN_ORDER is an option available to programs that were
|
||||
written to expect options and other ARGV-elements in any order
|
||||
and that care about the ordering of the two. We describe each
|
||||
non-option ARGV-element as if it were the argument of an option
|
||||
with character code 1. Using `-' as the first character of the
|
||||
list of option characters selects this mode of operation.
|
||||
|
||||
The special argument `--' forces an end of option-scanning regardless
|
||||
of the value of `ordering'. In the case of RETURN_IN_ORDER, only
|
||||
`--' can cause `getopt' to return -1 with `optind' != ARGC. */
|
||||
|
||||
enum
|
||||
{
|
||||
REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
|
||||
} __ordering;
|
||||
|
||||
/* If the POSIXLY_CORRECT environment variable is set
|
||||
or getopt was called. */
|
||||
int __posixly_correct;
|
||||
|
||||
|
||||
/* Handle permutation of arguments. */
|
||||
|
||||
/* Describe the part of ARGV that contains non-options that have
|
||||
been skipped. `first_nonopt' is the index in ARGV of the first
|
||||
of them; `last_nonopt' is the index after the last of them. */
|
||||
|
||||
int __first_nonopt;
|
||||
int __last_nonopt;
|
||||
|
||||
#if defined _LIBC && defined USE_NONOPTION_FLAGS
|
||||
int __nonoption_flags_max_len;
|
||||
int __nonoption_flags_len;
|
||||
# endif
|
||||
};
|
||||
|
||||
/* The initializer is necessary to set OPTIND and OPTERR to their
|
||||
default values and to clear the initialization flag. */
|
||||
#define _GETOPT_DATA_INITIALIZER { 1, 1 }
|
||||
|
||||
extern int _getopt_internal_r (int ___argc, char **___argv,
|
||||
const char *__shortopts,
|
||||
const struct option *__longopts, int *__longind,
|
||||
int __long_only, int __posixly_correct,
|
||||
struct _getopt_data *__data);
|
||||
|
||||
extern int _getopt_long_r (int ___argc, char **___argv,
|
||||
const char *__shortopts,
|
||||
const struct option *__longopts, int *__longind,
|
||||
struct _getopt_data *__data);
|
||||
|
||||
extern int _getopt_long_only_r (int ___argc, char **___argv,
|
||||
const char *__shortopts,
|
||||
const struct option *__longopts,
|
||||
int *__longind,
|
||||
struct _getopt_data *__data);
|
||||
|
||||
#endif /* getopt_int.h */
|
||||
@@ -0,0 +1,270 @@
|
||||
/* Convenience header for conditional use of GNU <libintl.h>.
|
||||
Copyright (C) 1995-1998, 2000-2002, 2004-2006 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, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#ifndef _LIBGETTEXT_H
|
||||
#define _LIBGETTEXT_H 1
|
||||
|
||||
/* NLS can be disabled through the configure --disable-nls option. */
|
||||
#if ENABLE_NLS
|
||||
|
||||
/* Get declarations of GNU message catalog functions. */
|
||||
# include <libintl.h>
|
||||
|
||||
/* You can set the DEFAULT_TEXT_DOMAIN macro to specify the domain used by
|
||||
the gettext() and ngettext() macros. This is an alternative to calling
|
||||
textdomain(), and is useful for libraries. */
|
||||
# ifdef DEFAULT_TEXT_DOMAIN
|
||||
# undef gettext
|
||||
# define gettext(Msgid) \
|
||||
dgettext (DEFAULT_TEXT_DOMAIN, Msgid)
|
||||
# undef ngettext
|
||||
# define ngettext(Msgid1, Msgid2, N) \
|
||||
dngettext (DEFAULT_TEXT_DOMAIN, Msgid1, Msgid2, N)
|
||||
# endif
|
||||
|
||||
#else
|
||||
|
||||
/* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which
|
||||
chokes if dcgettext is defined as a macro. So include it now, to make
|
||||
later inclusions of <locale.h> a NOP. We don't include <libintl.h>
|
||||
as well because people using "gettext.h" will not include <libintl.h>,
|
||||
and also including <libintl.h> would fail on SunOS 4, whereas <locale.h>
|
||||
is OK. */
|
||||
#if defined(__sun)
|
||||
# include <locale.h>
|
||||
#endif
|
||||
|
||||
/* Many header files from the libstdc++ coming with g++ 3.3 or newer include
|
||||
<libintl.h>, which chokes if dcgettext is defined as a macro. So include
|
||||
it now, to make later inclusions of <libintl.h> a NOP. */
|
||||
#if defined(__cplusplus) && defined(__GNUG__) && (__GNUC__ >= 3)
|
||||
# include <cstdlib>
|
||||
# if (__GLIBC__ >= 2) || _GLIBCXX_HAVE_LIBINTL_H
|
||||
# include <libintl.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Disabled NLS.
|
||||
The casts to 'const char *' serve the purpose of producing warnings
|
||||
for invalid uses of the value returned from these functions.
|
||||
On pre-ANSI systems without 'const', the config.h file is supposed to
|
||||
contain "#define const". */
|
||||
# define gettext(Msgid) ((const char *) (Msgid))
|
||||
# define dgettext(Domainname, Msgid) ((void) (Domainname), gettext (Msgid))
|
||||
# define dcgettext(Domainname, Msgid, Category) \
|
||||
((void) (Category), dgettext (Domainname, Msgid))
|
||||
# define ngettext(Msgid1, Msgid2, N) \
|
||||
((N) == 1 \
|
||||
? ((void) (Msgid2), (const char *) (Msgid1)) \
|
||||
: ((void) (Msgid1), (const char *) (Msgid2)))
|
||||
# define dngettext(Domainname, Msgid1, Msgid2, N) \
|
||||
((void) (Domainname), ngettext (Msgid1, Msgid2, N))
|
||||
# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \
|
||||
((void) (Category), dngettext(Domainname, Msgid1, Msgid2, N))
|
||||
# define textdomain(Domainname) ((const char *) (Domainname))
|
||||
# define bindtextdomain(Domainname, Dirname) \
|
||||
((void) (Domainname), (const char *) (Dirname))
|
||||
# define bind_textdomain_codeset(Domainname, Codeset) \
|
||||
((void) (Domainname), (const char *) (Codeset))
|
||||
|
||||
#endif
|
||||
|
||||
/* A pseudo function call that serves as a marker for the automated
|
||||
extraction of messages, but does not call gettext(). The run-time
|
||||
translation is done at a different place in the code.
|
||||
The argument, String, should be a literal string. Concatenated strings
|
||||
and other string expressions won't work.
|
||||
The macro's expansion is not parenthesized, so that it is suitable as
|
||||
initializer for static 'char[]' or 'const char[]' variables. */
|
||||
#define gettext_noop(String) String
|
||||
|
||||
/* The separator between msgctxt and msgid in a .mo file. */
|
||||
#define GETTEXT_CONTEXT_GLUE "\004"
|
||||
|
||||
/* Pseudo function calls, taking a MSGCTXT and a MSGID instead of just a
|
||||
MSGID. MSGCTXT and MSGID must be string literals. MSGCTXT should be
|
||||
short and rarely need to change.
|
||||
The letter 'p' stands for 'particular' or 'special'. */
|
||||
#ifdef DEFAULT_TEXT_DOMAIN
|
||||
# define pgettext(Msgctxt, Msgid) \
|
||||
pgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
|
||||
#else
|
||||
# define pgettext(Msgctxt, Msgid) \
|
||||
pgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
|
||||
#endif
|
||||
#define dpgettext(Domainname, Msgctxt, Msgid) \
|
||||
pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
|
||||
#define dcpgettext(Domainname, Msgctxt, Msgid, Category) \
|
||||
pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, Category)
|
||||
#ifdef DEFAULT_TEXT_DOMAIN
|
||||
# define npgettext(Msgctxt, Msgid, MsgidPlural, N) \
|
||||
npgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES)
|
||||
#else
|
||||
# define npgettext(Msgctxt, Msgid, MsgidPlural, N) \
|
||||
npgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES)
|
||||
#endif
|
||||
#define dnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N) \
|
||||
npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES)
|
||||
#define dcnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N, Category) \
|
||||
npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, Category)
|
||||
|
||||
#ifdef __GNUC__
|
||||
__inline
|
||||
#else
|
||||
#ifdef __cplusplus
|
||||
inline
|
||||
#endif
|
||||
#endif
|
||||
static const char *
|
||||
pgettext_aux (const char *domain,
|
||||
const char *msg_ctxt_id, const char *msgid,
|
||||
int category)
|
||||
{
|
||||
const char *translation = dcgettext (domain, msg_ctxt_id, category);
|
||||
if (translation == msg_ctxt_id)
|
||||
return msgid;
|
||||
else
|
||||
return translation;
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
__inline
|
||||
#else
|
||||
#ifdef __cplusplus
|
||||
inline
|
||||
#endif
|
||||
#endif
|
||||
static const char *
|
||||
npgettext_aux (const char *domain,
|
||||
const char *msg_ctxt_id, const char *msgid,
|
||||
const char *msgid_plural, unsigned long int n,
|
||||
int category)
|
||||
{
|
||||
const char *translation =
|
||||
dcngettext (domain, msg_ctxt_id, msgid_plural, n, category);
|
||||
if (translation == msg_ctxt_id || translation == msgid_plural)
|
||||
return (n == 1 ? msgid : msgid_plural);
|
||||
else
|
||||
return translation;
|
||||
}
|
||||
|
||||
/* The same thing extended for non-constant arguments. Here MSGCTXT and MSGID
|
||||
can be arbitrary expressions. But for string literals these macros are
|
||||
less efficient than those above. */
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS \
|
||||
(((__GNUC__ >= 3 || __GNUG__ >= 2) && !__STRICT_ANSI__) \
|
||||
/* || __STDC_VERSION__ >= 199901L */ )
|
||||
|
||||
#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#define pgettext_expr(Msgctxt, Msgid) \
|
||||
dcpgettext_expr (NULL, Msgctxt, Msgid, LC_MESSAGES)
|
||||
#define dpgettext_expr(Domainname, Msgctxt, Msgid) \
|
||||
dcpgettext_expr (Domainname, Msgctxt, Msgid, LC_MESSAGES)
|
||||
|
||||
#ifdef __GNUC__
|
||||
__inline
|
||||
#else
|
||||
#ifdef __cplusplus
|
||||
inline
|
||||
#endif
|
||||
#endif
|
||||
static const char *
|
||||
dcpgettext_expr (const char *domain,
|
||||
const char *msgctxt, const char *msgid,
|
||||
int category)
|
||||
{
|
||||
size_t msgctxt_len = strlen (msgctxt) + 1;
|
||||
size_t msgid_len = strlen (msgid) + 1;
|
||||
const char *translation;
|
||||
#if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
|
||||
char msg_ctxt_id[msgctxt_len + msgid_len];
|
||||
#else
|
||||
char buf[1024];
|
||||
char *msg_ctxt_id =
|
||||
(msgctxt_len + msgid_len <= sizeof (buf)
|
||||
? buf
|
||||
: (char *) malloc (msgctxt_len + msgid_len));
|
||||
if (msg_ctxt_id != NULL)
|
||||
#endif
|
||||
{
|
||||
memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1);
|
||||
msg_ctxt_id[msgctxt_len - 1] = '\004';
|
||||
memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len);
|
||||
translation = dcgettext (domain, msg_ctxt_id, category);
|
||||
#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
|
||||
if (msg_ctxt_id != buf)
|
||||
free (msg_ctxt_id);
|
||||
#endif
|
||||
if (translation != msg_ctxt_id)
|
||||
return translation;
|
||||
}
|
||||
return msgid;
|
||||
}
|
||||
|
||||
#define npgettext_expr(Msgctxt, Msgid, MsgidPlural, N) \
|
||||
dcnpgettext_expr (NULL, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES)
|
||||
#define dnpgettext_expr(Domainname, Msgctxt, Msgid, MsgidPlural, N) \
|
||||
dcnpgettext_expr (Domainname, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES)
|
||||
|
||||
#ifdef __GNUC__
|
||||
__inline
|
||||
#else
|
||||
#ifdef __cplusplus
|
||||
inline
|
||||
#endif
|
||||
#endif
|
||||
static const char *
|
||||
dcnpgettext_expr (const char *domain,
|
||||
const char *msgctxt, const char *msgid,
|
||||
const char *msgid_plural, unsigned long int n,
|
||||
int category)
|
||||
{
|
||||
size_t msgctxt_len = strlen (msgctxt) + 1;
|
||||
size_t msgid_len = strlen (msgid) + 1;
|
||||
const char *translation;
|
||||
#if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
|
||||
char msg_ctxt_id[msgctxt_len + msgid_len];
|
||||
#else
|
||||
char buf[1024];
|
||||
char *msg_ctxt_id =
|
||||
(msgctxt_len + msgid_len <= sizeof (buf)
|
||||
? buf
|
||||
: (char *) malloc (msgctxt_len + msgid_len));
|
||||
if (msg_ctxt_id != NULL)
|
||||
#endif
|
||||
{
|
||||
memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1);
|
||||
msg_ctxt_id[msgctxt_len - 1] = '\004';
|
||||
memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len);
|
||||
translation = dcngettext (domain, msg_ctxt_id, msgid_plural, n, category);
|
||||
#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
|
||||
if (msg_ctxt_id != buf)
|
||||
free (msg_ctxt_id);
|
||||
#endif
|
||||
if (!(translation == msg_ctxt_id || translation == msgid_plural))
|
||||
return translation;
|
||||
}
|
||||
return (n == 1 ? msgid : msgid_plural);
|
||||
}
|
||||
|
||||
#endif /* _LIBGETTEXT_H */
|
||||
@@ -0,0 +1,40 @@
|
||||
/* hash-pjw.c -- compute a hash value from a NUL-terminated string.
|
||||
|
||||
Copyright (C) 2001, 2003, 2006 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/>. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "hash-pjw.h"
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#define SIZE_BITS (sizeof (size_t) * CHAR_BIT)
|
||||
|
||||
/* A hash function for NUL-terminated char* strings using
|
||||
the method described by Bruno Haible.
|
||||
See http://www.haible.de/bruno/hashfunc.html. */
|
||||
|
||||
size_t
|
||||
hash_pjw (const void *x, size_t tablesize)
|
||||
{
|
||||
const char *s;
|
||||
size_t h = 0;
|
||||
|
||||
for (s = x; *s; s++)
|
||||
h = *s + ((h << 9) | (h >> (SIZE_BITS - 9)));
|
||||
|
||||
return h % tablesize;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/* hash-pjw.h -- declaration for a simple hash function
|
||||
Copyright (C) 2001, 2003 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/>. */
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
/* Compute a hash code for a NUL-terminated string starting at X,
|
||||
and return the hash code modulo TABLESIZE.
|
||||
The result is platform dependent: it depends on the size of the 'size_t'
|
||||
type and on the signedness of the 'char' type. */
|
||||
extern size_t hash_pjw (void const *x, size_t tablesize);
|
||||
@@ -0,0 +1,77 @@
|
||||
/* Hash functions for file-related triples: name, device, inode.
|
||||
Copyright (C) 2007 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/>. */
|
||||
|
||||
/* written by Jim Meyering */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "hash-triple.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "hash-pjw.h"
|
||||
#include "same.h"
|
||||
#include "same-inode.h"
|
||||
|
||||
#define STREQ(a, b) (strcmp ((a), (b)) == 0)
|
||||
|
||||
/* Hash an F_triple, and *do* consider the file name. */
|
||||
size_t
|
||||
triple_hash (void const *x, size_t table_size)
|
||||
{
|
||||
struct F_triple const *p = x;
|
||||
size_t tmp = hash_pjw (p->name, table_size);
|
||||
|
||||
/* Ignoring the device number here should be fine. */
|
||||
return (tmp ^ p->st_ino) % table_size;
|
||||
}
|
||||
|
||||
/* Hash an F_triple, without considering the file name. */
|
||||
size_t
|
||||
triple_hash_no_name (void const *x, size_t table_size)
|
||||
{
|
||||
struct F_triple const *p = x;
|
||||
|
||||
/* Ignoring the device number here should be fine. */
|
||||
return p->st_ino % table_size;
|
||||
}
|
||||
|
||||
/* Compare two F_triple structs. */
|
||||
bool
|
||||
triple_compare (void const *x, void const *y)
|
||||
{
|
||||
struct F_triple const *a = x;
|
||||
struct F_triple const *b = y;
|
||||
return (SAME_INODE (*a, *b) && same_name (a->name, b->name)) ? true : false;
|
||||
}
|
||||
|
||||
bool
|
||||
triple_compare_ino_str (void const *x, void const *y)
|
||||
{
|
||||
struct F_triple const *a = x;
|
||||
struct F_triple const *b = y;
|
||||
return (SAME_INODE (*a, *b) && STREQ (a->name, b->name)) ? true : false;
|
||||
}
|
||||
|
||||
/* Free an F_triple. */
|
||||
void
|
||||
triple_free (void *x)
|
||||
{
|
||||
struct F_triple *a = x;
|
||||
free (a->name);
|
||||
free (a);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
#ifndef HASH_TRIPLE_H
|
||||
#define HASH_TRIPLE_H
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/* Describe a just-created or just-renamed destination file. */
|
||||
struct F_triple
|
||||
{
|
||||
char *name;
|
||||
ino_t st_ino;
|
||||
dev_t st_dev;
|
||||
};
|
||||
|
||||
extern size_t triple_hash (void const *x, size_t table_size);
|
||||
extern size_t triple_hash_no_name (void const *x, size_t table_size);
|
||||
extern bool triple_compare (void const *x, void const *y);
|
||||
extern bool triple_compare_ino_str (void const *x, void const *y);
|
||||
extern void triple_free (void *x);
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,87 @@
|
||||
/* hash - hashing table processing.
|
||||
Copyright (C) 1998, 1999, 2001, 2003 Free Software Foundation, Inc.
|
||||
Written by Jim Meyering <meyering@ascend.com>, 1998.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 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/>. */
|
||||
|
||||
/* A generic hash table package. */
|
||||
|
||||
/* Make sure USE_OBSTACK is defined to 1 if you want the allocator to use
|
||||
obstacks instead of malloc, and recompile `hash.c' with same setting. */
|
||||
|
||||
#ifndef HASH_H_
|
||||
# define HASH_H_
|
||||
|
||||
# include <stdio.h>
|
||||
# include <stdbool.h>
|
||||
|
||||
typedef size_t (*Hash_hasher) (const void *, size_t);
|
||||
typedef bool (*Hash_comparator) (const void *, const void *);
|
||||
typedef void (*Hash_data_freer) (void *);
|
||||
typedef bool (*Hash_processor) (void *, void *);
|
||||
|
||||
struct hash_entry
|
||||
{
|
||||
void *data;
|
||||
struct hash_entry *next;
|
||||
};
|
||||
|
||||
struct hash_tuning
|
||||
{
|
||||
/* This structure is mainly used for `hash_initialize', see the block
|
||||
documentation of `hash_reset_tuning' for more complete comments. */
|
||||
|
||||
float shrink_threshold; /* ratio of used buckets to trigger a shrink */
|
||||
float shrink_factor; /* ratio of new smaller size to original size */
|
||||
float growth_threshold; /* ratio of used buckets to trigger a growth */
|
||||
float growth_factor; /* ratio of new bigger size to original size */
|
||||
bool is_n_buckets; /* if CANDIDATE really means table size */
|
||||
};
|
||||
|
||||
typedef struct hash_tuning Hash_tuning;
|
||||
|
||||
struct hash_table;
|
||||
|
||||
typedef struct hash_table Hash_table;
|
||||
|
||||
/* Information and lookup. */
|
||||
size_t hash_get_n_buckets (const Hash_table *);
|
||||
size_t hash_get_n_buckets_used (const Hash_table *);
|
||||
size_t hash_get_n_entries (const Hash_table *);
|
||||
size_t hash_get_max_bucket_length (const Hash_table *);
|
||||
bool hash_table_ok (const Hash_table *);
|
||||
void hash_print_statistics (const Hash_table *, FILE *);
|
||||
void *hash_lookup (const Hash_table *, const void *);
|
||||
|
||||
/* Walking. */
|
||||
void *hash_get_first (const Hash_table *);
|
||||
void *hash_get_next (const Hash_table *, const void *);
|
||||
size_t hash_get_entries (const Hash_table *, void **, size_t);
|
||||
size_t hash_do_for_each (const Hash_table *, Hash_processor, void *);
|
||||
|
||||
/* Allocation and clean-up. */
|
||||
size_t hash_string (const char *, size_t);
|
||||
void hash_reset_tuning (Hash_tuning *);
|
||||
Hash_table *hash_initialize (size_t, const Hash_tuning *,
|
||||
Hash_hasher, Hash_comparator,
|
||||
Hash_data_freer);
|
||||
void hash_clear (Hash_table *);
|
||||
void hash_free (Hash_table *);
|
||||
|
||||
/* Insertion and deletion. */
|
||||
bool hash_rehash (Hash_table *, size_t);
|
||||
void *hash_insert (Hash_table *, const void *);
|
||||
void *hash_delete (Hash_table *, const void *);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,471 @@
|
||||
/* human.c -- print human readable file size
|
||||
|
||||
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
|
||||
2005, 2006, 2007 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/>. */
|
||||
|
||||
/* Written by Paul Eggert and Larry McVoy. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "human.h"
|
||||
|
||||
#include <locale.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <argmatch.h>
|
||||
#include <error.h>
|
||||
#include <intprops.h>
|
||||
|
||||
/* The maximum length of a suffix like "KiB". */
|
||||
#define HUMAN_READABLE_SUFFIX_LENGTH_MAX 3
|
||||
|
||||
static const char power_letter[] =
|
||||
{
|
||||
0, /* not used */
|
||||
'K', /* kibi ('k' for kilo is a special case) */
|
||||
'M', /* mega or mebi */
|
||||
'G', /* giga or gibi */
|
||||
'T', /* tera or tebi */
|
||||
'P', /* peta or pebi */
|
||||
'E', /* exa or exbi */
|
||||
'Z', /* zetta or 2**70 */
|
||||
'Y' /* yotta or 2**80 */
|
||||
};
|
||||
|
||||
|
||||
/* If INEXACT_STYLE is not human_round_to_nearest, and if easily
|
||||
possible, adjust VALUE according to the style. */
|
||||
|
||||
static long double
|
||||
adjust_value (int inexact_style, long double value)
|
||||
{
|
||||
/* Do not use the floorl or ceill functions, as that would mean
|
||||
checking for their presence and possibly linking with the
|
||||
standard math library, which is a porting pain. So leave the
|
||||
value alone if it is too large to easily round. */
|
||||
if (inexact_style != human_round_to_nearest && value < UINTMAX_MAX)
|
||||
{
|
||||
uintmax_t u = value;
|
||||
value = u + (inexact_style == human_ceiling && u != value);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/* Group the digits of NUMBER according to the grouping rules of the
|
||||
current locale. NUMBER contains NUMBERLEN digits. Modify the
|
||||
bytes pointed to by NUMBER in place, subtracting 1 from NUMBER for
|
||||
each byte inserted. Return the starting address of the modified
|
||||
number.
|
||||
|
||||
To group the digits, use GROUPING and THOUSANDS_SEP as in `struct
|
||||
lconv' from <locale.h>. */
|
||||
|
||||
static char *
|
||||
group_number (char *number, size_t numberlen,
|
||||
char const *grouping, char const *thousands_sep)
|
||||
{
|
||||
register char *d;
|
||||
size_t grouplen = SIZE_MAX;
|
||||
size_t thousands_seplen = strlen (thousands_sep);
|
||||
size_t i = numberlen;
|
||||
|
||||
/* The maximum possible value for NUMBERLEN is the number of digits
|
||||
in the square of the largest uintmax_t, so double the size needed. */
|
||||
char buf[2 * INT_STRLEN_BOUND (uintmax_t) + 1];
|
||||
|
||||
memcpy (buf, number, numberlen);
|
||||
d = number + numberlen;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
unsigned char g = *grouping;
|
||||
|
||||
if (g)
|
||||
{
|
||||
grouplen = g < CHAR_MAX ? g : i;
|
||||
grouping++;
|
||||
}
|
||||
|
||||
if (i < grouplen)
|
||||
grouplen = i;
|
||||
|
||||
d -= grouplen;
|
||||
i -= grouplen;
|
||||
memcpy (d, buf + i, grouplen);
|
||||
if (i == 0)
|
||||
return d;
|
||||
|
||||
d -= thousands_seplen;
|
||||
memcpy (d, thousands_sep, thousands_seplen);
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert N to a human readable format in BUF, using the options OPTS.
|
||||
|
||||
N is expressed in units of FROM_BLOCK_SIZE. FROM_BLOCK_SIZE must
|
||||
be nonnegative.
|
||||
|
||||
Use units of TO_BLOCK_SIZE in the output number. TO_BLOCK_SIZE
|
||||
must be positive.
|
||||
|
||||
Use (OPTS & (human_round_to_nearest | human_floor | human_ceiling))
|
||||
to determine whether to take the ceiling or floor of any result
|
||||
that cannot be expressed exactly.
|
||||
|
||||
If (OPTS & human_group_digits), group the thousands digits
|
||||
according to the locale, e.g., `1,000,000' in an American English
|
||||
locale.
|
||||
|
||||
If (OPTS & human_autoscale), deduce the output block size
|
||||
automatically; TO_BLOCK_SIZE must be 1 but it has no effect on the
|
||||
output. Use powers of 1024 if (OPTS & human_base_1024), and powers
|
||||
of 1000 otherwise. For example, assuming powers of 1024, 8500
|
||||
would be converted to 8.3, 133456345 to 127, 56990456345 to 53, and
|
||||
so on. Numbers smaller than the power aren't modified.
|
||||
human_autoscale is normally used together with human_SI.
|
||||
|
||||
If (OPTS & human_space_before_unit), use a space to separate the
|
||||
number from any suffix that is appended as described below.
|
||||
|
||||
If (OPTS & human_SI), append an SI prefix indicating which power is
|
||||
being used. If in addition (OPTS & human_B), append "B" (if base
|
||||
1000) or "iB" (if base 1024) to the SI prefix. When ((OPTS &
|
||||
human_SI) && ! (OPTS & human_autoscale)), TO_BLOCK_SIZE must be a
|
||||
power of 1024 or of 1000, depending on (OPTS &
|
||||
human_base_1024). */
|
||||
|
||||
char *
|
||||
human_readable (uintmax_t n, char *buf, int opts,
|
||||
uintmax_t from_block_size, uintmax_t to_block_size)
|
||||
{
|
||||
int inexact_style =
|
||||
opts & (human_round_to_nearest | human_floor | human_ceiling);
|
||||
unsigned int base = opts & human_base_1024 ? 1024 : 1000;
|
||||
uintmax_t amt;
|
||||
int tenths;
|
||||
int exponent = -1;
|
||||
int exponent_max = sizeof power_letter - 1;
|
||||
char *p;
|
||||
char *psuffix;
|
||||
char const *integerlim;
|
||||
|
||||
/* 0 means adjusted N == AMT.TENTHS;
|
||||
1 means AMT.TENTHS < adjusted N < AMT.TENTHS + 0.05;
|
||||
2 means adjusted N == AMT.TENTHS + 0.05;
|
||||
3 means AMT.TENTHS + 0.05 < adjusted N < AMT.TENTHS + 0.1. */
|
||||
int rounding;
|
||||
|
||||
char const *decimal_point = ".";
|
||||
size_t decimal_pointlen = 1;
|
||||
char const *grouping = "";
|
||||
char const *thousands_sep = "";
|
||||
struct lconv const *l = localeconv ();
|
||||
size_t pointlen = strlen (l->decimal_point);
|
||||
if (0 < pointlen && pointlen <= MB_LEN_MAX)
|
||||
{
|
||||
decimal_point = l->decimal_point;
|
||||
decimal_pointlen = pointlen;
|
||||
}
|
||||
grouping = l->grouping;
|
||||
if (strlen (l->thousands_sep) <= MB_LEN_MAX)
|
||||
thousands_sep = l->thousands_sep;
|
||||
|
||||
psuffix = buf + LONGEST_HUMAN_READABLE - HUMAN_READABLE_SUFFIX_LENGTH_MAX;
|
||||
p = psuffix;
|
||||
|
||||
/* Adjust AMT out of FROM_BLOCK_SIZE units and into TO_BLOCK_SIZE
|
||||
units. If this can be done exactly with integer arithmetic, do
|
||||
not use floating point operations. */
|
||||
if (to_block_size <= from_block_size)
|
||||
{
|
||||
if (from_block_size % to_block_size == 0)
|
||||
{
|
||||
uintmax_t multiplier = from_block_size / to_block_size;
|
||||
amt = n * multiplier;
|
||||
if (amt / multiplier == n)
|
||||
{
|
||||
tenths = 0;
|
||||
rounding = 0;
|
||||
goto use_integer_arithmetic;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (from_block_size != 0 && to_block_size % from_block_size == 0)
|
||||
{
|
||||
uintmax_t divisor = to_block_size / from_block_size;
|
||||
uintmax_t r10 = (n % divisor) * 10;
|
||||
uintmax_t r2 = (r10 % divisor) * 2;
|
||||
amt = n / divisor;
|
||||
tenths = r10 / divisor;
|
||||
rounding = r2 < divisor ? 0 < r2 : 2 + (divisor < r2);
|
||||
goto use_integer_arithmetic;
|
||||
}
|
||||
|
||||
{
|
||||
/* Either the result cannot be computed easily using uintmax_t,
|
||||
or from_block_size is zero. Fall back on floating point.
|
||||
FIXME: This can yield answers that are slightly off. */
|
||||
|
||||
long double dto_block_size = to_block_size;
|
||||
long double damt = n * (from_block_size / dto_block_size);
|
||||
size_t buflen;
|
||||
size_t nonintegerlen;
|
||||
|
||||
if (! (opts & human_autoscale))
|
||||
{
|
||||
sprintf (buf, "%.0Lf", adjust_value (inexact_style, damt));
|
||||
buflen = strlen (buf);
|
||||
nonintegerlen = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
long double e = 1;
|
||||
exponent = 0;
|
||||
|
||||
do
|
||||
{
|
||||
e *= base;
|
||||
exponent++;
|
||||
}
|
||||
while (e * base <= damt && exponent < exponent_max);
|
||||
|
||||
damt /= e;
|
||||
|
||||
sprintf (buf, "%.1Lf", adjust_value (inexact_style, damt));
|
||||
buflen = strlen (buf);
|
||||
nonintegerlen = decimal_pointlen + 1;
|
||||
|
||||
if (1 + nonintegerlen + ! (opts & human_base_1024) < buflen
|
||||
|| ((opts & human_suppress_point_zero)
|
||||
&& buf[buflen - 1] == '0'))
|
||||
{
|
||||
sprintf (buf, "%.0Lf",
|
||||
adjust_value (inexact_style, damt * 10) / 10);
|
||||
buflen = strlen (buf);
|
||||
nonintegerlen = 0;
|
||||
}
|
||||
}
|
||||
|
||||
p = psuffix - buflen;
|
||||
memmove (p, buf, buflen);
|
||||
integerlim = p + buflen - nonintegerlen;
|
||||
}
|
||||
goto do_grouping;
|
||||
|
||||
use_integer_arithmetic:
|
||||
{
|
||||
/* The computation can be done exactly, with integer arithmetic.
|
||||
|
||||
Use power of BASE notation if requested and if adjusted AMT is
|
||||
large enough. */
|
||||
|
||||
if (opts & human_autoscale)
|
||||
{
|
||||
exponent = 0;
|
||||
|
||||
if (base <= amt)
|
||||
{
|
||||
do
|
||||
{
|
||||
unsigned int r10 = (amt % base) * 10 + tenths;
|
||||
unsigned int r2 = (r10 % base) * 2 + (rounding >> 1);
|
||||
amt /= base;
|
||||
tenths = r10 / base;
|
||||
rounding = (r2 < base
|
||||
? (r2 + rounding) != 0
|
||||
: 2 + (base < r2 + rounding));
|
||||
exponent++;
|
||||
}
|
||||
while (base <= amt && exponent < exponent_max);
|
||||
|
||||
if (amt < 10)
|
||||
{
|
||||
if (inexact_style == human_round_to_nearest
|
||||
? 2 < rounding + (tenths & 1)
|
||||
: inexact_style == human_ceiling && 0 < rounding)
|
||||
{
|
||||
tenths++;
|
||||
rounding = 0;
|
||||
|
||||
if (tenths == 10)
|
||||
{
|
||||
amt++;
|
||||
tenths = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (amt < 10
|
||||
&& (tenths || ! (opts & human_suppress_point_zero)))
|
||||
{
|
||||
*--p = '0' + tenths;
|
||||
p -= decimal_pointlen;
|
||||
memcpy (p, decimal_point, decimal_pointlen);
|
||||
tenths = rounding = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (inexact_style == human_round_to_nearest
|
||||
? 5 < tenths + (0 < rounding + (amt & 1))
|
||||
: inexact_style == human_ceiling && 0 < tenths + rounding)
|
||||
{
|
||||
amt++;
|
||||
|
||||
if ((opts & human_autoscale)
|
||||
&& amt == base && exponent < exponent_max)
|
||||
{
|
||||
exponent++;
|
||||
if (! (opts & human_suppress_point_zero))
|
||||
{
|
||||
*--p = '0';
|
||||
p -= decimal_pointlen;
|
||||
memcpy (p, decimal_point, decimal_pointlen);
|
||||
}
|
||||
amt = 1;
|
||||
}
|
||||
}
|
||||
|
||||
integerlim = p;
|
||||
|
||||
do
|
||||
{
|
||||
int digit = amt % 10;
|
||||
*--p = digit + '0';
|
||||
}
|
||||
while ((amt /= 10) != 0);
|
||||
}
|
||||
|
||||
do_grouping:
|
||||
if (opts & human_group_digits)
|
||||
p = group_number (p, integerlim - p, grouping, thousands_sep);
|
||||
|
||||
if (opts & human_SI)
|
||||
{
|
||||
if (exponent < 0)
|
||||
{
|
||||
uintmax_t power;
|
||||
exponent = 0;
|
||||
for (power = 1; power < to_block_size; power *= base)
|
||||
if (++exponent == exponent_max)
|
||||
break;
|
||||
}
|
||||
|
||||
if ((exponent | (opts & human_B)) && (opts & human_space_before_unit))
|
||||
*psuffix++ = ' ';
|
||||
|
||||
if (exponent)
|
||||
*psuffix++ = (! (opts & human_base_1024) && exponent == 1
|
||||
? 'k'
|
||||
: power_letter[exponent]);
|
||||
|
||||
if (opts & human_B)
|
||||
{
|
||||
if ((opts & human_base_1024) && exponent)
|
||||
*psuffix++ = 'i';
|
||||
*psuffix++ = 'B';
|
||||
}
|
||||
}
|
||||
|
||||
*psuffix = '\0';
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
/* The default block size used for output. This number may change in
|
||||
the future as disks get larger. */
|
||||
#ifndef DEFAULT_BLOCK_SIZE
|
||||
# define DEFAULT_BLOCK_SIZE 1024
|
||||
#endif
|
||||
|
||||
static char const *const block_size_args[] = { "human-readable", "si", 0 };
|
||||
static int const block_size_opts[] =
|
||||
{
|
||||
human_autoscale + human_SI + human_base_1024,
|
||||
human_autoscale + human_SI
|
||||
};
|
||||
|
||||
static uintmax_t
|
||||
default_block_size (void)
|
||||
{
|
||||
return getenv ("POSIXLY_CORRECT") ? 512 : DEFAULT_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
static strtol_error
|
||||
humblock (char const *spec, uintmax_t *block_size, int *options)
|
||||
{
|
||||
int i;
|
||||
int opts = 0;
|
||||
|
||||
if (! spec
|
||||
&& ! (spec = getenv ("BLOCK_SIZE"))
|
||||
&& ! (spec = getenv ("BLOCKSIZE")))
|
||||
*block_size = default_block_size ();
|
||||
else
|
||||
{
|
||||
if (*spec == '\'')
|
||||
{
|
||||
opts |= human_group_digits;
|
||||
spec++;
|
||||
}
|
||||
|
||||
if (0 <= (i = ARGMATCH (spec, block_size_args, block_size_opts)))
|
||||
{
|
||||
opts |= block_size_opts[i];
|
||||
*block_size = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
char *ptr;
|
||||
strtol_error e = xstrtoumax (spec, &ptr, 0, block_size,
|
||||
"eEgGkKmMpPtTyYzZ0");
|
||||
if (e != LONGINT_OK)
|
||||
{
|
||||
*options = 0;
|
||||
return e;
|
||||
}
|
||||
for (; ! ('0' <= *spec && *spec <= '9'); spec++)
|
||||
if (spec == ptr)
|
||||
{
|
||||
opts |= human_SI;
|
||||
if (ptr[-1] == 'B')
|
||||
opts |= human_B;
|
||||
if (ptr[-1] != 'B' || ptr[-2] == 'i')
|
||||
opts |= human_base_1024;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*options = opts;
|
||||
return LONGINT_OK;
|
||||
}
|
||||
|
||||
enum strtol_error
|
||||
human_options (char const *spec, int *opts, uintmax_t *block_size)
|
||||
{
|
||||
strtol_error e = humblock (spec, block_size, opts);
|
||||
if (*block_size == 0)
|
||||
{
|
||||
*block_size = default_block_size ();
|
||||
e = LONGINT_INVALID;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user