Compare commits

..

No commits in common. "edge" and "szaka" have entirely different histories.
edge ... szaka

181 changed files with 5969 additions and 107686 deletions

23
AUTHORS
View File

@ -1,23 +0,0 @@
Present authors of ntfs-3g in alphabetical order:
Jean-Pierre Andre
Alon Bar-Lev
Martin Bene
Dominique L Bouix
Csaba Henk
Bernhard Kaindl
Erik Larsson
Alejandro Pulver
Szabolcs Szakacsits
Miklos Szeredi
Past authors in alphabetical order:
Anton Altaparmakov
Mario Emmenlauer
Yuval Fledel
Yura Pakhuchiy
Richard Russon

340
COPYING
View File

@ -1,340 +0,0 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
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
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.
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.
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.
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.
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.
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.
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".
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.
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.
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.
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:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
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.
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.
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.
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.
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:
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,
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,
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 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.
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.
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.
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
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
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.
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.
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.
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.
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
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.
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.
NO WARRANTY
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.
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.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
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:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision 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.
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:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

View File

@ -1,482 +0,0 @@
GNU LIBRARY GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1991 Free Software Foundation, Inc.
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the library GPL. It is
numbered 2 because it goes with version 2 of the ordinary GPL.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Library General Public License, applies to some
specially designated Free Software Foundation software, and to any
other libraries whose authors decide to use it. You can use it for
your libraries, 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.
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 library, or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link a program with the library, you must provide
complete object files to the recipients so that they can relink them
with the library, after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
Our method of protecting your rights has two steps: (1) copyright
the library, and (2) offer you this license which gives you legal
permission to copy, distribute and/or modify the library.
Also, for each distributor's protection, we want to make certain
that everyone understands that there is no warranty for this free
library. If the library is modified by someone else and passed on, we
want its recipients to know that what they have is not the original
version, so that any problems introduced by others will not reflect on
the original authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that companies distributing free
software will individually obtain patent licenses, thus in effect
transforming the program into proprietary software. To prevent this,
we have made it clear that any patent must be licensed for everyone's
free use or not licensed at all.
Most GNU software, including some libraries, is covered by the ordinary
GNU General Public License, which was designed for utility programs. This
license, the GNU Library General Public License, applies to certain
designated libraries. This license is quite different from the ordinary
one; be sure to read it in full, and don't assume that anything in it is
the same as in the ordinary license.
The reason we have a separate public license for some libraries is that
they blur the distinction we usually make between modifying or adding to a
program and simply using it. Linking a program with a library, without
changing the library, is in some sense simply using the library, and is
analogous to running a utility program or application program. However, in
a textual and legal sense, the linked executable is a combined work, a
derivative of the original library, and the ordinary General Public License
treats it as such.
Because of this blurred distinction, using the ordinary General
Public License for libraries did not effectively promote software
sharing, because most developers did not use the libraries. We
concluded that weaker conditions might promote sharing better.
However, unrestricted linking of non-free programs would deprive the
users of those programs of all benefit from the free status of the
libraries themselves. This Library General Public License is intended to
permit developers of non-free programs to use free libraries, while
preserving your freedom as a user of such programs to change the free
libraries that are incorporated in them. (We have not seen how to achieve
this as regards changes in header files, but we have achieved it as regards
changes in the actual functions of the Library.) The hope is that this
will lead to faster development of free libraries.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, while the latter only
works together with the library.
Note that it is possible for a library to be covered by the ordinary
General Public License rather than by this special one.
GNU LIBRARY GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library which
contains a notice placed by the copyright holder or other authorized
party saying it may be distributed under the terms of this Library
General Public License (also called "this License"). Each licensee is
addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, 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 library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete 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 distribute a copy of this License along with the
Library.
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.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
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 Library, 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.
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 Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you 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.
If distribution of 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 satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also compile or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
c) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
d) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. 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.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library 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.
9. 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 Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
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
this License.
11. 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
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 Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library 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 Library.
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.
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.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library 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.
13. The Free Software Foundation may publish revised and/or new
versions of the Library 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 Library
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 Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
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.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "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
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. 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 LIBRARY 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
LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
Appendix: How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. 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 the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

23
CREDITS
View File

@ -5,9 +5,6 @@ Please let ntfs-3g-devel@lists.sf.net know if you believe
someone is missing, or if you prefer not to be listed.
Dominique L Bouix
Csaba Henk
Max Khon
Auri Hautamäki
Gergely Erdelyi
Anton Altaparmakov
Peter Boross
@ -38,24 +35,4 @@ Ismail Donmez
Laszlo Dvornik
Pallaghy Ajtony
Szabolcs Szakacsits
Alexei Alexandrov
Albert D. Cahalan
Russ Christensen
Pete Curran
Andras Erdei
Matthew J. Fanto
Marcin GibuÅa
Christophe Grenier
Ian Jackson
Carmelo Kintana
Jan Kratochvil
Lode Leroy
David Martínez Moreno
Giang Nguyen
Leonard Norrgård
Holger Ohmacht
Per Olofsson
Yuri Per
Richard Russon
Erik Sørnes

View File

@ -1,3 +0,0 @@
ChangeLog can be found at :
https://github.com/tuxera/ntfs-3g/wiki

View File

@ -1,60 +1,17 @@
SUBDIRS = include libntfs-3g src
EXTRA_DIST = AUTHORS CREDITS COPYING INSTALL NEWS README autogen.sh
AUTOMAKE_OPTIONS = gnu
ACLOCAL_AMFLAGS = -I m4
EXTRA_DIST = AUTHORS CREDITS COPYING NEWS autogen.sh
MAINTAINERCLEANFILES=\
$(srcdir)/configure \
$(srcdir)/Makefile.in \
$(srcdir)/aclocal.m4 \
$(srcdir)/compile \
$(srcdir)/depcomp \
$(srcdir)/install-sh \
$(srcdir)/ltmain.sh \
$(srcdir)/missing \
$(srcdir)/config.guess \
$(srcdir)/config.sub \
$(srcdir)/config.h.in \
$(srcdir)/config.h.in~ \
$(srcdir)/INSTALL \
$(srcdir)/m4/ltsugar.m4 \
$(srcdir)/m4/libtool.m4 \
$(srcdir)/m4/ltversion.m4 \
$(srcdir)/m4/lt~obsolete.m4 \
$(srcdir)/m4/ltoptions.m4
SUBDIRS = include libfuse-lite libntfs-3g ntfsprogs src
doc_DATA = README
dist-hook:
$(MKDIR_P) "$(distdir)/m4"
MAINTAINERCLEANFILES = configure Makefile.in aclocal.m4 compile depcomp \
install-sh ltmain.sh missing config.guess config.sub config.h.in INSTALL
libtool: $(LIBTOOL_DEPS)
$(SHELL) ./config.status --recheck
libs:
if FUSE_INTERNAL
(cd libfuse-lite && $(MAKE) libs) || exit 1;
endif
(cd libntfs-3g && $(MAKE) libs) || exit 1;
libntfs:
(cd libntfs-3g && $(MAKE) libs) || exit 1;
drivers: libs
(cd src && $(MAKE) drivers) || exit 1;
ntfsprogs: libntfs
(cd ntfsprogs && $(MAKE)) || exit 1;
if ENABLE_NTFSPROGS
strip:
(cd ntfsprogs && $(MAKE) strip) || exit 1;
(cd src && $(MAKE) strip) || exit 1;
extra: extras
extras: libs
(cd ntfsprogs && $(MAKE) extras) || exit 1;
endif
libs:
(cd libntfs-3g && $(MAKE) libs) || exit 1;

3
NEWS
View File

@ -1,3 +0,0 @@
Project information can be found at :
https://github.com/tuxera/ntfs-3g/

171
README
View File

@ -2,165 +2,62 @@
INTRODUCTION
============
The NTFS-3G driver is an open source, freely available read/write NTFS driver
for Linux, FreeBSD, macOS, NetBSD, OpenIndiana, QNX and Haiku. It provides
safe and fast handling of the Windows XP, Windows Server 2003, Windows 2000,
Windows Vista, Windows Server 2008, Windows 7, Windows 8, Windows Server 2012,
Windows Server 2016, Windows 10 and Windows Server 2019 NTFS file systems.
The ntfs-3g driver is an open source, freely available read/write NTFS
driver, which provides safe and fast handling of the Windows XP, Windows
Server 2003 and Windows 2000 filesystems. Almost the full POSIX filesystem
functionality is supported, the major exceptions are changing the file
ownerships and the access rights.
The purpose of the project is to develop, quality assurance and support a
trustable, featureful and high performance solution for hardware platforms
and operating systems whose users need to reliably interoperate with NTFS.
Besides this practical goal, the project also aims to explore the limits
of the hybrid, kernel/user space filesystem driver approach, performance,
reliability and feature richness per invested effort wise.
The purpose of the project is to develop, continuously quality test and
support a trustable, featureful and high performance solution for hardware
platforms and operating systems whose users need to reliably interoperate
with NTFS. Besides this practical goal, the project also aims to explore
the limits of the hybrid, kernel/user space filesystem driver approach,
performance, reliability and feature richness per invested effort wise.
Besides the common file system features, NTFS-3G has support for file
ownership and permissions, POSIX ACLs, junction points, extended attributes
and creating internally compressed files (parameter files in the directory
.NTFS-3G may be required to enable them). The new compressed file formats
available in Windows 10 can also be read through a plugin.
The driver currently is in BETA status, which means that we weren't
reported and haven't found any data corruption or loss during ordinary
driver use and in our extensive quality testing before release of the
latest version of ntfs-3g, however we are aware of some usability issues
and driver restrictions which are all documented and planned to be resolved
in the future.
News, support answers, problem submission instructions, support and discussion
forums, and other information are available on the project web site at
You can find news, technical answers, problem submission instructions,
performance evaluation and other informations on the project web site:
https://github.com/tuxera/ntfs-3g/wiki
The project has been funded, supported and maintained since 2008 by Tuxera:
https://tuxera.com
LICENSES
========
All the NTFS related components: the file system drivers, the ntfsprogs
utilities and the shared library libntfs-3g are distributed under the terms
of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version. See the included file COPYING.
The fuse-lite library is distributed under the terms of the GNU LGPLv2.
See the included file COPYING.LIB.
http://www.ntfs-3g.org
QUICK INSTALLATION
==================
Most distributions have an up-to-date NTFS-3G package ready for use, and
the recommended way is to install it.
If you need some specific customization, you can compile and install from
the released source code. Make sure you have the basic development tools
and the kernel includes the FUSE kernel module. Then unpack the source
tarball and type:
Make sure you have the basic Linux development tools and the full FUSE
package (http://fuse.sourceforge.net) is already installed correctly on
the computer. Then type:
./configure
make
make install # or 'sudo make install' if you aren't root.
Please note that NTFS-3G doesn't require the FUSE user space package any
more.
The list of options for building specific configurations is displayed by
typing :
./configure --help
Below are a few specific options to ./configure :
--disable-ntfsprogs : do not build the ntfsprogs tools,
--enable-extras : build more ntfsprogs tools,
--disable-plugins : disable support for plugins
--enable-posix-acls : enable support for Posix ACLs
--enable-xattr-mappings : enable system extended attributes mappings
--with-fuse=external : use external fuse (overriding Linux default)
There are also a few make targets for building parts :
make libntfs : only build the libntfs-3g library
make libs : only build libntfs-3g (and libfuse-lite, if relevant)
make drivers : only build drivers and libraries, without ntfsprogs
make ntfsprogs : only build ntfsprogs and libntfs-3g, without drivers
USAGE
=====
If there was no error during installation then the NTFS volume can be
read-write mounted for everybody the following way as the root user
(unmount the volume if it was already mounted, and replace /dev/sda1
and /mnt/windows, if needed):
read-write mounted for everybody the following way (unmount the volume if
it was already mounted, and replace /dev/hda1 and /mnt/windows, if needed):
mount -t ntfs-3g /dev/sda1 /mnt/windows
or
ntfs-3g /dev/sda1 /mnt/windows
ntfs-3g /dev/hda1 /mnt/windows
You may also need to set the 'locale' option to make all files with national
characters visible. Replace the below hu_HU.utf8 with the appropriate setting.
ntfs-3g /dev/hda1 /mnt/windows -o locale=hu_HU.utf8
Please see the ntfs-3g manual page for more options and examples.
You can also make NTFS to be mounted during boot by putting the below
line at the END(!) of the /etc/fstab file:
line at the end of the /etc/fstab file:
/dev/sda1 /mnt/windows ntfs-3g defaults 0 0
/dev/hda1 /mnt/windows ntfs-3g defaults 0 0
TESTING WITHOUT INSTALLING
=========================
Newer versions of ntfs-3g can be tested without installing anything and
without disturbing an existing installation. Just configure and make as
shown previously. This will create the scripts ntfs-3g and lowntfs-3g
in the src directory, which you may activate for testing:
./configure
make
then, as root:
src/ntfs-3g [-o mount-options] /dev/sda1 /mnt/windows
And, to end the test, unmount the usual way:
umount /dev/sda1
NTFS UTILITIES
==============
The ntfsprogs directory includes utilities for doing all required tasks to
NTFS partitions. In general, just run a utility without any command line
options to display the version number and usage syntax.
The following utilities are so far implemented:
ntfsfix - Attempt to fix an NTFS partition and force Windows to check NTFS.
mkntfs - Format a partition with the NTFS filesystem. See man 8 mkntfs for
command line options.
ntfslabel - Display/change the label of an NTFS partition. See man 8 ntfslabel
for details.
ntfsundelete - Recover deleted files from an NTFS volume. See man 8
ntfsundelete for more details.
ntfsresize - Resize NTFS volumes. See man 8 ntfsresize for details.
ntfsclone - Efficiently create/restore an image of an NTFS partition. See
man 8 ntfsclone for details.
ntfscluster - Locate the owner of any given sector or cluster on an NTFS
partition. See man 8 ntfscluster for details.
ntfsinfo - Show some information about an NTFS partition or one of the files
or directories within it. See man 8 ntfsinfo for details.
ntfsrecover - Recover updates committed by Windows but interrupted before
being synced.
ntfsls - List information about files in a directory residing on an NTFS
partition. See man 8 ntfsls for details.
ntfscat - Concatenate files and print their contents on the standard output.
ntfscp - Overwrite files on an NTFS partition.
ntfssecaudit - Audit the security metadata.
ntfsusermap - Assistance for building a user mapping file.

View File

@ -1,126 +0,0 @@
Please keep in alphabetical order so utilities are easier to find.
Thanks,
Anton
**********
* mkntfs *
**********
- Correct support for creating volumes with larger sector sizes (mft record
size, cluster size, and index block size must be >= sector size), so for 1k,
2k, and 4k sectors, we need to set the default mft record, cluster, and index
block size to be at least the sector size.
- Correct the odd last partition sector not being accessible under 2.4 kernels
by setting the device block size to the sector size (default is 1k on 2.4
kernels and they can't cope with partial sectors).
- Got a report that creating a floppy with mkntfs failed. Difference between
this floppy and the floppy created by the special tool found on the net was
said to be that the bitmap is 256kib on the special floppy while mkntfs will
make it much smaller. Need to verify this and experiment with the bitmap
size to make it work. Note, reporter was using win2k.
*************
* ntfsclone *
*************
- get rid of the unneeded lseek()'s during reads/writes (probably it
doesn't improve performance much, or any at all)
- catch if source and dest are the same
- disable consistency check for --metadata (e.g. if the check is crashing)
- option: --inode
- option: --data
- metadata cloning: skip more non-needed inodes
- manual: document LFS issues (smbfs' lfs option, nfs)
- manual: mention optimized seeks
- manual: optimal backup if disks have bad sectors
- manual: ntfsclone guarantees the restored image works only
if one restores to the exactly same partition. For example,
one can not copy system partition to a different partition:
minimum "hidden sectors" field and BOOT.INI need modifications.
We could do these adjustments optionally.
- check if kernel block size = GCD(page size, device size) makes
effect on performance (Al Viro says no)
- check whether the O_WRONLY -> O_RDWR change made effect on performance
***********
* ntfscmp *
***********
- compare mft record headers
- exit status is 0 if inputs are the same, 1 if different, other if trouble
- optionally ignore less interesting fields (e.g. attribute instance)
- new option: --metadata mode
- unnamed resident attributes with same type are ignored
- code cleanup, remove many cross-util duplicates
- handle deleted records
- performance: special handling for sparse files
**********
* ntfscp *
**********
- add ability to copy multiple files at once.
***********
* ntfsfix *
***********
- Cleanup to use ntfs_attr_* API for editing $MFTMirr, $Volume, and $LogFile.
This has the immediate benefit of enabling attribute list support and making
the code simpler.
- On ntfs 3.0+ volumes need to disable the usn journal if it is active. This
means deleting file $UsnJrnl from /$Extend directory.
- On ntfs 3.0+ volumes need to mark the quota out of date? - Probably, but
it shouldn't cause any corruption not doing so for the moment so this is
not a showstopper bug for the first release. (AIA)
*************
* ntfslabel *
*************
- Support ioctls for kernel driver and ntfsmount for reading/changing the label.
*************
* ntfsmount *
*************
**************
* ntfsresize *
**************
High priority
- move ntfs consistency check to libntfs (for ntfsck, ntfsclone, etc)
- use different exit codes (e.g. corrupt volume detected, unsupported case,
bad sectors, etc)
Medium priority
- cope with the rare, unsupported cases, see man ntfsresize 'KNOWN ISSUES'
- save $Bitmap if it was modified and an error occures (e.g. bad sector).
- handle signals (^C, etc)
Low priority
- fully support disks with bad sectors (attrlist attr, unknown bad sectors)
- move volume start
****************
* ntfsundelete *
****************
- undelete by name rather than inode number
- support for compressed files
- support for internationalisation
- recover by type?
- mass undelete (using wildcards)
- display parent directory
- name "<none>" to MFTn

View File

@ -1,4 +1,4 @@
#!/bin/sh
#!/bin/bash
# Run this to generate configure, Makefile.in's, etc
(autoreconf --version) < /dev/null > /dev/null 2>&1 || {
@ -18,5 +18,5 @@
exit 1
}
echo Running autoreconf --verbose --install --force
autoreconf --verbose --install --force
echo Running autoreconf --verbose --install
autoreconf --force --verbose --install

View File

@ -2,10 +2,9 @@
# configure.ac - Source file to generate "./configure" to prepare package for
# compilation.
#
# Copyright (c) 2000-2013 Anton Altaparmakov
# Copyright (c) 2000-2006 Anton Altaparmakov
# Copyright (c) 2003 Jan Kratochvil
# Copyright (c) 2005-2009 Szabolcs Szakacsits
# Copyright (C) 2007-2008 Alon Bar-Lev
# Copyright (c) 2005-2006 Szabolcs Szakacsits
#
# This program/include file is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as published
@ -21,345 +20,74 @@
# along with this program (in the main directory of the NTFS-3G
# distribution in the file COPYING); if not, write to the Free Software
# Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# Autoconf
AC_PREREQ(2.59)
AC_INIT([ntfs-3g],[2022.10.3],[ntfs-3g-devel@lists.sf.net])
LIBNTFS_3G_VERSION="89"
AC_CONFIG_SRCDIR([src/ntfs-3g.c])
AC_INIT([ntfs-3g],[0.20061031-BETA],[ntfs-3g-devel@lists.sf.net])
# Environment
AC_CANONICAL_HOST
AC_CANONICAL_TARGET
# Automake
AM_INIT_AUTOMAKE([])
AC_CANONICAL_HOST([])
AC_CANONICAL_TARGET([])
AC_CONFIG_SRCDIR([config.h.in])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_MACRO_DIR([m4])
AM_INIT_AUTOMAKE
AM_MAINTAINER_MODE
AM_ENABLE_SHARED
AM_ENABLE_STATIC
# Options
AC_ARG_ENABLE(
[debug],
[AS_HELP_STRING([--enable-debug],[enable debugging code and output])],
,
[enable_debug="no"]
AC_PREFIX_DEFAULT(/usr/local)
if test "x$prefix" = "xNONE"; then
prefix=$ac_default_prefix
ac_configure_args="$ac_configure_args --prefix $prefix"
fi
# Command-line options.
AC_ARG_ENABLE(debug,
AS_HELP_STRING(--enable-debug,enable additional debugging code and
output), ,
enable_debug=no
)
AC_ARG_ENABLE(
[warnings],
[AS_HELP_STRING([--enable-warnings],[enable lots of compiler warnings])],
,
[enable_warnings="no"]
AC_ARG_ENABLE(really-static,
AS_HELP_STRING(--enable-really-static,create static binaries
for the utilities), ,
enable_really_static=no
)
AM_CONDITIONAL(REALLYSTATIC, test "$enable_really_static" = yes)
AC_ARG_ENABLE(warnings,
AS_HELP_STRING(--enable-warnings,enable additional compiler warnings), ,
enable_warnings=no
)
AC_ARG_ENABLE(
[pedantic],
[AS_HELP_STRING([--enable-pedantic],[enable compile pedantic mode])],
,
[enable_pedantic="no"]
)
AC_ARG_ENABLE(
[really-static],
[AS_HELP_STRING([--enable-really-static],[create fully static binaries])],
,
[enable_really_static="no"]
)
AC_ARG_ENABLE(
[mount-helper],
[AS_HELP_STRING([--enable-mount-helper],[install mount helper @<:@default=enabled for linux@:>@])],
,
[
case "${target_os}" in
linux*) enable_mount_helper="yes" ;;
*) enable_mount_helper="no" ;;
esac
]
)
AC_ARG_ENABLE(
[ldscript],
[AS_HELP_STRING([--enable-ldscript],[use ldscript instead of .so symlink])],
,
[enable_ldscript="no"]
)
AC_ARG_ENABLE(
[ldconfig],
[AS_HELP_STRING([--disable-ldconfig],[do not update dynamic linker cache using ldconfig])],
,
[enable_ldconfig="yes"]
)
AC_ARG_ENABLE(
[library],
[AS_HELP_STRING([--disable-library],[do not install libntfs-3g but link it into ntfs-3g])],
,
[enable_library="yes"]
)
AC_ARG_ENABLE(
[mtab],
[AS_HELP_STRING([--disable-mtab],[disable and ignore usage of /etc/mtab])],
,
[enable_mtab="yes"]
)
AC_ARG_ENABLE(
[posix-acls],
[AS_HELP_STRING([--enable-posix-acls],[enable POSIX ACL support])],
,
[enable_posix_acls="no"]
)
AC_ARG_ENABLE(
[xattr-mappings],
[AS_HELP_STRING([--enable-xattr-mappings],[enable system extended attributes mappings])],
,
[enable_xattr_mappings="no"]
)
AC_ARG_ENABLE(
[plugins],
[AS_HELP_STRING([--disable-plugins], [Disable external reparse point
plugins for the ntfs-3g FUSE driver])],
[if test x${enableval} = "xyes"; then disable_plugins="no"; fi],
[disable_plugins="no"]
)
AC_ARG_ENABLE(
[device-default-io-ops],
[AS_HELP_STRING([--disable-device-default-io-ops],[install default IO ops])],
,
[enable_device_default_io_ops="yes"]
)
AC_ARG_ENABLE(
[ntfs-3g],
[AS_HELP_STRING([--disable-ntfs-3g],[disable the ntfs-3g FUSE driver])],
,
[enable_ntfs_3g="yes"]
)
AC_ARG_ENABLE(
[ntfsprogs],
[AS_HELP_STRING([--disable-ntfsprogs],[disable ntfsprogs utilities
(default=no)])],
,
[enable_ntfsprogs="yes"]
)
AC_ARG_ENABLE(crypto,
AS_HELP_STRING(--enable-crypto,enable crypto related code and utilities
(default=no)), ,
enable_crypto=no
)
AC_ARG_ENABLE(
[extras],
[AS_HELP_STRING([--enable-extras],[enable extra ntfsprogs utilities
(default=no)])],
,
[enable_extras="no"]
)
AC_ARG_ENABLE(
[quarantined],
[AS_HELP_STRING([--enable-quarantined],[enable quarantined ntfsprogs utilities
(default=no)])],
,
[enable_quarantined="no"]
)
AC_ARG_ENABLE(
[nfconv],
[AS_HELP_STRING([--disable-nfconv],[disable the 'nfconv' patch, which adds support for Unicode normalization form conversion when built on Mac OS X @<:@default=enabled for Mac OS X@:>@])],
[enable_nfconv="no"],
[
case "${target_os}" in
darwin*) enable_nfconv="yes" ;;
*) enable_nfconv="no" ;;
esac
]
)
# pthread_rwlock_t requires _GNU_SOURCE
# Use GNU extensions if available.
AC_GNU_SOURCE
# Programs
AC_PROG_CC(gcc cc)
AC_PROG_LN_S
AM_PROG_CC_C_O
ifdef(
[LT_INIT],
[LT_INIT],
[AC_PROG_LIBTOOL]
)
# Checks for programs.
AC_PROG_CC
AC_PROG_GCC_TRADITIONAL
AC_PROG_INSTALL
PKG_PROG_PKG_CONFIG
AC_PATH_PROG(RM, rm, rm)
AC_PROG_LN_S
AC_PROG_MAKE_SET
AC_PROG_LIBTOOL
AC_PATH_PROG([MV], [mv])
AC_PATH_PROG([RM], [rm])
AC_PATH_PROG([SED], [sed])
AC_ARG_VAR([LDCONFIG], [ldconfig utility])
AC_PATH_PROG([LDCONFIG], [ldconfig], [true], [/sbin /usr/sbin $PATH])
# Libraries often install their metadata .pc files in directories not searched
# by pkg-config. Let's workaround this.
export PKG_CONFIG_PATH=${PKG_CONFIG_PATH}:/usr/lib/pkgconfig:/opt/gnome/lib/pkgconfig:/usr/share/pkgconfig:/usr/local/lib/pkgconfig:$prefix/lib/pkgconfig:/opt/gnome/share/pkgconfig:/usr/local/share/pkgconfig
# Environment
AC_MSG_CHECKING([Windows OS])
case "${target}" in
*-mingw32*|*-winnt*|*-cygwin*)
AC_MSG_RESULT([yes])
WINDOWS="yes"
AC_DEFINE(
[WINDOWS],
[1],
[Define to 1 if this is a Windows OS]
)
;;
*)
AC_MSG_RESULT([no])
WINDOWS="no"
;;
esac
# Enable large file support.
AC_SYS_LARGEFILE
if test "x${enable_ntfs_3g}" != "xyes"; then
with_fuse="none"
elif test "x${with_fuse}" = "x"; then
AC_MSG_CHECKING([fuse compatibility])
case "${target_os}" in
linux*|solaris*)
AC_ARG_WITH(
[fuse],
[AS_HELP_STRING([--with-fuse=<internal|external>],[Select FUSE library: internal or external @<:@default=internal@:>@])],
,
[with_fuse="internal"]
)
;;
darwin*|netbsd*|kfreebsd*-gnu)
with_fuse="external"
;;
freebsd*)
AC_MSG_ERROR([Please see FreeBSD support at http://www.freshports.org/sysutils/fusefs-ntfs])
;;
*)
AC_MSG_ERROR([ntfs-3g can be built for Linux, FreeBSD, Mac OS X, NetBSD, and Solaris only.])
;;
esac
AC_MSG_RESULT([${with_fuse}])
fi
case "${target_os}" in
solaris*)
if test "x$GCC" != "xyes" ; then
AC_MSG_ERROR([ntfs-3g can be built only with gcc on Solaris. Install it by 'pkg install gcc-dev' and retry.)])
fi
;;
esac
if test "${enable_ldscript}" = "yes"; then
AC_MSG_CHECKING([Output format])
OUTPUT_FORMAT="$(${CC} ${CFLAGS} ${LDFLAGS} -Wl,--verbose 2>&1 | ${SED} -n 's/^OUTPUT_FORMAT("\([[^"]]*\)",.*/\1/p')"
if test -z "${OUTPUT_FORMAT}"; then
AC_MSG_RESULT([None])
else
AC_MSG_RESULT([${OUTPUT_FORMAT}])
OUTPUT_FORMAT="OUTPUT_FORMAT ( ${OUTPUT_FORMAT} )"
fi
fi
# Libraries
if test "${with_fuse}" = "internal"; then
AC_CHECK_LIB(
[pthread],
[pthread_create],
[LIBFUSE_LITE_LIBS="${LIBFUSE_LITE_LIBS} -lpthread"],
[AC_MSG_ERROR([Cannot find pthread library])]
)
AC_DEFINE(
[_REENTRANT],
[1],
[Required define if using POSIX threads]
)
# required so that we re-compile anything
AC_DEFINE(
[FUSE_INTERNAL],
[1],
[Define to 1 if using internal fuse]
)
AC_MSG_CHECKING([Solaris OS])
AC_LANG_PUSH([C])
AC_COMPILE_IFELSE(
[
AC_LANG_SOURCE(
[[#if !((defined(sun) || defined(__sun)) && (defined(__SVR4) || defined(__svr4__)))]]
[[#error "Not a Solaris system."]]
[[#endif]]
)
],
[
AC_MSG_RESULT([yes])
LIBFUSE_LITE_CFLAGS="${LIBFUSE_LITE_CFLAGS} -std=c99 -D__SOLARIS__ -D_XOPEN_SOURCE=600 -D__EXTENSIONS__"
LIBFUSE_LITE_LIBS="${LIBFUSE_LITE_LIBS} -lxnet"
],
[
AC_MSG_RESULT([no])
]
)
AC_LANG_POP([C])
elif test "${with_fuse}" = "external"; then
if test -z "$PKG_CONFIG"; then
AC_PATH_PROG(PKG_CONFIG, pkg-config, no)
fi
test "x${PKG_CONFIG}" = "xno" && AC_MSG_ERROR([pkg-config wasn't found! Please install from your vendor, or see http://pkg-config.freedesktop.org/wiki/])
# Libraries often install their metadata .pc files in directories
# not searched by pkg-config. Let's workaround this.
export PKG_CONFIG_PATH=${PKG_CONFIG_PATH}:/lib/pkgconfig:/usr/lib/pkgconfig:/opt/gnome/lib/pkgconfig:/usr/share/pkgconfig:/usr/local/lib/pkgconfig:$prefix/lib/pkgconfig:/opt/gnome/share/pkgconfig:/usr/local/share/pkgconfig
PKG_CHECK_MODULES(
[FUSE_MODULE],
[fuse >= 2.6.0],
,
[
AC_MSG_ERROR([FUSE >= 2.6.0 was not found. Either older FUSE is still present, or FUSE is not fully installed (e.g. fuse, libfuse, libfuse2, libfuse-dev, etc packages). Source code: http://fuse.sf.net])
]
)
FUSE_LIB_PATH=`$PKG_CONFIG --libs-only-L fuse | sed -e 's,/[/]*,/,g' -e 's,[ ]*$,,'`
fi
# Autodetect whether we can build crypto stuff or not.
compile_crypto=false
if test "$enable_crypto" != "no"; then
have_libgcrypt=false
AM_PATH_LIBGCRYPT(1.2.2, [ have_libgcrypt=true ],
case "$target_os" in
linux*)
PKG_CHECK_MODULES(FUSE_MODULE, fuse >= 2.5.0, [ compile_fuse_module=true ],
[
if test "$enable_crypto" = "yes"; then
AC_MSG_ERROR([ntfsprogs crypto code requires the gcrypt library.])
else
AC_MSG_WARN([ntfsprogs crypto code requires the gcrypt library.])
fi
])
have_libgnutls=false
PKG_CHECK_MODULES(GNUTLS, gnutls >= 1.4.4, [ have_libgnutls=true ],
if test "$enable_crypto" = "yes"; then
AC_MSG_ERROR([ntfsprogs crypto code requires the gnutls library.])
else
AC_MSG_WARN([ntfsprogs crypto code requires the gnutls library.])
fi
)
if test "$have_libgcrypt" = "true"; then
if test "$have_libgnutls" = "true"; then
compile_crypto=true
AC_DEFINE([ENABLE_CRYPTO], 1,
[Define this to 1 if you want to enable support of
encrypted files in libntfs and utilities.])
fi
fi
fi
AM_CONDITIONAL(ENABLE_CRYPTO, $compile_crypto)
AC_MSG_ERROR([ntfs-3g requires FUSE >= 2.5.0. Please see http://fuse.sf.net/ or install __all__ the precompiled fuse packages.])
]);;
*)
AC_MSG_ERROR([ntfs-3g can be built only under Linux.])
;;
esac
# add --with-extra-includes and --with-extra-libs switch to ./configure
all_libraries="$all_libraries $USER_LDFLAGS"
@ -367,165 +95,55 @@ all_includes="$all_includes $USER_INCLUDES"
AC_SUBST(all_includes)
AC_SUBST(all_libraries)
# Specify support for generating DCE compliant UUIDs (aka GUIDs). We check if
# uuid/uuid.h header is present and the uuid library is present that goes with
# it and then check if uuid_generate() is present and usable.
#
# DCE UUIDs are enabled by default and can be disabled with the --disable-uuid
# option to the configure script.
AC_ARG_WITH(uuid, [
--with-uuid@<:@=PFX@:>@ generate DCE compliant UUIDs, with optional prefix
to uuid library and headers @<:@default=detect@:>@
--without-uuid do not generate DCE compliant UUIDs],
if test "$with_uuid" = "yes"; then
extrapath=default
elif test "$with_uuid" = "no"; then
extrapath=
else
extrapath=$with_uuid
fi,
extrapath=default
)
if test "x$extrapath" != "x"; then
if test "x$extrapath" != "xdefault"; then
MKNTFS_CPPFLAGS="$MKNTFS_CPPFLAGS -I$extrapath/include"
MKNTFS_LIBS="$MKNTFS_LIBS -L$extrapath/lib"
fi
# Add our compiler switches not discarding 'CFLAGS' as they may have been
# passed to us by rpmbuild(8).
# We add -Wall to enable some compiler warnings.
CFLAGS="$CFLAGS -Wall"
search_for_luuid="yes"
AC_CHECK_HEADER([uuid/uuid.h],
[],
[
AC_MSG_WARN([ntfsprogs DCE compliant UUID generation code requires the uuid library.])
search_for_luuid="no"
],
)
if test "x$search_for_luuid" != "xno"; then
# Look for uuid_generate in the standard C library.
AC_CHECK_FUNC([uuid_generate],
[
AC_DEFINE([ENABLE_UUID], 1,
[Define this to 1 if you want to enable
generation of DCE compliant UUIDs.])
search_for_luuid="no"
],
[],
)
fi
if test "x$search_for_luuid" != "xno"; then
# Look for uuid_generate in the 'uuid' library.
AC_CHECK_LIB([uuid], [uuid_generate],
[
AC_DEFINE([ENABLE_UUID], 1,
[Define this to 1 if you want to enable
generation of DCE compliant UUIDs.])
MKNTFS_LIBS="$MKNTFS_LIBS -luuid"
search_for_luuid="no"
],
[],
)
fi
if test "x$search_for_luuid" != "xno"; then
AC_MSG_WARN([ntfsprogs DCE compliant UUID generation code requires the uuid library.])
fi
# Add lots of extra warnings if --enable-warnings was specified.
if test "$enable_warnings" = "yes"; then
CFLAGS="$CFLAGS -W -Wall -Waggregate-return -Wbad-function-cast -Wcast-align -Wcast-qual -Wdisabled-optimization -Wdiv-by-zero -Wfloat-equal -Winline -Wmissing-declarations -Wmissing-format-attribute -Wmissing-noreturn -Wmissing-prototypes -Wmultichar -Wnested-externs -Wpointer-arith -Wredundant-decls -Wshadow -Wsign-compare -Wstrict-prototypes -Wundef -Wwrite-strings"
fi
# Specify support for obtaining the correct BIOS legacy geometry needed for
# Windows to boot in CHS mode. We check if hd.h header is present and the hd
# library is present that goes with it and then check if the hd_list() function
# is present and usable.
#
# Using the hd library is enabled by default and can be disabled with the
# --disable-hd option to the configure script.
AC_ARG_WITH(hd, [
--with-hd@<:@=PFX@:>@ use Windows compliant disk geometry, with optional
prefix to hd library and headers @<:@default=detect@:>@
--without-hd do not use Windows compliant disk geometry],
if test "$with_hd" = "yes"; then
extrapath2=default
elif test "$with_hd" = "no"; then
extrapath2=
else
extrapath2=$with_hd
fi,
extrapath2=default
)
if test "x$extrapath2" != "x"; then
if test "x$extrapath2" != "xdefault"; then
LIBNTFS_CPPFLAGS="$LIBNTFS_CPPFLAGS -I$extrapath2/include"
LIBNTFS_LIBS="$LIBNTFS_LIBS -L$extrapath2/lib"
fi
AC_CHECK_HEADER([hd.h],
AC_CHECK_LIB([hd], [hd_list],
AC_DEFINE([ENABLE_HD], 1,
[Define this to 1 if you want to enable use of Windows
compliant disk geometry.])
LIBNTFS_LIBS="$LIBNTFS_LIBS -lhd"
NTFSPROGS_STATIC_LIBS="$NTFSPROGS_STATIC_LIBS -lhd",
AC_MSG_WARN([ntfsprogs Windows compliant geometry code requires the hd library.]),
),
AC_MSG_WARN([ntfsprogs Windows compliant geometry code requires the hd library.]),
)
# Add debugging switches if --enable-debug was specified.
if test "$enable_debug" = "yes"; then
CFLAGS="$CFLAGS -ggdb3 -DDEBUG"
fi
AC_SUBST(CFLAGS)
AC_SUBST(CPPFLAGS)
AC_SUBST(LDFLAGS)
AC_SUBST(LIBS)
AC_SUBST(LIBNTFS_3G_CFLAGS)
AC_SUBST(AUTODIRS)
# Checks for libraries.
# Checks for header files.
AC_HEADER_STDC
AC_HEADER_MAJOR
AC_CHECK_HEADERS([ctype.h fcntl.h libgen.h libintl.h limits.h locale.h \
mntent.h stddef.h stdint.h stdlib.h stdio.h stdarg.h string.h \
strings.h errno.h time.h unistd.h utime.h wchar.h getopt.h features.h \
regex.h endian.h byteswap.h sys/byteorder.h sys/disk.h sys/endian.h \
sys/param.h sys/ioctl.h sys/mount.h sys/stat.h sys/types.h \
sys/vfs.h sys/statvfs.h linux/major.h linux/fd.h \
linux/fs.h inttypes.h linux/hdreg.h \
machine/endian.h windows.h syslog.h pwd.h malloc.h])
endian.h byteswap.h sys/byteorder.h sys/endian.h sys/param.h \
sys/ioctl.h sys/mount.h sys/stat.h sys/types.h sys/vfs.h \
sys/statvfs.h sys/sysmacros.h linux/major.h linux/fd.h linux/hdreg.h \
machine/endian.h gcrypt.h windows.h gnutls/pkcs12.h syslog.h])
# Checks for typedefs, structures, and compiler characteristics.
AC_HEADER_STDBOOL
AC_C_BIGENDIAN(
,
[
AC_DEFINE(
[WORDS_LITTLEENDIAN],
[1],
[Define to 1 if your processor stores words with the least significant
byte first (like Intel and VAX, unlike Motorola and SPARC).]
)
]
,
)
AC_C_BIGENDIAN(,
[AC_DEFINE([WORDS_LITTLEENDIAN], 1,
[Define to 1 if your processor stores words with the least significant
byte first (like Intel and VAX, unlike Motorola and SPARC).])]
,)
AC_C_CONST
AC_C_INLINE
AC_TYPE_OFF_T
AC_TYPE_SIZE_T
AC_STRUCT_ST_BLOCKS
AC_CHECK_MEMBERS([struct stat.st_rdev])
AC_CHECK_MEMBERS([struct stat.st_atim])
AC_CHECK_MEMBERS([struct stat.st_atimespec])
AC_CHECK_MEMBERS([struct stat.st_atimensec])
# For the 'nfconv' patch (Mac OS X only):
case "${target_os}" in
darwin*)
if test "${enable_nfconv}" = "yes"; then
AC_CHECK_HEADER(
[CoreFoundation/CoreFoundation.h],
[
LDFLAGS="${LDFLAGS} -framework CoreFoundation"
AC_DEFINE(
[ENABLE_NFCONV],
[1],
[Define to 1 if the nfconv patch should be enabled]
)
],
AC_MSG_ERROR([[Cannot find CoreFoundation required for 'nfconv' functionality Mac OS X. You may use the --disable-nfconv 'configure' option to avoid this error.]])
)
fi
;;
esac
# Checks for library functions.
AC_FUNC_GETMNTENT
@ -535,174 +153,17 @@ AC_FUNC_STAT
AC_FUNC_STRFTIME
AC_FUNC_UTIME_NULL
AC_FUNC_VPRINTF
AC_CHECK_FUNCS([ \
atexit basename daemon dup2 fdatasync ffs getopt_long hasmntopt \
mbsinit memmove memset realpath regcomp setlocale setxattr \
strcasecmp strchr strdup strerror strnlen strsep strtol strtoul \
sysconf utime utimensat gettimeofday clock_gettime fork memcpy random snprintf \
])
AC_SYS_LARGEFILE
AC_CHECK_FUNCS([atexit basename dup2 fdatasync getopt_long hasmntopt mbsinit \
memmove memset realpath regcomp setlocale setxattr strcasecmp strchr \
strdup strerror strnlen strtol strtoul sysconf utime])
# The dlopen API might be in libc or in libdl. Check libc first, then
# fall back to libdl.
LIBDL=""
if test "x${disable_plugins}" = "xno"; then
AC_CHECK_LIB(c, dlopen, ,
[AC_CHECK_LIB(dl, dlopen, [LIBDL="-ldl"],
[AC_MSG_ERROR(["Unable to find libdl (required for external plugin support)"])])])
fi
AC_SUBST([LIBDL])
if test "$GCC" = "yes" ; then
# We add -Wall to enable some compiler warnings.
CFLAGS="${CFLAGS} -Wall"
fi
if test "${enable_pedantic}" = "yes"; then
enable_warnings="yes"
CFLAGS="${CFLAGS} -pedantic"
fi
if test "${enable_warnings}" = "yes"; then
CFLAGS="${CFLAGS} -W -Wall -Waggregate-return -Wbad-function-cast -Wcast-align -Wcast-qual -Wdisabled-optimization -Wdiv-by-zero -Wfloat-equal -Winline -Wmissing-declarations -Wmissing-format-attribute -Wmissing-noreturn -Wmissing-prototypes -Wmultichar -Wnested-externs -Wpointer-arith -Wredundant-decls -Wshadow -Wsign-compare -Wstrict-prototypes -Wundef -Wwrite-strings -Wformat -Wformat-security -Wuninitialized"
fi
if test "${enable_debug}" = "yes"; then
CFLAGS="${CFLAGS} -ggdb3 -DDEBUG"
AC_DEFINE(
[ENABLE_DEBUG],
[1],
[Define to 1 if debug should be enabled]
)
fi
test "${enable_device_default_io_ops}" = "no" && AC_DEFINE(
[NO_NTFS_DEVICE_DEFAULT_IO_OPS],
[1],
[Don't use default IO ops]
)
test "${enable_mtab}" = "no" && AC_DEFINE([IGNORE_MTAB], [1], [Don't update /etc/mtab])
test "${enable_posix_acls}" != "no" && AC_DEFINE([POSIXACLS], [1], [POSIX ACL support])
test "${enable_xattr_mappings}" != "no" && AC_DEFINE([XATTR_MAPPINGS], [1], [system extended attributes mappings])
test "${disable_plugins}" != "no" && AC_DEFINE([DISABLE_PLUGINS], [1], [Define to 1 for disabling reparse plugins])
test "${enable_really_static}" = "yes" && enable_library="no"
test "${enable_library}" = "no" && enable_ldconfig="no"
if test "x${DISTCHECK_HACK}" != "x"; then
enable_mount_helper="no"
enable_ldconfig="no"
fi
# Settings
pkgconfigdir="\$(libdir)/pkgconfig"
ntfs3gincludedir="\$(includedir)/ntfs-3g"
# Executables should be installed to the root filesystem, otherwise
# automounting NTFS volumes can fail during boot if the driver binaries
# and their dependencies are on an unmounted partition. Use --exec-prefix
# to override this.
if test "x${exec_prefix}" = "xNONE"; then
rootbindir="/bin"
rootsbindir="/sbin"
rootlibdir="/lib${libdir##*/lib}"
else
rootbindir="\$(bindir)"
rootsbindir="\$(sbindir)"
rootlibdir="\$(libdir)"
fi
AC_SUBST([pkgconfigdir])
AC_SUBST([ntfs3gincludedir])
AC_SUBST([rootbindir])
AC_SUBST([rootsbindir])
AC_SUBST([rootlibdir])
AC_SUBST([LIBNTFS_3G_VERSION])
AC_SUBST([LIBFUSE_LITE_CFLAGS])
AC_SUBST([LIBFUSE_LITE_LIBS])
AC_SUBST([MKNTFS_CPPFLAGS])
AC_SUBST([MKNTFS_LIBS])
AC_SUBST([LIBNTFS_CPPFLAGS])
AC_SUBST([LIBNTFS_LIBS])
AC_SUBST([NTFSPROGS_STATIC_LIBS])
AC_SUBST([OUTPUT_FORMAT])
AM_CONDITIONAL([FUSE_INTERNAL], [test "${with_fuse}" = "internal"])
AM_CONDITIONAL([GENERATE_LDSCRIPT], [test "${enable_ldscript}" = "yes"])
AM_CONDITIONAL([WINDOWS], [test "${WINDOWS}" = "yes"])
AM_CONDITIONAL([NTFS_DEVICE_DEFAULT_IO_OPS], [test "${enable_device_default_io_ops}" = "yes"])
AM_CONDITIONAL([RUN_LDCONFIG], [test "${enable_ldconfig}" = "yes"])
AM_CONDITIONAL([REALLYSTATIC], [test "${enable_really_static}" = "yes"])
AM_CONDITIONAL([INSTALL_LIBRARY], [test "${enable_library}" = "yes"])
AM_CONDITIONAL([ENABLE_MOUNT_HELPER], [test "${enable_mount_helper}" = "yes"])
AM_CONDITIONAL([ENABLE_NTFS_3G], [test "${enable_ntfs_3g}" = "yes"])
AM_CONDITIONAL([ENABLE_NTFSPROGS], [test "${enable_ntfsprogs}" = "yes"])
AM_CONDITIONAL([ENABLE_EXTRAS], [test "${enable_extras}" = "yes"])
AM_CONDITIONAL([ENABLE_QUARANTINED], [test "${enable_quarantined}" = "yes"])
AM_CONDITIONAL([DISABLE_PLUGINS], [test "${disable_plugins}" != "no"])
# workaround for <autoconf-2.60
if test -z "${docdir}"; then
docdir="\$(datarootdir)/doc/\$(PACKAGE_NAME)"
AC_SUBST([docdir])
fi
# workaround for <automake-1.10
if test -z "${MKDIR_P}"; then
MKDIR_P="\$(mkdir_p)"
AC_SUBST([MKDIR_P])
fi
# generate files
# Makefiles to be created by configure.
AC_CONFIG_FILES([
Makefile
include/Makefile
include/fuse-lite/Makefile
include/ntfs-3g/Makefile
libfuse-lite/Makefile
libntfs-3g/Makefile
libntfs-3g/libntfs-3g.pc
libntfs-3g/libntfs-3g.script.so
ntfsprogs/Makefile
ntfsprogs/mkntfs.8
ntfsprogs/ntfscat.8
ntfsprogs/ntfsclone.8
ntfsprogs/ntfscluster.8
ntfsprogs/ntfscmp.8
ntfsprogs/ntfscp.8
ntfsprogs/ntfsfix.8
ntfsprogs/ntfsinfo.8
ntfsprogs/ntfslabel.8
ntfsprogs/ntfsls.8
ntfsprogs/ntfsprogs.8
ntfsprogs/ntfsresize.8
ntfsprogs/ntfsundelete.8
ntfsprogs/ntfsdecrypt.8
ntfsprogs/ntfswipe.8
ntfsprogs/ntfstruncate.8
ntfsprogs/ntfsfallocate.8
ntfsprogs/ntfsrecover.8
ntfsprogs/ntfsusermap.8
ntfsprogs/ntfssecaudit.8
src/Makefile
src/ntfs-3g.8
src/ntfs-3g.probe.8
])
AC_OUTPUT
if test "${with_fuse}" = "external"; then
if ! echo "x$FUSE_LIB_PATH" | grep -- "x-L/lib" > /dev/null; then
cat <<EOF
****************************************************************************
* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING *
* The FUSE user space binaries were NOT installed with root directory *
* executable prefix. This means that automounting NTFS volumes during boot *
* could fail. This can be fixed the below way by reinstalling FUSE using *
* the right 'configure' option during FUSE compilation: *
* ./configure --exec-prefix=/ *
* make && sudo make install *
* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING *
****************************************************************************
EOF
fi
fi
echo "You can type now 'make' to build ntfs-3g."

View File

@ -1,4 +1,3 @@
SUBDIRS = ntfs-3g
MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
SUBDIRS = ntfs-3g fuse-lite
MAINTAINERCLEANFILES = Makefile.in

View File

@ -1,10 +0,0 @@
MAINTAINERCLEANFILES = Makefile.in
noinst_HEADERS = \
fuse.h \
fuse_common.h \
fuse_lowlevel.h \
fuse_lowlevel_compat.h \
fuse_opt.h \
fuse_kernel.h

View File

@ -1,697 +0,0 @@
/*
FUSE: Filesystem in Userspace
Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
This program can be distributed under the terms of the GNU LGPLv2.
See the file COPYING.LIB.
*/
#ifndef _FUSE_H_
#define _FUSE_H_
/** @file
*
* This file defines the library interface of FUSE
*/
#include "fuse_common.h"
#include <fcntl.h>
#include <time.h>
#include <utime.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
#ifdef __cplusplus
extern "C" {
#endif
/* ----------------------------------------------------------- *
* Basic FUSE API *
* ----------------------------------------------------------- */
/** Handle for a FUSE filesystem */
struct fuse;
/** Structure containing a raw command */
struct fuse_cmd;
/** Function to add an entry in a readdir() operation
*
* @param buf the buffer passed to the readdir() operation
* @param name the file name of the directory entry
* @param stat file attributes, can be NULL
* @param off offset of the next entry or zero
* @return 1 if buffer is full, zero otherwise
*/
typedef int (*fuse_fill_dir_t) (void *buf, const char *name,
const struct stat *stbuf, off_t off);
/**
* The file system operations:
*
* Most of these should work very similarly to the well known UNIX
* file system operations. A major exception is that instead of
* returning an error in 'errno', the operation should return the
* negated error value (-errno) directly.
*
* All methods are optional, but some are essential for a useful
* filesystem (e.g. getattr). Open, flush, release, fsync, opendir,
* releasedir, fsyncdir, access, create, ftruncate, fgetattr, lock,
* init and destroy are special purpose methods, without which a full
* featured filesystem can still be implemented.
*
* Almost all operations take a path which can be of any length.
*
* Changed in fuse 2.8.0 (regardless of API version)
* Previously, paths were limited to a length of PATH_MAX.
*/
struct fuse_operations {
/** Get file attributes.
*
* Similar to stat(). The 'st_dev' and 'st_blksize' fields are
* ignored. The 'st_ino' field is ignored except if the 'use_ino'
* mount option is given.
*/
int (*getattr) (const char *, struct stat *);
/** Read the target of a symbolic link
*
* The buffer should be filled with a null terminated string. The
* buffer size argument includes the space for the terminating
* null character. If the linkname is too long to fit in the
* buffer, it should be truncated. The return value should be 0
* for success.
*/
int (*readlink) (const char *, char *, size_t);
/** Create a file node
*
* This is called for creation of all non-directory, non-symlink
* nodes. If the filesystem defines a create() method, then for
* regular files that will be called instead.
*/
int (*mknod) (const char *, mode_t, dev_t);
/** Create a directory
*
* Note that the mode argument may not have the type specification
* bits set, i.e. S_ISDIR(mode) can be false. To obtain the
* correct directory type bits use mode|S_IFDIR
* */
int (*mkdir) (const char *, mode_t);
/** Remove a file */
int (*unlink) (const char *);
/** Remove a directory */
int (*rmdir) (const char *);
/** Create a symbolic link */
int (*symlink) (const char *, const char *);
/** Rename a file */
int (*rename) (const char *, const char *);
/** Create a hard link to a file */
int (*link) (const char *, const char *);
/** Change the permission bits of a file */
int (*chmod) (const char *, mode_t);
/** Change the owner and group of a file */
int (*chown) (const char *, uid_t, gid_t);
/** Change the size of a file */
int (*truncate) (const char *, off_t);
/** Change the access and/or modification times of a file
*
* Deprecated, use utimens() instead.
*/
int (*utime) (const char *, struct utimbuf *);
/** File open operation
*
* No creation (O_CREAT, O_EXCL) and by default also no
* truncation (O_TRUNC) flags will be passed to open(). If an
* application specifies O_TRUNC, fuse first calls truncate()
* and then open(). Only if 'atomic_o_trunc' has been
* specified and kernel version is 2.6.24 or later, O_TRUNC is
* passed on to open.
*
* Unless the 'default_permissions' mount option is given,
* open should check if the operation is permitted for the
* given flags. Optionally open may also return an arbitrary
* filehandle in the fuse_file_info structure, which will be
* passed to all file operations.
*
* Changed in version 2.2
*/
int (*open) (const char *, struct fuse_file_info *);
/** Read data from an open file
*
* Read should return exactly the number of bytes requested except
* on EOF or error, otherwise the rest of the data will be
* substituted with zeroes. An exception to this is when the
* 'direct_io' mount option is specified, in which case the return
* value of the read system call will reflect the return value of
* this operation.
*
* Changed in version 2.2
*/
int (*read) (const char *, char *, size_t, off_t,
struct fuse_file_info *);
/** Write data to an open file
*
* Write should return exactly the number of bytes requested
* except on error. An exception to this is when the 'direct_io'
* mount option is specified (see read operation).
*
* Changed in version 2.2
*/
int (*write) (const char *, const char *, size_t, off_t,
struct fuse_file_info *);
/** Get file system statistics
*
* The 'f_frsize', 'f_favail', 'f_fsid' and 'f_flag' fields are ignored
*
* Replaced 'struct statfs' parameter with 'struct statvfs' in
* version 2.5
*/
int (*statfs) (const char *, struct statvfs *);
/** Possibly flush cached data
*
* BIG NOTE: This is not equivalent to fsync(). It's not a
* request to sync dirty data.
*
* Flush is called on each close() of a file descriptor. So if a
* filesystem wants to return write errors in close() and the file
* has cached dirty data, this is a good place to write back data
* and return any errors. Since many applications ignore close()
* errors this is not always useful.
*
* NOTE: The flush() method may be called more than once for each
* open(). This happens if more than one file descriptor refers
* to an opened file due to dup(), dup2() or fork() calls. It is
* not possible to determine if a flush is final, so each flush
* should be treated equally. Multiple write-flush sequences are
* relatively rare, so this shouldn't be a problem.
*
* Filesystems shouldn't assume that flush will always be called
* after some writes, or that if will be called at all.
*
* Changed in version 2.2
*/
int (*flush) (const char *, struct fuse_file_info *);
/** Release an open file
*
* Release is called when there are no more references to an open
* file: all file descriptors are closed and all memory mappings
* are unmapped.
*
* For every open() call there will be exactly one release() call
* with the same flags and file descriptor. It is possible to
* have a file opened more than once, in which case only the last
* release will mean, that no more reads/writes will happen on the
* file. The return value of release is ignored.
*
* Changed in version 2.2
*/
int (*release) (const char *, struct fuse_file_info *);
/** Synchronize file contents
*
* If the datasync parameter is non-zero, then only the user data
* should be flushed, not the meta data.
*
* Changed in version 2.2
*/
int (*fsync) (const char *, int, struct fuse_file_info *);
/** Set extended attributes */
int (*setxattr) (const char *, const char *, const char *, size_t, int);
/** Get extended attributes */
int (*getxattr) (const char *, const char *, char *, size_t);
/** List extended attributes */
int (*listxattr) (const char *, char *, size_t);
/** Remove extended attributes */
int (*removexattr) (const char *, const char *);
/** Open directory
*
* This method should check if the open operation is permitted for
* this directory
*
* Introduced in version 2.3
*/
int (*opendir) (const char *, struct fuse_file_info *);
/** Read directory
*
* The filesystem may choose between two modes of operation:
*
* 1) The readdir implementation ignores the offset parameter, and
* passes zero to the filler function's offset. The filler
* function will not return '1' (unless an error happens), so the
* whole directory is read in a single readdir operation.
*
* 2) The readdir implementation keeps track of the offsets of the
* directory entries. It uses the offset parameter and always
* passes non-zero offset to the filler function. When the buffer
* is full (or an error happens) the filler function will return
* '1'.
*
* Introduced in version 2.3
*/
int (*readdir) (const char *, void *, fuse_fill_dir_t, off_t,
struct fuse_file_info *);
/** Release directory
*
* Introduced in version 2.3
*/
int (*releasedir) (const char *, struct fuse_file_info *);
/** Synchronize directory contents
*
* If the datasync parameter is non-zero, then only the user data
* should be flushed, not the meta data
*
* Introduced in version 2.3
*/
int (*fsyncdir) (const char *, int, struct fuse_file_info *);
/**
* Initialize filesystem
*
* The return value will passed in the private_data field of
* fuse_context to all file operations and as a parameter to the
* destroy() method.
*
* Introduced in version 2.3
* Changed in version 2.6
*/
void *(*init) (struct fuse_conn_info *conn);
/**
* Clean up filesystem
*
* Called on filesystem exit.
*
* Introduced in version 2.3
*/
void (*destroy) (void *);
/**
* Check file access permissions
*
* This will be called for the access() system call. If the
* 'default_permissions' mount option is given, this method is not
* called.
*
* This method is not called under Linux kernel versions 2.4.x
*
* Introduced in version 2.5
*/
int (*access) (const char *, int);
/**
* Create and open a file
*
* If the file does not exist, first create it with the specified
* mode, and then open it.
*
* If this method is not implemented or under Linux kernel
* versions earlier than 2.6.15, the mknod() and open() methods
* will be called instead.
*
* Introduced in version 2.5
*/
int (*create) (const char *, mode_t, struct fuse_file_info *);
/**
* Change the size of an open file
*
* This method is called instead of the truncate() method if the
* truncation was invoked from an ftruncate() system call.
*
* If this method is not implemented or under Linux kernel
* versions earlier than 2.6.15, the truncate() method will be
* called instead.
*
* Introduced in version 2.5
*/
int (*ftruncate) (const char *, off_t, struct fuse_file_info *);
/**
* Get attributes from an open file
*
* This method is called instead of the getattr() method if the
* file information is available.
*
* Currently this is only called after the create() method if that
* is implemented (see above). Later it may be called for
* invocations of fstat() too.
*
* Introduced in version 2.5
*/
int (*fgetattr) (const char *, struct stat *, struct fuse_file_info *);
/**
* Perform POSIX file locking operation
*
* The cmd argument will be either F_GETLK, F_SETLK or F_SETLKW.
*
* For the meaning of fields in 'struct flock' see the man page
* for fcntl(2). The l_whence field will always be set to
* SEEK_SET.
*
* For checking lock ownership, the 'fuse_file_info->owner'
* argument must be used.
*
* For F_GETLK operation, the library will first check currently
* held locks, and if a conflicting lock is found it will return
* information without calling this method. This ensures, that
* for local locks the l_pid field is correctly filled in. The
* results may not be accurate in case of race conditions and in
* the presence of hard links, but it's unlikly that an
* application would rely on accurate GETLK results in these
* cases. If a conflicting lock is not found, this method will be
* called, and the filesystem may fill out l_pid by a meaningful
* value, or it may leave this field zero.
*
* For F_SETLK and F_SETLKW the l_pid field will be set to the pid
* of the process performing the locking operation.
*
* Note: if this method is not implemented, the kernel will still
* allow file locking to work locally. Hence it is only
* interesting for network filesystems and similar.
*
* Introduced in version 2.6
*/
int (*lock) (const char *, struct fuse_file_info *, int cmd,
struct flock *);
/**
* Change the access and modification times of a file with
* nanosecond resolution
*
* Introduced in version 2.6
*/
int (*utimens) (const char *, const struct timespec tv[2]);
/**
* Map block index within file to block index within device
*
* Note: This makes sense only for block device backed filesystems
* mounted with the 'blkdev' option
*
* Introduced in version 2.6
*/
int (*bmap) (const char *, size_t blocksize, uint64_t *idx);
/**
* Ioctl
*
* flags will have FUSE_IOCTL_COMPAT set for 32bit ioctls in
* 64bit environment. The size and direction of data is
* determined by _IOC_*() decoding of cmd. For _IOC_NONE,
* data will be NULL, for _IOC_WRITE data is out area, for
* _IOC_READ in area and if both are set in/out area. In all
* non-NULL cases, the area is of _IOC_SIZE(cmd) bytes.
*
* Introduced in version 2.8
*
* Note : the unsigned long request submitted by the application
* is truncated to 32 bits, and forwarded as a signed int.
*/
int (*ioctl) (const char *, int cmd, void *arg,
struct fuse_file_info *, unsigned int flags, void *data);
/*
* The flags below have been discarded, they should not be used
*/
unsigned int flag_nullpath_ok : 1;
/**
* Reserved flags, don't set
*/
unsigned int flag_reserved : 30;
};
/** Extra context that may be needed by some filesystems
*
* The uid, gid and pid fields are not filled in case of a writepage
* operation.
*/
struct fuse_context {
/** Pointer to the fuse object */
struct fuse *fuse;
/** User ID of the calling process */
uid_t uid;
/** Group ID of the calling process */
gid_t gid;
/** Thread ID of the calling process */
pid_t pid;
/** Private filesystem data */
void *private_data;
/** Umask of the calling process (introduced in version 2.8) */
mode_t umask;
};
/* ----------------------------------------------------------- *
* More detailed API *
* ----------------------------------------------------------- */
/**
* Create a new FUSE filesystem.
*
* @param ch the communication channel
* @param args argument vector
* @param op the filesystem operations
* @param op_size the size of the fuse_operations structure
* @param user_data user data supplied in the context during the init() method
* @return the created FUSE handle
*/
struct fuse *fuse_new(struct fuse_chan *ch, struct fuse_args *args,
const struct fuse_operations *op, size_t op_size,
void *user_data);
/**
* Destroy the FUSE handle.
*
* The communication channel attached to the handle is also destroyed.
*
* NOTE: This function does not unmount the filesystem. If this is
* needed, call fuse_unmount() before calling this function.
*
* @param f the FUSE handle
*/
void fuse_destroy(struct fuse *f);
/**
* FUSE event loop.
*
* Requests from the kernel are processed, and the appropriate
* operations are called.
*
* @param f the FUSE handle
* @return 0 if no error occurred, -1 otherwise
*/
int fuse_loop(struct fuse *f);
/**
* Exit from event loop
*
* @param f the FUSE handle
*/
void fuse_exit(struct fuse *f);
/**
* Get the current context
*
* The context is only valid for the duration of a filesystem
* operation, and thus must not be stored and used later.
*
* @return the context
*/
struct fuse_context *fuse_get_context(void);
/**
* Check if a request has already been interrupted
*
* @param req request handle
* @return 1 if the request has been interrupted, 0 otherwise
*/
int fuse_interrupted(void);
/*
* Stacking API
*/
/**
* Fuse filesystem object
*
* This is opaque object represents a filesystem layer
*/
struct fuse_fs;
/*
* These functions call the relevant filesystem operation, and return
* the result.
*
* If the operation is not defined, they return -ENOSYS, with the
* exception of fuse_fs_open, fuse_fs_release, fuse_fs_opendir,
* fuse_fs_releasedir and fuse_fs_statfs, which return 0.
*/
int fuse_fs_getattr(struct fuse_fs *fs, const char *path, struct stat *buf);
int fuse_fs_fgetattr(struct fuse_fs *fs, const char *path, struct stat *buf,
struct fuse_file_info *fi);
int fuse_fs_rename(struct fuse_fs *fs, const char *oldpath,
const char *newpath);
int fuse_fs_unlink(struct fuse_fs *fs, const char *path);
int fuse_fs_rmdir(struct fuse_fs *fs, const char *path);
int fuse_fs_symlink(struct fuse_fs *fs, const char *linkname,
const char *path);
int fuse_fs_link(struct fuse_fs *fs, const char *oldpath, const char *newpath);
int fuse_fs_release(struct fuse_fs *fs, const char *path,
struct fuse_file_info *fi);
int fuse_fs_open(struct fuse_fs *fs, const char *path,
struct fuse_file_info *fi);
int fuse_fs_read(struct fuse_fs *fs, const char *path, char *buf, size_t size,
off_t off, struct fuse_file_info *fi);
int fuse_fs_write(struct fuse_fs *fs, const char *path, const char *buf,
size_t size, off_t off, struct fuse_file_info *fi);
int fuse_fs_fsync(struct fuse_fs *fs, const char *path, int datasync,
struct fuse_file_info *fi);
int fuse_fs_flush(struct fuse_fs *fs, const char *path,
struct fuse_file_info *fi);
int fuse_fs_statfs(struct fuse_fs *fs, const char *path, struct statvfs *buf);
int fuse_fs_opendir(struct fuse_fs *fs, const char *path,
struct fuse_file_info *fi);
int fuse_fs_readdir(struct fuse_fs *fs, const char *path, void *buf,
fuse_fill_dir_t filler, off_t off,
struct fuse_file_info *fi);
int fuse_fs_fsyncdir(struct fuse_fs *fs, const char *path, int datasync,
struct fuse_file_info *fi);
int fuse_fs_releasedir(struct fuse_fs *fs, const char *path,
struct fuse_file_info *fi);
int fuse_fs_create(struct fuse_fs *fs, const char *path, mode_t mode,
struct fuse_file_info *fi);
int fuse_fs_lock(struct fuse_fs *fs, const char *path,
struct fuse_file_info *fi, int cmd, struct flock *lock);
int fuse_fs_chmod(struct fuse_fs *fs, const char *path, mode_t mode);
int fuse_fs_chown(struct fuse_fs *fs, const char *path, uid_t uid, gid_t gid);
int fuse_fs_truncate(struct fuse_fs *fs, const char *path, off_t size);
int fuse_fs_ftruncate(struct fuse_fs *fs, const char *path, off_t size,
struct fuse_file_info *fi);
int fuse_fs_utimens(struct fuse_fs *fs, const char *path,
const struct timespec tv[2]);
int fuse_fs_access(struct fuse_fs *fs, const char *path, int mask);
int fuse_fs_readlink(struct fuse_fs *fs, const char *path, char *buf,
size_t len);
int fuse_fs_mknod(struct fuse_fs *fs, const char *path, mode_t mode,
dev_t rdev);
int fuse_fs_mkdir(struct fuse_fs *fs, const char *path, mode_t mode);
int fuse_fs_setxattr(struct fuse_fs *fs, const char *path, const char *name,
const char *value, size_t size, int flags);
int fuse_fs_getxattr(struct fuse_fs *fs, const char *path, const char *name,
char *value, size_t size);
int fuse_fs_listxattr(struct fuse_fs *fs, const char *path, char *list,
size_t size);
int fuse_fs_removexattr(struct fuse_fs *fs, const char *path,
const char *name);
int fuse_fs_bmap(struct fuse_fs *fs, const char *path, size_t blocksize,
uint64_t *idx);
int fuse_fs_ioctl(struct fuse_fs *fs, const char *path, int cmd, void *arg,
struct fuse_file_info *fi, unsigned int flags, void *data);
void fuse_fs_init(struct fuse_fs *fs, struct fuse_conn_info *conn);
void fuse_fs_destroy(struct fuse_fs *fs);
/**
* Create a new fuse filesystem object
*
* This is usually called from the factory of a fuse module to create
* a new instance of a filesystem.
*
* @param op the filesystem operations
* @param op_size the size of the fuse_operations structure
* @param user_data user data supplied in the context during the init() method
* @return a new filesystem object
*/
struct fuse_fs *fuse_fs_new(const struct fuse_operations *op, size_t op_size,
void *user_data);
#ifdef __SOLARIS__
/**
* Filesystem module
*
* Filesystem modules are registered with the FUSE_REGISTER_MODULE()
* macro.
*
* If the "-omodules=modname:..." option is present, filesystem
* objects are created and pushed onto the stack with the 'factory'
* function.
*/
struct fuse_module {
/**
* Name of filesystem
*/
const char *name;
/**
* Factory for creating filesystem objects
*
* The function may use and remove options from 'args' that belong
* to this module.
*
* For now the 'fs' vector always contains exactly one filesystem.
* This is the filesystem which will be below the newly created
* filesystem in the stack.
*
* @param args the command line arguments
* @param fs NULL terminated filesystem object vector
* @return the new filesystem object
*/
struct fuse_fs *(*factory)(struct fuse_args *args, struct fuse_fs *fs[]);
struct fuse_module *next;
struct fusemod_so *so;
int ctr;
};
#endif /* __SOLARIS__ */
/* ----------------------------------------------------------- *
* Advanced API for event handling, don't worry about this... *
* ----------------------------------------------------------- */
/* NOTE: the following functions are deprecated, and will be removed
from the 3.0 API. Use the lowlevel session functions instead */
/** Get session from fuse object */
struct fuse_session *fuse_get_session(struct fuse *f);
#ifdef __cplusplus
}
#endif
#endif /* _FUSE_H_ */

View File

@ -1,246 +0,0 @@
/*
FUSE: Filesystem in Userspace
Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
This program can be distributed under the terms of the GNU LGPLv2.
See the file COPYING.LIB.
*/
/** @file */
#if !defined(_FUSE_H_) && !defined(_FUSE_LOWLEVEL_H_)
#error "Never include <fuse_common.h> directly; use <fuse.h> or <fuse_lowlevel.h> instead."
#endif
#ifndef _FUSE_COMMON_H_
#define _FUSE_COMMON_H_
#include "fuse_opt.h"
#include <stdio.h> /* temporary */
#include <stdint.h>
/** Major version of FUSE library interface */
#define FUSE_MAJOR_VERSION 2
/** Minor version of FUSE library interface */
#ifdef POSIXACLS
#define FUSE_MINOR_VERSION 8
#else
#define FUSE_MINOR_VERSION 7
#endif
#define FUSE_MAKE_VERSION(maj, min) ((maj) * 10 + (min))
#define FUSE_VERSION FUSE_MAKE_VERSION(FUSE_MAJOR_VERSION, FUSE_MINOR_VERSION)
/* This interface uses 64 bit off_t */
#if defined(__SOLARIS__) && !defined(__x86_64__) && (_FILE_OFFSET_BITS != 64)
#error Please add -D_FILE_OFFSET_BITS=64 to your compile flags!
#endif
#ifdef __cplusplus
extern "C" {
#endif
#ifdef POSIXACLS
/*
* FUSE_CAP_DONT_MASK: don't apply umask to file mode on create operations
* FUSE_CAP_POSIX_ACL: process Posix ACLs within the kernel
*/
#define FUSE_CAP_DONT_MASK (1 << 6)
#define FUSE_CAP_POSIX_ACL (1 << 18)
#endif
#define FUSE_CAP_BIG_WRITES (1 << 5)
#define FUSE_CAP_IOCTL_DIR (1 << 11)
/**
* Ioctl flags
*
* FUSE_IOCTL_COMPAT: 32bit compat ioctl on 64bit machine
* FUSE_IOCTL_UNRESTRICTED: not restricted to well-formed ioctls, retry allowed
* FUSE_IOCTL_RETRY: retry with new iovecs
* FUSE_IOCTL_DIR: is a directory
*/
#define FUSE_IOCTL_COMPAT (1 << 0)
#define FUSE_IOCTL_UNRESTRICTED (1 << 1)
#define FUSE_IOCTL_RETRY (1 << 2)
#define FUSE_IOCTL_DIR (1 << 4)
#define FUSE_IOCTL_MAX_IOV 256
/**
* Information about open files
*
* Changed in version 2.5
*/
struct fuse_file_info {
/** Open flags. Available in open() and release() */
int flags;
/** Old file handle, don't use */
unsigned long fh_old;
/** In case of a write operation indicates if this was caused by a
writepage */
int writepage;
/** Can be filled in by open, to use direct I/O on this file.
Introduced in version 2.4 */
unsigned int direct_io : 1;
/** Can be filled in by open, to indicate, that cached file data
need not be invalidated. Introduced in version 2.4 */
unsigned int keep_cache : 1;
/** Indicates a flush operation. Set in flush operation, also
maybe set in highlevel lock operation and lowlevel release
operation. Introduced in version 2.6 */
unsigned int flush : 1;
/** Padding. Do not use*/
unsigned int padding : 29;
/** File handle. May be filled in by filesystem in open().
Available in all other file operations */
uint64_t fh;
/** Lock owner id. Available in locking operations and flush */
uint64_t lock_owner;
};
/**
* Connection information, passed to the ->init() method
*
* Some of the elements are read-write, these can be changed to
* indicate the value requested by the filesystem. The requested
* value must usually be smaller than the indicated value.
*/
struct fuse_conn_info {
/**
* Major version of the protocol (read-only)
*/
unsigned proto_major;
/**
* Minor version of the protocol (read-only)
*/
unsigned proto_minor;
/**
* Is asynchronous read supported (read-write)
*/
unsigned async_read;
/**
* Maximum size of the write buffer
*/
unsigned max_write;
/**
* Maximum readahead
*/
unsigned max_readahead;
unsigned capable;
unsigned want;
/**
* For future use.
*/
unsigned reserved[25];
};
struct fuse_session;
struct fuse_chan;
/**
* Create a FUSE mountpoint
*
* Returns a control file descriptor suitable for passing to
* fuse_new()
*
* @param mountpoint the mount point path
* @param args argument vector
* @return the communication channel on success, NULL on failure
*/
struct fuse_chan *fuse_mount(const char *mountpoint, struct fuse_args *args);
/**
* Umount a FUSE mountpoint
*
* @param mountpoint the mount point path
* @param ch the communication channel
*/
void fuse_unmount(const char *mountpoint, struct fuse_chan *ch);
#ifdef __SOLARIS__
/**
* Parse common options
*
* The following options are parsed:
*
* '-f' foreground
* '-d' '-odebug' foreground, but keep the debug option
* '-s' single threaded
* '-h' '--help' help
* '-ho' help without header
* '-ofsname=..' file system name, if not present, then set to the program
* name
*
* All parameters may be NULL
*
* @param args argument vector
* @param mountpoint the returned mountpoint, should be freed after use
* @param multithreaded set to 1 unless the '-s' option is present
* @param foreground set to 1 if one of the relevant options is present
* @return 0 on success, -1 on failure
*/
int fuse_parse_cmdline(struct fuse_args *args, char **mountpoint,
int *multithreaded, int *foreground);
/**
* Go into the background
*
* @param foreground if true, stay in the foreground
* @return 0 on success, -1 on failure
*/
int fuse_daemonize(int foreground);
#endif /* __SOLARIS__ */
/**
* Get the version of the library
*
* @return the version
*/
int fuse_version(void);
/* ----------------------------------------------------------- *
* Signal handling *
* ----------------------------------------------------------- */
/**
* Exit session on HUP, TERM and INT signals and ignore PIPE signal
*
* Stores session in a global variable. May only be called once per
* process until fuse_remove_signal_handlers() is called.
*
* @param se the session to exit
* @return 0 on success, -1 on failure
*/
int fuse_set_signal_handlers(struct fuse_session *se);
/**
* Restore default signal handlers
*
* Resets global session. After this fuse_set_signal_handlers() may
* be called again.
*
* @param se the same session as given in fuse_set_signal_handlers()
*/
void fuse_remove_signal_handlers(struct fuse_session *se);
#ifdef __cplusplus
}
#endif
#endif /* _FUSE_COMMON_H_ */

View File

@ -1,441 +0,0 @@
/*
This file defines the kernel interface of FUSE
Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
This program can be distributed under the terms of the GNU GPL.
See the file COPYING.
This -- and only this -- header file may also be distributed under
the terms of the BSD Licence as follows:
Copyright (C) 2001-2007 Miklos Szeredi. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
*
* 7.12
* - add umask flag to input argument of open, mknod and mkdir
*/
#ifndef linux
#include <sys/types.h>
#define __u64 uint64_t
#define __u32 uint32_t
#define __s32 int32_t
#else
#include <asm/types.h>
#include <linux/major.h>
#endif
/** Version number of this interface */
#define FUSE_KERNEL_VERSION 7
/** Minor version number of this interface
* We introduce ourself as 7.18 (Posix ACLS : 7.12, IOCTL_DIR : 7.18)
* and we expect features features defined for 7.18, but not implemented
* here to not be triggered by ntfs-3g.
*/
#define FUSE_KERNEL_MINOR_VERSION 18
/*
* For binary compatibility with old kernels we accept falling back
* to 7.12 or earlier maximum version supported by the kernel
*/
#define FUSE_KERNEL_MAJOR_FALLBACK 7
#define FUSE_KERNEL_MINOR_FALLBACK 12
/** The node ID of the root inode */
#define FUSE_ROOT_ID 1
/** The major number of the fuse character device */
#define FUSE_MAJOR MISC_MAJOR
/** The minor number of the fuse character device */
#define FUSE_MINOR 229
/* Make sure all structures are padded to 64bit boundary, so 32bit
userspace works under 64bit kernels */
struct fuse_attr {
__u64 ino;
__u64 size;
__u64 blocks;
__u64 atime;
__u64 mtime;
__u64 ctime;
__u32 atimensec;
__u32 mtimensec;
__u32 ctimensec;
__u32 mode;
__u32 nlink;
__u32 uid;
__u32 gid;
__u32 rdev;
__u64 filling; /* JPA needed for minor >= 12, but meaning unknown */
};
struct fuse_kstatfs {
__u64 blocks;
__u64 bfree;
__u64 bavail;
__u64 files;
__u64 ffree;
__u32 bsize;
__u32 namelen;
__u32 frsize;
__u32 padding;
__u32 spare[6];
};
struct fuse_file_lock {
__u64 start;
__u64 end;
__u32 type;
__u32 pid; /* tgid */
};
/**
* Bitmasks for fuse_setattr_in.valid
*/
#define FATTR_MODE (1 << 0)
#define FATTR_UID (1 << 1)
#define FATTR_GID (1 << 2)
#define FATTR_SIZE (1 << 3)
#define FATTR_ATIME (1 << 4)
#define FATTR_MTIME (1 << 5)
#define FATTR_FH (1 << 6)
/**
* Flags returned by the OPEN request
*
* FOPEN_DIRECT_IO: bypass page cache for this open file
* FOPEN_KEEP_CACHE: don't invalidate the data cache on open
*/
#define FOPEN_DIRECT_IO (1 << 0)
#define FOPEN_KEEP_CACHE (1 << 1)
/**
* INIT request/reply flags
* FUSE_BIG_WRITES: allow big writes to be issued to the file system
* FUSE_DONT_MASK: don't apply umask to file mode on create operations
* FUSE_HAS_IOCTL_DIR: kernel supports ioctl on directories
* FUSE_POSIX_ACL: kernel supports Posix ACLs
*/
#define FUSE_ASYNC_READ (1 << 0)
#define FUSE_POSIX_LOCKS (1 << 1)
#define FUSE_BIG_WRITES (1 << 5)
#define FUSE_DONT_MASK (1 << 6)
#define FUSE_HAS_IOCTL_DIR (1 << 11)
#define FUSE_POSIX_ACL (1 << 19)
/**
* Release flags
*/
#define FUSE_RELEASE_FLUSH (1 << 0)
enum fuse_opcode {
FUSE_LOOKUP = 1,
FUSE_FORGET = 2, /* no reply */
FUSE_GETATTR = 3,
FUSE_SETATTR = 4,
FUSE_READLINK = 5,
FUSE_SYMLINK = 6,
FUSE_MKNOD = 8,
FUSE_MKDIR = 9,
FUSE_UNLINK = 10,
FUSE_RMDIR = 11,
FUSE_RENAME = 12,
FUSE_LINK = 13,
FUSE_OPEN = 14,
FUSE_READ = 15,
FUSE_WRITE = 16,
FUSE_STATFS = 17,
FUSE_RELEASE = 18,
FUSE_FSYNC = 20,
FUSE_SETXATTR = 21,
FUSE_GETXATTR = 22,
FUSE_LISTXATTR = 23,
FUSE_REMOVEXATTR = 24,
FUSE_FLUSH = 25,
FUSE_INIT = 26,
FUSE_OPENDIR = 27,
FUSE_READDIR = 28,
FUSE_RELEASEDIR = 29,
FUSE_FSYNCDIR = 30,
FUSE_GETLK = 31,
FUSE_SETLK = 32,
FUSE_SETLKW = 33,
FUSE_ACCESS = 34,
FUSE_CREATE = 35,
FUSE_INTERRUPT = 36,
FUSE_BMAP = 37,
FUSE_DESTROY = 38,
FUSE_IOCTL = 39,
};
/* The read buffer is required to be at least 8k, but may be much larger */
#define FUSE_MIN_READ_BUFFER 8192
#define FUSE_COMPAT_ENTRY_OUT_SIZE 120 /* JPA */
struct fuse_entry_out {
__u64 nodeid; /* Inode ID */
__u64 generation; /* Inode generation: nodeid:gen must
be unique for the fs's lifetime */
__u64 entry_valid; /* Cache timeout for the name */
__u64 attr_valid; /* Cache timeout for the attributes */
__u32 entry_valid_nsec;
__u32 attr_valid_nsec;
struct fuse_attr attr;
};
struct fuse_forget_in {
__u64 nlookup;
};
#define FUSE_COMPAT_FUSE_ATTR_OUT_SIZE 96 /* JPA */
struct fuse_attr_out {
__u64 attr_valid; /* Cache timeout for the attributes */
__u32 attr_valid_nsec;
__u32 dummy;
struct fuse_attr attr;
};
#define FUSE_COMPAT_MKNOD_IN_SIZE 8
struct fuse_mknod_in {
__u32 mode;
__u32 rdev;
__u32 umask;
__u32 padding;
};
struct fuse_mkdir_in {
__u32 mode;
__u32 umask;
};
struct fuse_rename_in {
__u64 newdir;
};
struct fuse_link_in {
__u64 oldnodeid;
};
struct fuse_setattr_in {
__u32 valid;
__u32 padding;
__u64 fh;
__u64 size;
__u64 unused1;
__u64 atime;
__u64 mtime;
__u64 unused2;
__u32 atimensec;
__u32 mtimensec;
__u32 unused3;
__u32 mode;
__u32 unused4;
__u32 uid;
__u32 gid;
__u32 unused5;
};
struct fuse_open_in {
__u32 flags;
__u32 mode; /* unused for protocol < 7.12 */
};
struct fuse_create_in {
__u32 flags;
__u32 mode;
__u32 umask;
__u32 padding;
};
struct fuse_open_out {
__u64 fh;
__u32 open_flags;
__u32 padding;
};
struct fuse_release_in {
__u64 fh;
__u32 flags;
__u32 release_flags;
__u64 lock_owner;
};
struct fuse_flush_in {
__u64 fh;
__u32 unused;
__u32 padding;
__u64 lock_owner;
};
struct fuse_read_in {
__u64 fh;
__u64 offset;
__u32 size;
__u32 padding;
};
#define FUSE_COMPAT_WRITE_IN_SIZE 24 /* JPA */
struct fuse_write_in {
__u64 fh;
__u64 offset;
__u32 size;
__u32 write_flags;
__u64 lock_owner; /* JPA */
__u32 flags; /* JPA */
__u32 padding; /* JPA */
};
struct fuse_write_out {
__u32 size;
__u32 padding;
};
#define FUSE_COMPAT_STATFS_SIZE 48
struct fuse_statfs_out {
struct fuse_kstatfs st;
};
struct fuse_fsync_in {
__u64 fh;
__u32 fsync_flags;
__u32 padding;
};
struct fuse_setxattr_in {
__u32 size;
__u32 flags;
};
struct fuse_getxattr_in {
__u32 size;
__u32 padding;
};
struct fuse_getxattr_out {
__u32 size;
__u32 padding;
};
struct fuse_lk_in {
__u64 fh;
__u64 owner;
struct fuse_file_lock lk;
};
struct fuse_lk_out {
struct fuse_file_lock lk;
};
struct fuse_access_in {
__u32 mask;
__u32 padding;
};
struct fuse_init_in {
__u32 major;
__u32 minor;
__u32 max_readahead;
__u32 flags;
};
struct fuse_init_out {
__u32 major;
__u32 minor;
__u32 max_readahead;
__u32 flags;
__u32 unused;
__u32 max_write;
};
struct fuse_interrupt_in {
__u64 unique;
};
struct fuse_bmap_in {
__u64 block;
__u32 blocksize;
__u32 padding;
};
struct fuse_bmap_out {
__u64 block;
};
struct fuse_ioctl_in {
__u64 fh;
__u32 flags;
__u32 cmd;
__u64 arg;
__u32 in_size;
__u32 out_size;
};
struct fuse_ioctl_iovec {
__u64 base;
__u64 len;
};
struct fuse_ioctl_out {
__s32 result;
__u32 flags;
__u32 in_iovs;
__u32 out_iovs;
};
struct fuse_in_header {
__u32 len;
__u32 opcode;
__u64 unique;
__u64 nodeid;
__u32 uid;
__u32 gid;
__u32 pid;
__u32 padding;
};
struct fuse_out_header {
__u32 len;
__s32 error;
__u64 unique;
};
struct fuse_dirent {
__u64 ino;
__u64 off;
__u32 namelen;
__u32 type;
char name[0];
};
#define FUSE_NAME_OFFSET offsetof(struct fuse_dirent, name)
#define FUSE_DIRENT_ALIGN(x) (((x) + sizeof(__u64) - 1) & ~(sizeof(__u64) - 1))
#define FUSE_DIRENT_SIZE(d) \
FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET + (d)->namelen)

File diff suppressed because it is too large Load Diff

View File

@ -1,16 +0,0 @@
/*
FUSE: Filesystem in Userspace
Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
This program can be distributed under the terms of the GNU LGPLv2.
See the file COPYING.LIB.
*/
/* these definitions provide source compatibility to prior versions.
Do not include this file directly! */
size_t fuse_dirent_size(size_t namelen);
char *fuse_add_dirent(char *buf, const char *name, const struct stat *stbuf,
off_t off);

View File

@ -1,261 +0,0 @@
/*
FUSE: Filesystem in Userspace
Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
This program can be distributed under the terms of the GNU LGPLv2.
See the file COPYING.LIB.
*/
#ifndef _FUSE_OPT_H_
#define _FUSE_OPT_H_
/** @file
*
* This file defines the option parsing interface of FUSE
*/
#ifdef __cplusplus
extern "C" {
#endif
/**
* Option description
*
* This structure describes a single option, and and action associated
* with it, in case it matches.
*
* More than one such match may occur, in which case the action for
* each match is executed.
*
* There are three possible actions in case of a match:
*
* i) An integer (int or unsigned) variable determined by 'offset' is
* set to 'value'
*
* ii) The processing function is called, with 'value' as the key
*
* iii) An integer (any) or string (char *) variable determined by
* 'offset' is set to the value of an option parameter
*
* 'offset' should normally be either set to
*
* - 'offsetof(struct foo, member)' actions i) and iii)
*
* - -1 action ii)
*
* The 'offsetof()' macro is defined in the <stddef.h> header.
*
* The template determines which options match, and also have an
* effect on the action. Normally the action is either i) or ii), but
* if a format is present in the template, then action iii) is
* performed.
*
* The types of templates are:
*
* 1) "-x", "-foo", "--foo", "--foo-bar", etc. These match only
* themselves. Invalid values are "--" and anything beginning
* with "-o"
*
* 2) "foo", "foo-bar", etc. These match "-ofoo", "-ofoo-bar" or
* the relevant option in a comma separated option list
*
* 3) "bar=", "--foo=", etc. These are variations of 1) and 2)
* which have a parameter
*
* 4) "bar=%s", "--foo=%lu", etc. Same matching as above but perform
* action iii).
*
* 5) "-x ", etc. Matches either "-xparam" or "-x param" as
* two separate arguments
*
* 6) "-x %s", etc. Combination of 4) and 5)
*
* If the format is "%s", memory is allocated for the string unlike
* with scanf().
*/
struct fuse_opt {
/** Matching template and optional parameter formatting */
const char *templ;
/**
* Offset of variable within 'data' parameter of fuse_opt_parse()
* or -1
*/
unsigned long offset;
/**
* Value to set the variable to, or to be passed as 'key' to the
* processing function. Ignored if template has a format
*/
int value;
};
/**
* Key option. In case of a match, the processing function will be
* called with the specified key.
*/
#define FUSE_OPT_KEY(templ, key) { templ, -1U, key }
/**
* Last option. An array of 'struct fuse_opt' must end with a NULL
* template value
*/
#define FUSE_OPT_END { .templ = NULL }
/**
* Argument list
*/
struct fuse_args {
/** Argument count */
int argc;
/** Argument vector. NULL terminated */
char **argv;
/** Is 'argv' allocated? */
int allocated;
};
/**
* Initializer for 'struct fuse_args'
*/
#define FUSE_ARGS_INIT(argc, argv) { argc, argv, 0 }
/**
* Key value passed to the processing function if an option did not
* match any template
*/
#define FUSE_OPT_KEY_OPT -1
/**
* Key value passed to the processing function for all non-options
*
* Non-options are the arguments beginning with a charater other than
* '-' or all arguments after the special '--' option
*/
#define FUSE_OPT_KEY_NONOPT -2
/**
* Special key value for options to keep
*
* Argument is not passed to processing function, but behave as if the
* processing function returned 1
*/
#define FUSE_OPT_KEY_KEEP -3
/**
* Special key value for options to discard
*
* Argument is not passed to processing function, but behave as if the
* processing function returned zero
*/
#define FUSE_OPT_KEY_DISCARD -4
/**
* Processing function
*
* This function is called if
* - option did not match any 'struct fuse_opt'
* - argument is a non-option
* - option did match and offset was set to -1
*
* The 'arg' parameter will always contain the whole argument or
* option including the parameter if exists. A two-argument option
* ("-x foo") is always converted to single arguemnt option of the
* form "-xfoo" before this function is called.
*
* Options of the form '-ofoo' are passed to this function without the
* '-o' prefix.
*
* The return value of this function determines whether this argument
* is to be inserted into the output argument vector, or discarded.
*
* @param data is the user data passed to the fuse_opt_parse() function
* @param arg is the whole argument or option
* @param key determines why the processing function was called
* @param outargs the current output argument list
* @return -1 on error, 0 if arg is to be discarded, 1 if arg should be kept
*/
typedef int (*fuse_opt_proc_t)(void *data, const char *arg, int key,
struct fuse_args *outargs);
/**
* Option parsing function
*
* If 'args' was returned from a previous call to fuse_opt_parse() or
* it was constructed from
*
* A NULL 'args' is equivalent to an empty argument vector
*
* A NULL 'opts' is equivalent to an 'opts' array containing a single
* end marker
*
* A NULL 'proc' is equivalent to a processing function always
* returning '1'
*
* @param args is the input and output argument list
* @param data is the user data
* @param opts is the option description array
* @param proc is the processing function
* @return -1 on error, 0 on success
*/
int fuse_opt_parse(struct fuse_args *args, void *data,
const struct fuse_opt opts[], fuse_opt_proc_t proc);
/**
* Add an option to a comma separated option list
*
* @param opts is a pointer to an option list, may point to a NULL value
* @param opt is the option to add
* @return -1 on allocation error, 0 on success
*/
int fuse_opt_add_opt(char **opts, const char *opt);
/**
* Add an argument to a NULL terminated argument vector
*
* @param args is the structure containing the current argument list
* @param arg is the new argument to add
* @return -1 on allocation error, 0 on success
*/
int fuse_opt_add_arg(struct fuse_args *args, const char *arg);
/**
* Add an argument at the specified position in a NULL terminated
* argument vector
*
* Adds the argument to the N-th position. This is useful for adding
* options at the beggining of the array which must not come after the
* special '--' option.
*
* @param args is the structure containing the current argument list
* @param pos is the position at which to add the argument
* @param arg is the new argument to add
* @return -1 on allocation error, 0 on success
*/
int fuse_opt_insert_arg(struct fuse_args *args, int pos, const char *arg);
/**
* Free the contents of argument list
*
* The structure itself is not freed
*
* @param args is the structure containing the argument list
*/
void fuse_opt_free_args(struct fuse_args *args);
/**
* Check if an option matches
*
* @param opts is the option description array
* @param opt is the option to match
* @return 1 if a match is found, 0 if not
*/
int fuse_opt_match(const struct fuse_opt opts[], const char *opt);
#ifdef __cplusplus
}
#endif
#endif /* _FUSE_OPT_H_ */

View File

@ -1,50 +1,34 @@
MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
headers = \
acls.h \
attrib.h \
attrlist.h \
bitmap.h \
bootsect.h \
cache.h \
collate.h \
compat.h \
compress.h \
debug.h \
device.h \
device_io.h \
dir.h \
ea.h \
efs.h \
endians.h \
index.h \
inode.h \
ioctl.h \
layout.h \
lcnalloc.h \
logfile.h \
logging.h \
mft.h \
misc.h \
mst.h \
ntfstime.h \
object_id.h \
param.h \
plugin.h \
realpath.h \
reparse.h \
runlist.h \
security.h \
support.h \
types.h \
unistr.h \
volume.h \
xattrs.h
if INSTALL_LIBRARY
ntfs3ginclude_HEADERS = $(headers)
else
noinst_HEADERS = $(headers)
endif
linux_ntfsincludedir = $(includedir)/ntfs-3g
linux_ntfsinclude_HEADERS = \
attrib.h \
attrlist.h \
bitmap.h \
bootsect.h \
collate.h \
compat.h \
compress.h \
debug.h \
device.h \
device_io.h \
dir.h \
endians.h \
index.h \
inode.h \
layout.h \
lcnalloc.h \
list.h \
logfile.h \
logging.h \
mft.h \
mst.h \
ntfstime.h \
runlist.h \
security.h \
support.h \
types.h \
unistr.h \
version.h \
volume.h
MAINTAINERCLEANFILES = Makefile.in

View File

@ -1,184 +0,0 @@
/*
*
* Copyright (c) 2007-2008 Jean-Pierre Andre
*
*/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program (in the main directory of the NTFS-3G
* distribution in the file COPYING); if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef ACLS_H
#define ACLS_H
#include "endians.h"
/*
* JPA configuration modes for security.c / acls.c
* should be moved to some config file
*/
#define BUFSZ 1024 /* buffer size to read mapping file */
#define MAPPINGFILE ".NTFS-3G/UserMapping" /* default mapping file */
#define LINESZ 120 /* maximum useful size of a mapping line */
#define CACHE_PERMISSIONS_BITS 6 /* log2 of unitary allocation of permissions */
#define CACHE_PERMISSIONS_SIZE 262144 /* max cacheable permissions */
/*
* Matching of ntfs permissions to Linux permissions
* these constants are adapted to endianness
* when setting, set them all
* when checking, check one is present
*/
/* flags which are set to mean exec, write or read */
#define FILE_READ (FILE_READ_DATA)
#define FILE_WRITE (FILE_WRITE_DATA | FILE_APPEND_DATA \
| READ_CONTROL | FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA)
#define FILE_EXEC (FILE_EXECUTE)
#define DIR_READ FILE_LIST_DIRECTORY
#define DIR_WRITE (FILE_ADD_FILE | FILE_ADD_SUBDIRECTORY | FILE_DELETE_CHILD \
| READ_CONTROL | FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA)
#define DIR_EXEC (FILE_TRAVERSE)
/* flags tested for meaning exec, write or read */
/* tests for write allow for interpretation of a sticky bit */
#define FILE_GREAD (FILE_READ_DATA | GENERIC_READ)
#define FILE_GWRITE (FILE_WRITE_DATA | FILE_APPEND_DATA | GENERIC_WRITE)
#define FILE_GEXEC (FILE_EXECUTE | GENERIC_EXECUTE)
#define DIR_GREAD (FILE_LIST_DIRECTORY | GENERIC_READ)
#define DIR_GWRITE (FILE_ADD_FILE | FILE_ADD_SUBDIRECTORY | GENERIC_WRITE)
#define DIR_GEXEC (FILE_TRAVERSE | GENERIC_EXECUTE)
/* standard owner (and administrator) rights */
#define OWNER_RIGHTS (DELETE | READ_CONTROL | WRITE_DAC | WRITE_OWNER \
| SYNCHRONIZE \
| FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES \
| FILE_READ_EA | FILE_WRITE_EA)
/* standard world rights */
#define WORLD_RIGHTS (READ_CONTROL | FILE_READ_ATTRIBUTES | FILE_READ_EA \
| SYNCHRONIZE)
/* inheritance flags for files and directories */
#define FILE_INHERITANCE NO_PROPAGATE_INHERIT_ACE
#define DIR_INHERITANCE (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE)
/*
* To identify NTFS ACL meaning Posix ACL granted to root
* we use rights always granted to anybody, so they have no impact
* either on Windows or on Linux.
*/
#define ROOT_OWNER_UNMARK SYNCHRONIZE /* ACL granted to root as owner */
#define ROOT_GROUP_UNMARK FILE_READ_EA /* ACL granted to root as group */
/*
* Maximum SID size and a type large enough to hold it
*/
#define MAX_SID_SIZE (8 + SID_MAX_SUB_AUTHORITIES*4)
typedef char BIGSID[MAX_SID_SIZE];
/*
* Struct to hold the input mapping file
* (private to this module)
*/
struct MAPLIST {
struct MAPLIST *next;
char *uidstr; /* uid text from the same record */
char *gidstr; /* gid text from the same record */
char *sidstr; /* sid text from the same record */
char maptext[LINESZ + 1];
};
typedef int (*FILEREADER)(void *fileid, char *buf, size_t size, off_t pos);
/*
* Constants defined in acls.c
*/
extern const SID *adminsid;
extern const SID *worldsid;
/*
* Functions defined in acls.c
*/
BOOL ntfs_valid_descr(const char *securattr, unsigned int attrsz);
BOOL ntfs_valid_pattern(const SID *sid);
BOOL ntfs_valid_sid(const SID *sid);
BOOL ntfs_same_sid(const SID *first, const SID *second);
BOOL ntfs_is_user_sid(const SID *usid);
int ntfs_sid_size(const SID * sid);
unsigned int ntfs_attr_size(const char *attr);
const SID *ntfs_find_usid(const struct MAPPING *usermapping,
uid_t uid, SID *pdefsid);
const SID *ntfs_find_gsid(const struct MAPPING *groupmapping,
gid_t gid, SID *pdefsid);
uid_t ntfs_find_user(const struct MAPPING *usermapping, const SID *usid);
gid_t ntfs_find_group(const struct MAPPING *groupmapping, const SID * gsid);
const SID *ntfs_acl_owner(const char *secattr);
#if POSIXACLS
BOOL ntfs_valid_posix(const struct POSIX_SECURITY *pxdesc);
void ntfs_sort_posix(struct POSIX_SECURITY *pxdesc);
int ntfs_merge_mode_posix(struct POSIX_SECURITY *pxdesc, mode_t mode);
struct POSIX_SECURITY *ntfs_build_inherited_posix(
const struct POSIX_SECURITY *pxdesc, mode_t mode,
mode_t umask, BOOL isdir);
struct POSIX_SECURITY *ntfs_build_basic_posix(
const struct POSIX_SECURITY *pxdesc, mode_t mode,
mode_t umask, BOOL isdir);
struct POSIX_SECURITY *ntfs_replace_acl(const struct POSIX_SECURITY *oldpxdesc,
const struct POSIX_ACL *newacl, int count, BOOL deflt);
struct POSIX_SECURITY *ntfs_build_permissions_posix(
struct MAPPING* const mapping[],
const char *securattr,
const SID *usid, const SID *gsid, BOOL isdir);
struct POSIX_SECURITY *ntfs_merge_descr_posix(const struct POSIX_SECURITY *first,
const struct POSIX_SECURITY *second);
char *ntfs_build_descr_posix(struct MAPPING* const mapping[],
struct POSIX_SECURITY *pxdesc,
int isdir, const SID *usid, const SID *gsid);
#endif /* POSIXACLS */
int ntfs_inherit_acl(const ACL *oldacl, ACL *newacl,
const SID *usid, const SID *gsid,
BOOL fordir, le16 inherited);
int ntfs_build_permissions(const char *securattr,
const SID *usid, const SID *gsid, BOOL isdir);
char *ntfs_build_descr(mode_t mode,
int isdir, const SID * usid, const SID * gsid);
struct MAPLIST *ntfs_read_mapping(FILEREADER reader, void *fileid);
struct MAPPING *ntfs_do_user_mapping(struct MAPLIST *firstitem);
struct MAPPING *ntfs_do_group_mapping(struct MAPLIST *firstitem);
void ntfs_free_mapping(struct MAPPING *mapping[]);
#endif /* ACLS_H */

View File

@ -3,8 +3,7 @@
*
* Copyright (c) 2000-2004 Anton Altaparmakov
* Copyright (c) 2004-2005 Yura Pakhuchiy
* Copyright (c) 2006-2007 Szabolcs Szakacsits
* Copyright (c) 2010 Jean-Pierre Andre
* Copyright (c) 2006 Szabolcs Szakacsits
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
@ -38,10 +37,6 @@ typedef struct _ntfs_attr_search_ctx ntfs_attr_search_ctx;
#include "logging.h"
extern ntfschar AT_UNNAMED[];
extern ntfschar STREAM_SDS[];
/* The little endian Unicode string $TXF_DATA as a global constant. */
extern ntfschar TXF_DATA[10];
/**
* enum ntfs_lcn_special_values - special return values for ntfs_*_vcn_to_lcn()
@ -58,13 +53,6 @@ typedef enum {
LCN_EIO = -5,
} ntfs_lcn_special_values;
typedef enum { /* ways of processing holes when expanding */
HOLES_NO,
HOLES_OK,
HOLES_DELAY,
HOLES_NONRES
} hole_type;
/**
* struct ntfs_attr_search_ctx - search context used in attribute search functions
* @mrec: buffer containing mft record to search
@ -104,8 +92,6 @@ extern int ntfs_attr_lookup(const ATTR_TYPES type, const ntfschar *name,
const VCN lowest_vcn, const u8 *val, const u32 val_len,
ntfs_attr_search_ctx *ctx);
extern int ntfs_attr_position(const ATTR_TYPES type, ntfs_attr_search_ctx *ctx);
extern ATTR_DEF *ntfs_attr_find_in_attrdef(const ntfs_volume *vol,
const ATTR_TYPES type);
@ -186,7 +172,6 @@ struct _ntfs_attr {
runlist_element *rl;
ntfs_inode *ni;
ATTR_TYPES type;
ATTR_FLAGS data_flags;
ntfschar *name;
u32 name_len;
unsigned long state;
@ -197,21 +182,14 @@ struct _ntfs_attr {
u32 compression_block_size;
u8 compression_block_size_bits;
u8 compression_block_clusters;
s8 unused_runs; /* pre-reserved entries available */
};
/**
* enum ntfs_attr_state_bits - bits for the state field in the ntfs_attr
* structure
* enum ntfs_attr_state_bits - bits for the state field in the ntfs_attr structure
*/
typedef enum {
NA_Initialized, /* 1: structure is initialized. */
NA_NonResident, /* 1: Attribute is not resident. */
NA_BeingNonResident, /* 1: Attribute is being made not resident. */
NA_FullyMapped, /* 1: Attribute has been fully mapped */
NA_DataAppending, /* 1: Attribute is being appended to */
NA_ComprClosing, /* 1: Compressed attribute is being closed */
NA_RunlistDirty, /* 1: Runlist has been updated */
} ntfs_attr_state_bits;
#define test_nattr_flag(na, flag) test_bit(NA_##flag, (na)->state)
@ -226,35 +204,30 @@ typedef enum {
#define NAttrSetNonResident(na) set_nattr_flag(na, NonResident)
#define NAttrClearNonResident(na) clear_nattr_flag(na, NonResident)
#define NAttrBeingNonResident(na) test_nattr_flag(na, BeingNonResident)
#define NAttrSetBeingNonResident(na) set_nattr_flag(na, BeingNonResident)
#define NAttrClearBeingNonResident(na) clear_nattr_flag(na, BeingNonResident)
#define GenNAttrIno(func_name,flag) \
static inline int NAttr##func_name(ntfs_attr *na) \
{ \
if (na->type == AT_DATA && na->name == AT_UNNAMED) \
return (na->ni->flags & FILE_ATTR_##flag); \
return 0; \
} \
static inline void NAttrSet##func_name(ntfs_attr *na) \
{ \
if (na->type == AT_DATA && na->name == AT_UNNAMED) \
na->ni->flags |= FILE_ATTR_##flag; \
else \
ntfs_log_trace("BUG! Should be called only for "\
"unnamed data attribute.\n"); \
} \
static inline void NAttrClear##func_name(ntfs_attr *na) \
{ \
if (na->type == AT_DATA && na->name == AT_UNNAMED) \
na->ni->flags &= ~FILE_ATTR_##flag; \
}
#define NAttrFullyMapped(na) test_nattr_flag(na, FullyMapped)
#define NAttrSetFullyMapped(na) set_nattr_flag(na, FullyMapped)
#define NAttrClearFullyMapped(na) clear_nattr_flag(na, FullyMapped)
#define NAttrDataAppending(na) test_nattr_flag(na, DataAppending)
#define NAttrSetDataAppending(na) set_nattr_flag(na, DataAppending)
#define NAttrClearDataAppending(na) clear_nattr_flag(na, DataAppending)
#define NAttrRunlistDirty(na) test_nattr_flag(na, RunlistDirty)
#define NAttrSetRunlistDirty(na) set_nattr_flag(na, RunlistDirty)
#define NAttrClearRunlistDirty(na) clear_nattr_flag(na, RunlistDirty)
#define NAttrComprClosing(na) test_nattr_flag(na, ComprClosing)
#define NAttrSetComprClosing(na) set_nattr_flag(na, ComprClosing)
#define NAttrClearComprClosing(na) clear_nattr_flag(na, ComprClosing)
#define GenNAttrIno(func_name, flag) \
extern int NAttr##func_name(ntfs_attr *na); \
extern void NAttrSet##func_name(ntfs_attr *na); \
extern void NAttrClear##func_name(ntfs_attr *na);
GenNAttrIno(Compressed, FILE_ATTR_COMPRESSED)
GenNAttrIno(Encrypted, FILE_ATTR_ENCRYPTED)
GenNAttrIno(Sparse, FILE_ATTR_SPARSE_FILE)
#undef GenNAttrIno
GenNAttrIno(Compressed, COMPRESSED)
GenNAttrIno(Encrypted, ENCRYPTED)
GenNAttrIno(Sparse, SPARSE_FILE)
/**
* union attr_val - Union of all known attribute values
@ -284,14 +257,11 @@ typedef union {
} attr_val;
extern void ntfs_attr_init(ntfs_attr *na, const BOOL non_resident,
const ATTR_FLAGS data_flags, const BOOL encrypted,
const BOOL sparse,
const BOOL compressed, const BOOL encrypted, const BOOL sparse,
const s64 allocated_size, const s64 data_size,
const s64 initialized_size, const s64 compressed_size,
const u8 compression_unit);
/* warning : in the following "name" has to be freeable */
/* or one of constants AT_UNNAMED, NTFS_INDEX_I30 or STREAM_SDS */
extern ntfs_attr *ntfs_attr_open(ntfs_inode *ni, const ATTR_TYPES type,
ntfschar *name, u32 name_len);
extern void ntfs_attr_close(ntfs_attr *na);
@ -300,7 +270,6 @@ extern s64 ntfs_attr_pread(ntfs_attr *na, const s64 pos, s64 count,
void *b);
extern s64 ntfs_attr_pwrite(ntfs_attr *na, const s64 pos, s64 count,
const void *b);
extern int ntfs_attr_pclose(ntfs_attr *na);
extern void *ntfs_attr_readall(ntfs_inode *ni, const ATTR_TYPES type,
ntfschar *name, u32 name_len, s64 *data_size);
@ -318,26 +287,23 @@ extern runlist_element *ntfs_attr_find_vcn(ntfs_attr *na, const VCN vcn);
extern int ntfs_attr_size_bounds_check(const ntfs_volume *vol,
const ATTR_TYPES type, const s64 size);
extern int ntfs_attr_can_be_non_resident(const ntfs_volume *vol,
const ATTR_TYPES type);
extern int ntfs_attr_can_be_resident(const ntfs_volume *vol,
const ATTR_TYPES type);
int ntfs_attr_make_non_resident(ntfs_attr *na,
ntfs_attr_search_ctx *ctx);
int ntfs_attr_force_non_resident(ntfs_attr *na);
extern int ntfs_make_room_for_attr(MFT_RECORD *m, u8 *pos, u32 size);
extern int ntfs_resident_attr_record_add(ntfs_inode *ni, ATTR_TYPES type,
const ntfschar *name, u8 name_len, const u8 *val, u32 size,
ntfschar *name, u8 name_len, u8 *val, u32 size,
ATTR_FLAGS flags);
extern int ntfs_non_resident_attr_record_add(ntfs_inode *ni, ATTR_TYPES type,
const ntfschar *name, u8 name_len, VCN lowest_vcn,
int dataruns_size, ATTR_FLAGS flags);
ntfschar *name, u8 name_len, VCN lowest_vcn, int dataruns_size,
ATTR_FLAGS flags);
extern int ntfs_attr_record_rm(ntfs_attr_search_ctx *ctx);
extern int ntfs_attr_add(ntfs_inode *ni, ATTR_TYPES type,
ntfschar *name, u8 name_len, const u8 *val, s64 size);
extern int ntfs_attr_set_flags(ntfs_inode *ni, ATTR_TYPES type,
const ntfschar *name, u8 name_len, ATTR_FLAGS flags,
ATTR_FLAGS mask);
ntfschar *name, u8 name_len, u8 *val, s64 size);
extern int ntfs_attr_rm(ntfs_attr *na);
extern int ntfs_attr_record_resize(MFT_RECORD *m, ATTR_RECORD *a, u32 new_size);
@ -351,8 +317,8 @@ extern int ntfs_attr_record_move_away(ntfs_attr_search_ctx *ctx, int extra);
extern int ntfs_attr_update_mapping_pairs(ntfs_attr *na, VCN from_vcn);
extern int ntfs_attr_truncate(ntfs_attr *na, const s64 newsize);
extern int ntfs_attr_truncate_solid(ntfs_attr *na, const s64 newsize);
// FIXME / TODO: Above here the file is cleaned up. (AIA)
/**
* get_attribute_value_length - return the length of the value of an attribute
* @a: pointer to a buffer containing the attribute record
@ -364,7 +330,7 @@ extern int ntfs_attr_truncate_solid(ntfs_attr *na, const s64 newsize);
*
* FIXME: Describe possible errnos.
*/
extern s64 ntfs_get_attribute_value_length(const ATTR_RECORD *a);
s64 ntfs_get_attribute_value_length(const ATTR_RECORD *a);
/**
* get_attribute_value - return the attribute value of an attribute
@ -380,25 +346,14 @@ extern s64 ntfs_get_attribute_value_length(const ATTR_RECORD *a);
* then nothing was read due to a zero-length attribute value, otherwise
* errno describes the error.
*/
extern s64 ntfs_get_attribute_value(const ntfs_volume *vol,
const ATTR_RECORD *a, u8 *b);
s64 ntfs_get_attribute_value(const ntfs_volume *vol, const ATTR_RECORD *a,
u8 *b);
extern void ntfs_attr_name_free(char **name);
extern char *ntfs_attr_name_get(const ntfschar *uname, const int uname_len);
extern int ntfs_attr_exist(ntfs_inode *ni, const ATTR_TYPES type,
const ntfschar *name, u32 name_len);
extern int ntfs_attr_remove(ntfs_inode *ni, const ATTR_TYPES type,
ntfschar *name, u32 name_len);
extern s64 ntfs_attr_get_free_bits(ntfs_attr *na);
extern int ntfs_attr_data_read(ntfs_inode *ni,
ntfschar *stream_name, int stream_name_len,
char *buf, size_t size, off_t offset);
extern int ntfs_attr_data_write(ntfs_inode *ni,
ntfschar *stream_name, int stream_name_len,
const char *buf, size_t size, off_t offset);
extern int ntfs_attr_shrink_size(ntfs_inode *ni, ntfschar *stream_name,
int stream_name_len, off_t offset);
extern int ntfs_attr_inconsistent(const ATTR_RECORD *a, const MFT_REF mref);
void ntfs_attr_name_free(char **name);
char *ntfs_attr_name_get(const ntfschar *uname, const int uname_len);
int ntfs_attr_exist(ntfs_inode *ni, const ATTR_TYPES type, ntfschar *name,
u32 name_len);
#endif /* defined _NTFS_ATTRIB_H */

View File

@ -70,27 +70,5 @@ static __inline__ int ntfs_bitmap_clear_bit(ntfs_attr *na, s64 bit)
return ntfs_bitmap_clear_run(na, bit, 1);
}
/*
* rol32 - rotate a 32-bit value left
*
* @word: value to rotate
* @shift: bits to roll
*/
static __inline__ u32 ntfs_rol32(u32 word, unsigned int shift)
{
return (word << shift) | (word >> (32 - shift));
}
/*
* ror32 - rotate a 32-bit value right
*
* @word: value to rotate
* @shift: bits to roll
*/
static __inline__ u32 ntfs_ror32(u32 word, unsigned int shift)
{
return (word >> shift) | (word << (32 - shift));
}
#endif /* defined _NTFS_BITMAP_H */

View File

@ -1,9 +1,8 @@
/*
* bootsect.h - Exports for bootsector record handling.
* Originated from the Linux-NTFS project.
* bootsect.h - Exports for bootsector record handling. Originated from the Linux-NTFS
* project.
*
* Copyright (c) 2000-2002 Anton Altaparmakov
* Copyright (c) 2006 Szabolcs Szakacsits
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
@ -29,14 +28,20 @@
#include "layout.h"
/**
* ntfs_boot_sector_is_ntfs - check a boot sector for describing an ntfs volume
* is_boot_sector_ntfs - check a boot sector for describing an ntfs volume
* @b: buffer containing the boot sector
* @silent: if 1 don't display progress information
*
* This function checks the boot sector in @b for describing a valid ntfs
* volume. Return TRUE if @b is a valid NTFS boot sector or FALSE otherwise.
* If silent is FALSE, progress output will be output to stdout. If silent is
* TRUE no output to stdout will occur. Errors/warnings to stderr will occur
* disregarding the value of silent (but only if configure was run with
* --enable-debug).
*/
extern BOOL ntfs_boot_sector_is_ntfs(NTFS_BOOT_SECTOR *b);
extern int ntfs_boot_sector_parse(ntfs_volume *vol, const NTFS_BOOT_SECTOR *bs);
extern BOOL ntfs_boot_sector_is_ntfs(NTFS_BOOT_SECTOR *b, BOOL silent);
extern int ntfs_boot_sector_parse(ntfs_volume *vol,
const NTFS_BOOT_SECTOR *bs);
#endif /* defined _NTFS_BOOTSECT_H */

View File

@ -1,118 +0,0 @@
/*
* cache.h : deal with indexed LRU caches
*
* Copyright (c) 2008-2010 Jean-Pierre Andre
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program/include file 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 (in the main directory of the NTFS-3G
* distribution in the file COPYING); if not, write to the Free Software
* Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _NTFS_CACHE_H_
#define _NTFS_CACHE_H_
#include "volume.h"
struct CACHED_GENERIC {
struct CACHED_GENERIC *next;
struct CACHED_GENERIC *previous;
void *variable;
size_t varsize;
union ALIGNMENT payload[0];
} ;
struct CACHED_INODE {
struct CACHED_INODE *next;
struct CACHED_INODE *previous;
const char *pathname;
size_t varsize;
union ALIGNMENT payload[0];
/* above fields must match "struct CACHED_GENERIC" */
u64 inum;
} ;
struct CACHED_NIDATA {
struct CACHED_NIDATA *next;
struct CACHED_NIDATA *previous;
const char *pathname; /* not used */
size_t varsize; /* not used */
union ALIGNMENT payload[0];
/* above fields must match "struct CACHED_GENERIC" */
u64 inum;
ntfs_inode *ni;
} ;
struct CACHED_LOOKUP {
struct CACHED_LOOKUP *next;
struct CACHED_LOOKUP *previous;
const char *name;
size_t namesize;
union ALIGNMENT payload[0];
/* above fields must match "struct CACHED_GENERIC" */
u64 parent;
u64 inum;
} ;
enum {
CACHE_FREE = 1,
CACHE_NOHASH = 2
} ;
typedef int (*cache_compare)(const struct CACHED_GENERIC *cached,
const struct CACHED_GENERIC *item);
typedef void (*cache_free)(const struct CACHED_GENERIC *cached);
typedef int (*cache_hash)(const struct CACHED_GENERIC *cached);
struct HASH_ENTRY {
struct HASH_ENTRY *next;
struct CACHED_GENERIC *entry;
} ;
struct CACHE_HEADER {
const char *name;
struct CACHED_GENERIC *most_recent_entry;
struct CACHED_GENERIC *oldest_entry;
struct CACHED_GENERIC *free_entry;
struct HASH_ENTRY *free_hash;
struct HASH_ENTRY **first_hash;
cache_free dofree;
cache_hash dohash;
unsigned long reads;
unsigned long writes;
unsigned long hits;
int fixed_size;
int max_hash;
struct CACHED_GENERIC entry[0];
} ;
/* cast to generic, avoiding gcc warnings */
#define GENERIC(pstr) ((const struct CACHED_GENERIC*)(const void*)(pstr))
struct CACHED_GENERIC *ntfs_fetch_cache(struct CACHE_HEADER *cache,
const struct CACHED_GENERIC *wanted,
cache_compare compare);
struct CACHED_GENERIC *ntfs_enter_cache(struct CACHE_HEADER *cache,
const struct CACHED_GENERIC *item,
cache_compare compare);
int ntfs_invalidate_cache(struct CACHE_HEADER *cache,
const struct CACHED_GENERIC *item,
cache_compare compare, int flags);
int ntfs_remove_cache(struct CACHE_HEADER *cache,
struct CACHED_GENERIC *item, int flags);
void ntfs_create_lru_caches(ntfs_volume *vol);
void ntfs_free_lru_caches(ntfs_volume *vol);
#endif /* _NTFS_CACHE_H_ */

View File

@ -29,6 +29,9 @@
#define NTFS_COLLATION_ERROR -2
extern COLLATE ntfs_get_collate_function(COLLATION_RULES);
extern BOOL ntfs_is_collation_rule_supported(COLLATION_RULES cr);
extern int ntfs_collate(ntfs_volume *vol, COLLATION_RULES cr,
const void *data1, const int data1_len,
const void *data2, const int data2_len);
#endif /* _NTFS_COLLATE_H */

View File

@ -1,10 +1,8 @@
/*
* compat.h - Tweaks for compatibility with non-Linux systems.
* compat.h - Tweaks for Windows compatibility.
*
* Copyright (c) 2002 Richard Russon
* Copyright (c) 2002-2004 Anton Altaparmakov
* Copyright (c) 2008-2009 Szabolcs Szakacsits
* Copyright (c) 2019 Jean-Pierre Andre
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
@ -28,52 +26,14 @@
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#include <errno.h> /* ENODATA */
#ifndef ENODATA
#define ENODATA ENOENT
#endif
#ifndef ELIBBAD
#define ELIBBAD ENOEXEC
#endif
#ifndef ELIBACC
#define ELIBACC ENOENT
#endif
/* xattr APIs in macOS differs from Linux ones in that they expect the special
* error code ENOATTR to be returned when an attribute cannot be found. So
* define NTFS_NOXATTR_ERRNO to the appropriate "no xattr found" errno value for
* the platform. */
#if defined(__APPLE__) || defined(__DARWIN__)
#define NTFS_NOXATTR_ERRNO ENOATTR
#else
#define NTFS_NOXATTR_ERRNO ENODATA
#endif
#ifndef PATH_MAX
#define PATH_MAX 4096
#endif
#ifndef HAVE_FFS
extern int ffs(int i);
#endif /* HAVE_FFS */
#ifndef HAVE_DAEMON
extern int daemon(int nochdir, int noclose);
#endif /* HAVE_DAEMON */
#ifndef HAVE_STRSEP
extern char *strsep(char **stringp, const char *delim);
#endif /* HAVE_STRSEP */
#ifdef WINDOWS
#ifndef HAVE_FFS
#define HAVE_FFS
extern int ffs(int i);
#endif /* HAVE_FFS */
#define HAVE_STDIO_H /* mimic config.h */
#define HAVE_STDARG_H

View File

@ -29,13 +29,5 @@
extern s64 ntfs_compressed_attr_pread(ntfs_attr *na, s64 pos, s64 count,
void *b);
extern s64 ntfs_compressed_pwrite(ntfs_attr *na, runlist_element *brl, s64 wpos,
s64 offs, s64 to_write, s64 rounded,
const void *b, int compressed_part,
VCN *update_from);
extern int ntfs_compressed_close(ntfs_attr *na, runlist_element *brl,
s64 offs, VCN *update_from);
#endif /* defined _NTFS_COMPRESS_H */

View File

@ -38,10 +38,10 @@ static __inline__ void ntfs_debug_runlist_dump(const struct _runlist_element *rl
#define NTFS_BUG(msg) \
{ \
int ___i = 1; \
int ___i; \
ntfs_log_critical("Bug in %s(): %s\n", __FUNCTION__, msg); \
ntfs_log_debug("Forcing segmentation fault!"); \
___i = ((int*)NULL)[___i]; \
___i = ((int*)NULL)[1]; \
}
#endif /* defined _NTFS_DEBUG_H */

View File

@ -1,8 +1,7 @@
/*
* device.h - Exports for low level device io. Originated from the Linux-NTFS project.
*
* Copyright (c) 2000-2013 Anton Altaparmakov
* Copyright (c) 2008-2013 Tuxera Inc.
* Copyright (c) 2000-2006 Anton Altaparmakov
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
@ -42,7 +41,6 @@ typedef enum {
ND_ReadOnly, /* 1: Device is read-only. */
ND_Dirty, /* 1: Device is dirty, needs sync. */
ND_Block, /* 1: Device is a block device. */
ND_Sync, /* 1: Device is mounted with "-o sync" */
} ntfs_device_state_bits;
#define test_ndev_flag(nd, flag) test_bit(ND_##flag, (nd)->d_state)
@ -65,20 +63,11 @@ typedef enum {
#define NDevSetBlock(nd) set_ndev_flag(nd, Block)
#define NDevClearBlock(nd) clear_ndev_flag(nd, Block)
#define NDevSync(nd) test_ndev_flag(nd, Sync)
#define NDevSetSync(nd) set_ndev_flag(nd, Sync)
#define NDevClearSync(nd) clear_ndev_flag(nd, Sync)
/**
* struct ntfs_device -
*
* The ntfs device structure defining all operations needed to access the low
* level device underlying the ntfs volume.
*
* Note d_heads and d_sectors_per_track are only set as a result of a call to
* either ntfs_device_heads_get() or ntfs_device_sectors_per_track_get() (both
* calls will set up both fields or if getting them failed they will be left at
* -1).
*/
struct ntfs_device {
struct ntfs_device_operations *d_ops; /* Device operations. */
@ -86,10 +75,6 @@ struct ntfs_device {
char *d_name; /* Name of device. */
void *d_private; /* Private data used by the
device operations. */
int d_heads; /* Disk geometry: number of
heads or -1. */
int d_sectors_per_track; /* Disk geometry: number of
sectors per track or -1. */
};
struct stat;
@ -111,14 +96,12 @@ struct ntfs_device_operations {
s64 offset);
int (*sync)(struct ntfs_device *dev);
int (*stat)(struct ntfs_device *dev, struct stat *buf);
int (*ioctl)(struct ntfs_device *dev, unsigned long request,
void *argp);
int (*ioctl)(struct ntfs_device *dev, int request, void *argp);
};
extern struct ntfs_device *ntfs_device_alloc(const char *name, const long state,
struct ntfs_device_operations *dops, void *priv_data);
extern int ntfs_device_free(struct ntfs_device *dev);
extern int ntfs_device_sync(struct ntfs_device *dev);
extern s64 ntfs_pread(struct ntfs_device *dev, const s64 pos, s64 count,
void *b);

View File

@ -28,18 +28,12 @@
#ifndef NO_NTFS_DEVICE_DEFAULT_IO_OPS
#if defined(linux) || defined(__uClinux__) || defined(__sun) \
|| defined(__APPLE__) || defined(__DARWIN__)
/* Make sure the presence of <windows.h> means compiling for Windows */
#undef HAVE_WINDOWS_H
#endif
#ifndef __CYGWIN32__
#ifndef HAVE_WINDOWS_H
/* Not for Windows use standard Unix style low level device operations. */
/* Not on Cygwin; use standard Unix style low level device operations. */
#define ntfs_device_default_io_ops ntfs_device_unix_io_ops
#else /* HAVE_WINDOWS_H */
#else /* __CYGWIN32__ */
#ifndef HDIO_GETGEO
# define HDIO_GETGEO 0x301
@ -66,15 +60,10 @@ struct hd_geometry {
# define BLKBSZSET 0x40041271
#endif
/* On Windows (and Cygwin) : use Win32 low level device operations. */
/* On Cygwin; use Win32 low level device operations. */
#define ntfs_device_default_io_ops ntfs_device_win32_io_ops
/* A few useful functions */
int ntfs_win32_set_sparse(int);
int ntfs_win32_ftruncate(int fd, s64 size);
int ntfs_device_win32_ftruncate(struct ntfs_device*, s64);
#endif /* HAVE_WINDOWS_H */
#endif /* __CYGWIN32__ */
/* Forward declaration. */

View File

@ -1,10 +1,9 @@
/*
* dir.h - Exports for directory handling. Originated from the Linux-NTFS project.
*
* Copyright (c) 2002 Anton Altaparmakov
* Copyright (c) 2002 Anton Altaparmakov
* Copyright (c) 2005-2006 Yura Pakhuchiy
* Copyright (c) 2004-2005 Richard Russon
* Copyright (c) 2005-2008 Szabolcs Szakacsits
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
@ -29,6 +28,10 @@
#define PATH_SEP '/'
#ifndef MAX_PATH
#define MAX_PATH 1024
#endif
/*
* We do not have these under DJGPP, so define our version that do not conflict
* with other S_IFs defined under DJGPP.
@ -61,25 +64,21 @@ extern ntfschar NTFS_INDEX_R[3];
extern u64 ntfs_inode_lookup_by_name(ntfs_inode *dir_ni,
const ntfschar *uname, const int uname_len);
extern u64 ntfs_inode_lookup_by_mbsname(ntfs_inode *dir_ni, const char *name);
extern void ntfs_inode_update_mbsname(ntfs_inode *dir_ni, const char *name,
u64 inum);
extern ntfs_inode *ntfs_pathname_to_inode(ntfs_volume *vol, ntfs_inode *parent,
const char *pathname);
extern ntfs_inode *ntfs_create(ntfs_inode *dir_ni, le32 securid,
const ntfschar *name, u8 name_len, mode_t type);
extern ntfs_inode *ntfs_create_device(ntfs_inode *dir_ni, le32 securid,
const ntfschar *name, u8 name_len, mode_t type, dev_t dev);
extern ntfs_inode *ntfs_create_symlink(ntfs_inode *dir_ni, le32 securid,
const ntfschar *name, u8 name_len, const ntfschar *target,
int target_len);
extern ntfs_inode *ntfs_create(ntfs_inode *dir_ni, ntfschar *name, u8 name_len,
dev_t type);
extern ntfs_inode *ntfs_create_device(ntfs_inode *dir_ni,
ntfschar *name, u8 name_len, dev_t type, dev_t dev);
extern ntfs_inode *ntfs_create_symlink(ntfs_inode *dir_ni,
ntfschar *name, u8 name_len, ntfschar *target, u8 target_len);
extern int ntfs_check_empty_dir(ntfs_inode *ni);
extern int ntfs_delete(ntfs_volume *vol, const char *path,
ntfs_inode *ni, ntfs_inode *dir_ni, const ntfschar *name,
extern int ntfs_delete(ntfs_inode *ni, ntfs_inode *dir_ni, ntfschar *name,
u8 name_len);
extern int ntfs_link(ntfs_inode *ni, ntfs_inode *dir_ni, const ntfschar *name,
extern int ntfs_link(ntfs_inode *ni, ntfs_inode *dir_ni, ntfschar *name,
u8 name_len);
/*
@ -94,7 +93,6 @@ extern int ntfs_link(ntfs_inode *ni, ntfs_inode *dir_ni, const ntfschar *name,
#define NTFS_DT_LNK 10
#define NTFS_DT_SOCK 12
#define NTFS_DT_WHT 14
#define NTFS_DT_REPARSE 32
/*
* This is the "ntfs_filldir" function type, used by ntfs_readdir() to let
@ -109,24 +107,5 @@ typedef int (*ntfs_filldir_t)(void *dirent, const ntfschar *name,
extern int ntfs_readdir(ntfs_inode *dir_ni, s64 *pos,
void *dirent, ntfs_filldir_t filldir);
ntfs_inode *ntfs_dir_parent_inode(ntfs_inode *ni);
u32 ntfs_interix_types(ntfs_inode *ni);
int ntfs_get_ntfs_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni,
char *value, size_t size);
int ntfs_set_ntfs_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni,
const char *value, size_t size, int flags);
int ntfs_remove_ntfs_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni);
int ntfs_dir_link_cnt(ntfs_inode *ni);
#if CACHE_INODE_SIZE
struct CACHED_GENERIC;
extern int ntfs_dir_inode_hash(const struct CACHED_GENERIC *cached);
extern int ntfs_dir_lookup_hash(const struct CACHED_GENERIC *cached);
#endif
#endif /* defined _NTFS_DIR_H */

View File

@ -1,37 +0,0 @@
/*
*
* Copyright (c) 2014-2021 Jean-Pierre Andre
*
*/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program (in the main directory of the NTFS-3G
* distribution in the file COPYING); if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef EA_H
#define EA_H
int ntfs_ea_check_wsldev(ntfs_inode *ni, dev_t *rdevp);
int ntfs_ea_set_wsl_not_symlink(ntfs_inode *ni, mode_t mode, dev_t dev);
int ntfs_get_ntfs_ea(ntfs_inode *ni, char *value, size_t size);
int ntfs_set_ntfs_ea(ntfs_inode *ni, const char *value, size_t size, int flags);
int ntfs_remove_ntfs_ea(ntfs_inode *ni);
#endif /* EA_H */

View File

@ -61,16 +61,10 @@
# define __BYTE_ORDER BYTE_ORDER
# define __LITTLE_ENDIAN LITTLE_ENDIAN
# define __BIG_ENDIAN BIG_ENDIAN
# elif defined(__BYTE_ORDER__) && defined(__LITTLE_ENDIAN__) && \
defined(__BIG_ENDIAN__)
# elif defined(__BYTE_ORDER__)
# define __BYTE_ORDER __BYTE_ORDER__
# define __LITTLE_ENDIAN __LITTLE_ENDIAN__
# define __BIG_ENDIAN __BIG_ENDIAN__
# elif defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && \
defined(__ORDER_BIG_ENDIAN__)
# define __BYTE_ORDER __BYTE_ORDER__
# define __LITTLE_ENDIAN __ORDER_LITTLE_ENDIAN__
# define __BIG_ENDIAN __ORDER_BIG_ENDIAN__
# elif (defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN)) || \
defined(WORDS_LITTLEENDIAN)
# define __BYTE_ORDER 1
@ -132,22 +126,6 @@
#define __constant_cpu_to_le32(x) (x)
#define __constant_cpu_to_le64(x) (x)
#define __be16_to_cpu(x) bswap_16(x)
#define __be32_to_cpu(x) bswap_32(x)
#define __be64_to_cpu(x) bswap_64(x)
#define __cpu_to_be16(x) bswap_16(x)
#define __cpu_to_be32(x) bswap_32(x)
#define __cpu_to_be64(x) bswap_64(x)
#define __constant_be16_to_cpu(x) __ntfs_bswap_constant_16((u16)(x))
#define __constant_be32_to_cpu(x) __ntfs_bswap_constant_32((u32)(x))
#define __constant_be64_to_cpu(x) __ntfs_bswap_constant_64((u64)(x))
#define __constant_cpu_to_be16(x) __ntfs_bswap_constant_16((u16)(x))
#define __constant_cpu_to_be32(x) __ntfs_bswap_constant_32((u32)(x))
#define __constant_cpu_to_be64(x) __ntfs_bswap_constant_64((u64)(x))
#elif defined(__BIG_ENDIAN) && (__BYTE_ORDER == __BIG_ENDIAN)
#define __le16_to_cpu(x) bswap_16(x)
@ -166,22 +144,6 @@
#define __constant_cpu_to_le32(x) __ntfs_bswap_constant_32((u32)(x))
#define __constant_cpu_to_le64(x) __ntfs_bswap_constant_64((u64)(x))
#define __be16_to_cpu(x) (x)
#define __be32_to_cpu(x) (x)
#define __be64_to_cpu(x) (x)
#define __cpu_to_be16(x) (x)
#define __cpu_to_be32(x) (x)
#define __cpu_to_be64(x) (x)
#define __constant_be16_to_cpu(x) (x)
#define __constant_be32_to_cpu(x) (x)
#define __constant_be64_to_cpu(x) (x)
#define __constant_cpu_to_be16(x) (x)
#define __constant_cpu_to_be32(x) (x)
#define __constant_cpu_to_be64(x) (x)
#else
#error "You must define __BYTE_ORDER to be __LITTLE_ENDIAN or __BIG_ENDIAN."
@ -228,78 +190,14 @@
#define cpu_to_sle32p(x) (s32)__cpu_to_le32(*(s32*)(x))
#define cpu_to_sle64p(x) (s64)__cpu_to_le64(*(s64*)(x))
/* Unsigned from BE to CPU conversion. */
#define be16_to_cpu(x) (u16)__be16_to_cpu((u16)(x))
#define be32_to_cpu(x) (u32)__be32_to_cpu((u32)(x))
#define be64_to_cpu(x) (u64)__be64_to_cpu((u64)(x))
#define be16_to_cpup(x) (u16)__be16_to_cpu(*(const u16*)(x))
#define be32_to_cpup(x) (u32)__be32_to_cpu(*(const u32*)(x))
#define be64_to_cpup(x) (u64)__be64_to_cpu(*(const u64*)(x))
/* Signed from BE to CPU conversion. */
#define sbe16_to_cpu(x) (s16)__be16_to_cpu((s16)(x))
#define sbe32_to_cpu(x) (s32)__be32_to_cpu((s32)(x))
#define sbe64_to_cpu(x) (s64)__be64_to_cpu((s64)(x))
#define sbe16_to_cpup(x) (s16)__be16_to_cpu(*(s16*)(x))
#define sbe32_to_cpup(x) (s32)__be32_to_cpu(*(s32*)(x))
#define sbe64_to_cpup(x) (s64)__be64_to_cpu(*(s64*)(x))
/* Unsigned from CPU to BE conversion. */
#define cpu_to_be16(x) (u16)__cpu_to_be16((u16)(x))
#define cpu_to_be32(x) (u32)__cpu_to_be32((u32)(x))
#define cpu_to_be64(x) (u64)__cpu_to_be64((u64)(x))
#define cpu_to_be16p(x) (u16)__cpu_to_be16(*(u16*)(x))
#define cpu_to_be32p(x) (u32)__cpu_to_be32(*(u32*)(x))
#define cpu_to_be64p(x) (u64)__cpu_to_be64(*(u64*)(x))
/* Signed from CPU to BE conversion. */
#define cpu_to_sbe16(x) (s16)__cpu_to_be16((s16)(x))
#define cpu_to_sbe32(x) (s32)__cpu_to_be32((s32)(x))
#define cpu_to_sbe64(x) (s64)__cpu_to_be64((s64)(x))
#define cpu_to_sbe16p(x) (s16)__cpu_to_be16(*(s16*)(x))
#define cpu_to_sbe32p(x) (s32)__cpu_to_be32(*(s32*)(x))
#define cpu_to_sbe64p(x) (s64)__cpu_to_be64(*(s64*)(x))
/* Constant endianness conversion defines. */
#define const_le16_to_cpu(x) ((u16) __constant_le16_to_cpu(x))
#define const_le32_to_cpu(x) ((u32) __constant_le32_to_cpu(x))
#define const_le64_to_cpu(x) ((u64) __constant_le64_to_cpu(x))
#define const_le16_to_cpu(x) __constant_le16_to_cpu(x)
#define const_le32_to_cpu(x) __constant_le32_to_cpu(x)
#define const_le64_to_cpu(x) __constant_le64_to_cpu(x)
#define const_cpu_to_le16(x) ((le16) __constant_cpu_to_le16(x))
#define const_cpu_to_le32(x) ((le32) __constant_cpu_to_le32(x))
#define const_cpu_to_le64(x) ((le64) __constant_cpu_to_le64(x))
#define const_sle16_to_cpu(x) ((s16) __constant_le16_to_cpu((le16) x))
#define const_sle32_to_cpu(x) ((s32) __constant_le32_to_cpu((le32) x))
#define const_sle64_to_cpu(x) ((s64) __constant_le64_to_cpu((le64) x))
#define const_cpu_to_sle16(x) ((sle16) __constant_cpu_to_le16((u16) x))
#define const_cpu_to_sle32(x) ((sle32) __constant_cpu_to_le32((u32) x))
#define const_cpu_to_sle64(x) ((sle64) __constant_cpu_to_le64((u64) x))
#define const_be16_to_cpu(x) ((u16) __constant_be16_to_cpu(x)))
#define const_be32_to_cpu(x) ((u32) __constant_be32_to_cpu(x)))
#define const_be64_to_cpu(x) ((u64) __constant_be64_to_cpu(x)))
#define const_cpu_to_be16(x) ((be16) __constant_cpu_to_be16(x))
#define const_cpu_to_be32(x) ((be32) __constant_cpu_to_be32(x))
#define const_cpu_to_be64(x) ((be64) __constant_cpu_to_be64(x))
#define const_sbe16_to_cpu(x) ((s16) __constant_be16_to_cpu((be16) x))
#define const_sbe32_to_cpu(x) ((s32) __constant_be32_to_cpu((be32) x))
#define const_sbe64_to_cpu(x) ((s64) __constant_be64_to_cpu((be64) x))
#define const_cpu_to_sbe16(x) ((sbe16) __constant_cpu_to_be16((u16) x))
#define const_cpu_to_sbe32(x) ((sbe32) __constant_cpu_to_be32((u32) x))
#define const_cpu_to_sbe64(x) ((sbe64) __constant_cpu_to_be64((u64) x))
#define const_cpu_to_le16(x) __constant_cpu_to_le16(x)
#define const_cpu_to_le32(x) __constant_cpu_to_le32(x)
#define const_cpu_to_le64(x) __constant_cpu_to_le64(x)
#endif /* defined _NTFS_ENDIANS_H */

View File

@ -4,7 +4,7 @@
* Copyright (c) 2004 Anton Altaparmakov
* Copyright (c) 2004-2005 Richard Russon
* Copyright (c) 2005 Yura Pakhuchiy
* Copyright (c) 2006-2008 Szabolcs Szakacsits
* Copyright (c) 2006 Szabolcs Szakacsits
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
@ -25,34 +25,6 @@
#ifndef _NTFS_INDEX_H
#define _NTFS_INDEX_H
/* Convenience macros to test the versions of gcc.
* Use them like this:
* #if __GNUC_PREREQ (2,8)
* ... code requiring gcc 2.8 or later ...
* #endif
* Note - they won't work for gcc1 or glibc1, since the _MINOR macros
* were not defined then.
*/
#ifndef __GNUC_PREREQ
# if defined __GNUC__ && defined __GNUC_MINOR__
# define __GNUC_PREREQ(maj, min) \
((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
# else
# define __GNUC_PREREQ(maj, min) 0
# endif
#endif
/* allows us to warn about unused results of certain function calls */
#ifndef __attribute_warn_unused_result__
# if __GNUC_PREREQ (3,4)
# define __attribute_warn_unused_result__ \
__attribute__ ((__warn_unused_result__))
# else
# define __attribute_warn_unused_result__ /* empty */
# endif
#endif
#include "attrib.h"
#include "types.h"
#include "layout.h"
@ -63,9 +35,6 @@
#define MAX_PARENT_VCN 32
typedef int (*COLLATE)(ntfs_volume *vol, const void *data1, int len1,
const void *data2, int len2);
/**
* struct ntfs_index_context -
* @ni: inode containing the @entry described by this context
@ -79,6 +48,7 @@ typedef int (*COLLATE)(ntfs_volume *vol, const void *data1, int len1,
* @actx: attribute search context if in root or NULL otherwise
* @ia: index block if @is_in_root is FALSE or NULL otherwise
* @ia_na: opened INDEX_ALLOCATION attribute
* @ib_vcn: VCN from which @ia where read from
* @parent_pos: parent entries' positions in the index block
* @parent_vcn: entry's parent node or VCN_INDEX_ROOT_PARENT
* @new_vcn: new VCN if we need to create a new index block
@ -94,11 +64,11 @@ typedef int (*COLLATE)(ntfs_volume *vol, const void *data1, int len1,
* simply points into @entry. This is probably what the user is interested in.
*
* If @is_in_root is TRUE, @entry is in the index root attribute @ir described
* by the attribute search context @actx and inode @ni. @ia and
* by the attribute search context @actx and inode @ni. @ia, @ib_vcn and
* @ib_dirty are undefined in this case.
*
* If @is_in_root is FALSE, @entry is in the index allocation attribute and @ia
* point to the index allocation block and VCN where it's placed,
* and @ib_vcn point to the index allocation block and VCN where it's placed,
* respectively. @ir and @actx are NULL in this case. @ia_na is opened
* INDEX_ALLOCATION attribute. @ib_dirty is TRUE if index block was changed and
* FALSE otherwise.
@ -119,17 +89,18 @@ typedef struct {
INDEX_ENTRY *entry;
void *data;
u16 data_len;
COLLATE collate;
COLLATION_RULES cr;
BOOL is_in_root;
INDEX_ROOT *ir;
ntfs_attr_search_ctx *actx;
INDEX_BLOCK *ib;
ntfs_attr *ia_na;
int parent_pos[MAX_PARENT_VCN]; /* parent entries' positions */
VCN ib_vcn;
VCN parent_vcn[MAX_PARENT_VCN]; /* entry's parent nodes */
int max_depth; /* number of the parent nodes */
int pindex; /* maximum it's the number of the parent nodes */
BOOL ib_dirty;
BOOL bad_index;
u32 block_size;
u8 vcn_size_bits;
} ntfs_index_context;
@ -139,20 +110,12 @@ extern ntfs_index_context *ntfs_index_ctx_get(ntfs_inode *ni,
extern void ntfs_index_ctx_put(ntfs_index_context *ictx);
extern void ntfs_index_ctx_reinit(ntfs_index_context *ictx);
extern int ntfs_index_block_inconsistent(const INDEX_BLOCK *ib, u32 block_size,
u64 inum, VCN vcn);
extern int ntfs_index_entry_inconsistent(const INDEX_ENTRY *ie,
COLLATION_RULES collation_rule, u64 inum);
extern int ntfs_index_lookup(const void *key, const int key_len,
ntfs_index_context *ictx) __attribute_warn_unused_result__;
extern INDEX_ENTRY *ntfs_index_next(INDEX_ENTRY *ie,
ntfs_index_context *ictx);
extern int ntfs_index_add_filename(ntfs_inode *ni, FILE_NAME_ATTR *fn,
MFT_REF mref);
extern int ntfs_index_remove(ntfs_inode *dir_ni, ntfs_inode *ni,
const void *key, const int keylen);
extern int ntfs_index_rm(ntfs_index_context *ictx);
extern INDEX_ROOT *ntfs_index_root_get(ntfs_inode *ni, ATTR_RECORD *attr);
@ -164,9 +127,5 @@ extern char *ntfs_ie_filename_get(INDEX_ENTRY *ie);
extern void ntfs_ie_filename_dump(INDEX_ENTRY *ie);
extern void ntfs_ih_filename_dump(INDEX_HEADER *ih);
/* the following was added by JPA for use in security.c */
extern int ntfs_ie_add(ntfs_index_context *icx, INDEX_ENTRY *ie);
extern int ntfs_index_rm(ntfs_index_context *icx);
#endif /* _NTFS_INDEX_H */

View File

@ -1,10 +1,10 @@
/*
* inode.h - Defines for NTFS inode handling. Originated from the Linux-NTFS project.
*
* Copyright (c) 2001-2004 Anton Altaparmakov
* Copyright (c) 2004-2007 Yura Pakhuchiy
* Copyright (c) 2001,2002 Anton Altaparmakov
* Copyright (c) 2004-2005 Yura Pakhuchiy
* Copyright (c) 2004-2005 Richard Russon
* Copyright (c) 2006-2008 Szabolcs Szakacsits
* Copyright (c) 2006 Szabolcs Szakacsits
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
@ -32,7 +32,6 @@ typedef struct _ntfs_inode ntfs_inode;
#include "layout.h"
#include "support.h"
#include "volume.h"
#include "ntfstime.h"
/**
* enum ntfs_inode_state_bits -
@ -49,9 +48,6 @@ typedef enum {
mft record and then to disk. */
NI_FileNameDirty, /* 1: FILE_NAME attributes need to be updated
in the index. */
NI_v3_Extensions, /* 1: JPA v3.x extensions present. */
NI_TimesSet, /* 1: Use times which were set */
NI_KnownSize, /* 1: Set if sizes are meaningful */
} ntfs_inode_state_bits;
#define test_nino_flag(ni, flag) test_bit(NI_##flag, (ni)->state)
@ -89,13 +85,16 @@ typedef enum {
#define NInoAttrListTestAndSetDirty(ni) test_and_set_nino_al_flag(ni, Dirty)
#define NInoAttrListTestAndClearDirty(ni) test_and_clear_nino_al_flag(ni, Dirty)
#define NInoFileNameDirty(ni) test_nino_flag(ni, FileNameDirty)
#define NInoFileNameSetDirty(ni) set_nino_flag(ni, FileNameDirty)
#define NInoFileNameClearDirty(ni) clear_nino_flag(ni, FileNameDirty)
#define NInoFileNameDirty(ni) \
test_nino_flag(ni, FileNameDirty)
#define NInoFileNameSetDirty(ni) \
set_nino_flag(ni, FileNameDirty)
#define NInoFileNameClearDirty(ni) \
clear_nino_flag(ni, FileNameDirty)
#define NInoFileNameTestAndSetDirty(ni) \
test_and_set_nino_flag(ni, FileNameDirty)
test_and_set_nino_flag(ni, FileNameDirty)
#define NInoFileNameTestAndClearDirty(ni) \
test_and_clear_nino_flag(ni, FileNameDirty)
test_and_clear_nino_flag(ni, FileNameDirty)
/**
* struct _ntfs_inode - The NTFS in-memory inode structure.
@ -131,17 +130,12 @@ struct _ntfs_inode {
inode of the base mft record. */
};
/* Below fields are valid only for base inode. */
/* Temp: for directory handling */
void *private_data; /* ntfs_dt containing this inode */
int ref_count;
/*
* These two fields are used to sync filename index and guaranteed to be
* correct, however value in index itself maybe wrong (windows itself
* do not update them properly).
* For directories, they hold the index size, provided the
* flag KnownSize is set.
*/
s64 data_size; /* Data size of unnamed DATA attribute
(or INDEX_ROOT for directories) */
/* Below fields are valid only for base inode. */
s64 data_size; /* Data size stored in the filename index. */
s64 allocated_size; /* Allocated size stored in the filename
index. (NOTE: Equal to allocated size of
the unnamed data attribute for normal or
@ -149,61 +143,27 @@ struct _ntfs_inode {
of the unnamed data attribute for sparse or
compressed files.) */
/*
* These four fields are copy of relevant fields from
* STANDARD_INFORMATION attribute and used to sync it and FILE_NAME
* attribute in the index.
*/
ntfs_time creation_time;
ntfs_time last_data_change_time;
ntfs_time last_mft_change_time;
ntfs_time last_access_time;
/* NTFS 3.x extensions added by JPA */
/* only if NI_v3_Extensions is set in state */
le32 owner_id;
le32 security_id;
le64 quota_charged;
le64 usn;
time_t creation_time;
time_t last_data_change_time;
time_t last_mft_change_time;
time_t last_access_time;
};
typedef enum {
NTFS_UPDATE_ATIME = 1 << 0,
NTFS_UPDATE_MTIME = 1 << 1,
NTFS_UPDATE_CTIME = 1 << 2,
} ntfs_time_update_flags;
#define NTFS_UPDATE_MCTIME (NTFS_UPDATE_MTIME | NTFS_UPDATE_CTIME)
#define NTFS_UPDATE_AMCTIME (NTFS_UPDATE_ATIME | NTFS_UPDATE_MCTIME)
extern ntfs_inode *ntfs_inode_base(ntfs_inode *ni);
extern ntfs_inode *ntfs_inode_allocate(ntfs_volume *vol);
extern ntfs_inode *ntfs_inode_open(ntfs_volume *vol, const MFT_REF mref);
extern int ntfs_inode_close(ntfs_inode *ni);
extern int ntfs_inode_close_in_dir(ntfs_inode *ni, ntfs_inode *dir_ni);
#if CACHE_NIDATA_SIZE
struct CACHED_GENERIC;
extern int ntfs_inode_real_close(ntfs_inode *ni);
extern void ntfs_inode_invalidate(ntfs_volume *vol, const MFT_REF mref);
extern void ntfs_inode_nidata_free(const struct CACHED_GENERIC *cached);
extern int ntfs_inode_nidata_hash(const struct CACHED_GENERIC *item);
#endif
extern ntfs_inode *ntfs_extent_inode_open(ntfs_inode *base_ni,
const leMFT_REF mref);
const MFT_REF mref);
extern int ntfs_inode_attach_all_extents(ntfs_inode *ni);
extern void ntfs_inode_mark_dirty(ntfs_inode *ni);
extern void ntfs_inode_update_times(ntfs_inode *ni, ntfs_time_update_flags mask);
extern void ntfs_inode_update_atime(ntfs_inode *ni);
extern void ntfs_inode_update_time(ntfs_inode *ni);
extern int ntfs_inode_sync(ntfs_inode *ni);
@ -213,13 +173,4 @@ extern int ntfs_inode_free_space(ntfs_inode *ni, int size);
extern int ntfs_inode_badclus_bad(u64 mft_no, ATTR_RECORD *a);
extern int ntfs_inode_get_times(ntfs_inode *ni, char *value, size_t size);
extern int ntfs_inode_set_times(ntfs_inode *ni, const char *value,
size_t size, int flags);
/* debugging */
#define debug_double_inode(num, type)
#define debug_cached_inode(ni)
#endif /* defined _NTFS_INODE_H */

View File

@ -1,35 +0,0 @@
/*
*
* Copyright (c) 2014 Jean-Pierre Andre
*
*/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program (in the main directory of the NTFS-3G
* distribution in the file COPYING); if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef IOCTL_H
#define IOCTL_H
/*
* Using an "unsigned long cmd" internally, like in <sys/ioctl.h> for Linux
* Note however that fuse truncates the arg to 32 bits, and that
* some commands (e.g. FITRIM) do not fit in a signed 32 bit field.
*/
int ntfs_ioctl(ntfs_inode *ni, unsigned long cmd, void *arg,
unsigned int flags, void *data);
#endif /* IOCTL_H */

File diff suppressed because it is too large Load Diff

View File

@ -42,7 +42,6 @@ extern runlist *ntfs_cluster_alloc(ntfs_volume *vol, VCN start_vcn, s64 count,
LCN start_lcn, const NTFS_CLUSTER_ALLOCATION_ZONES zone);
extern int ntfs_cluster_free_from_rl(ntfs_volume *vol, runlist *rl);
extern int ntfs_cluster_free_basic(ntfs_volume *vol, s64 lcn, s64 count);
extern int ntfs_cluster_free(ntfs_volume *vol, ntfs_attr *na, VCN start_vcn,
s64 count);

View File

@ -1,5 +1,5 @@
/*
* list.h - Linked list implementation. Part of the Linux-NTFS project.
* list.h - Linked list implementation. Originated from the Linux-NTFS project.
*
* Copyright (c) 2000-2002 Anton Altaparmakov and others
*
@ -14,7 +14,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program (in the main directory of the Linux-NTFS
* along with this program (in the main directory of the NTFS-3G
* distribution in the file COPYING); if not, write to the Free Software
* Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
@ -23,8 +23,8 @@
#define _NTFS_LIST_H
/**
* struct ntfs_list_head - Simple doubly linked list implementation.
*
* struct list_head - Simple doubly linked list implementation.
*
* Copied from Linux kernel 2.4.2-ac18 into Linux-NTFS (with minor
* modifications). - AIA
*
@ -34,21 +34,21 @@
* generate better code by using them directly rather than
* using the generic single-entry routines.
*/
struct ntfs_list_head {
struct ntfs_list_head *next, *prev;
struct list_head {
struct list_head *next, *prev;
};
#define NTFS_LIST_HEAD_INIT(name) { &(name), &(name) }
#define LIST_HEAD_INIT(name) { &(name), &(name) }
#define NTFS_LIST_HEAD(name) \
struct ntfs_list_head name = NTFS_LIST_HEAD_INIT(name)
#define LIST_HEAD(name) \
struct list_head name = LIST_HEAD_INIT(name)
#define NTFS_INIT_LIST_HEAD(ptr) do { \
#define INIT_LIST_HEAD(ptr) do { \
(ptr)->next = (ptr); (ptr)->prev = (ptr); \
} while (0)
/**
* __ntfs_list_add - Insert a new entry between two known consecutive entries.
* __list_add - Insert a new entry between two known consecutive entries.
* @new:
* @prev:
* @next:
@ -56,8 +56,8 @@ struct ntfs_list_head {
* This is only for internal list manipulation where we know the prev/next
* entries already!
*/
static __inline__ void __ntfs_list_add(struct ntfs_list_head * new,
struct ntfs_list_head * prev, struct ntfs_list_head * next)
static void __list_add(struct list_head * new,
struct list_head * prev, struct list_head * next)
{
next->prev = new;
new->next = next;
@ -66,35 +66,33 @@ static __inline__ void __ntfs_list_add(struct ntfs_list_head * new,
}
/**
* ntfs_list_add - add a new entry
* list_add - add a new entry
* @new: new entry to be added
* @head: list head to add it after
*
* Insert a new entry after the specified head.
* This is good for implementing stacks.
*/
static __inline__ void ntfs_list_add(struct ntfs_list_head *new,
struct ntfs_list_head *head)
static __inline__ void list_add(struct list_head *new, struct list_head *head)
{
__ntfs_list_add(new, head, head->next);
__list_add(new, head, head->next);
}
/**
* ntfs_list_add_tail - add a new entry
* list_add_tail - add a new entry
* @new: new entry to be added
* @head: list head to add it before
*
* Insert a new entry before the specified head.
* This is useful for implementing queues.
*/
static __inline__ void ntfs_list_add_tail(struct ntfs_list_head *new,
struct ntfs_list_head *head)
static __inline__ void list_add_tail(struct list_head *new, struct list_head *head)
{
__ntfs_list_add(new, head->prev, head);
__list_add(new, head->prev, head);
}
/**
* __ntfs_list_del -
* __list_del -
* @prev:
* @next:
*
@ -103,57 +101,57 @@ static __inline__ void ntfs_list_add_tail(struct ntfs_list_head *new,
* This is only for internal list manipulation where we know the prev/next
* entries already!
*/
static __inline__ void __ntfs_list_del(struct ntfs_list_head * prev,
struct ntfs_list_head * next)
static __inline__ void __list_del(struct list_head * prev,
struct list_head * next)
{
next->prev = prev;
prev->next = next;
}
/**
* ntfs_list_del - deletes entry from list.
* list_del - deletes entry from list.
* @entry: the element to delete from the list.
*
* Note: ntfs_list_empty on entry does not return true after this, the entry is
* in an undefined state.
* Note: list_empty on entry does not return true after this, the entry is in
* an undefined state.
*/
static __inline__ void ntfs_list_del(struct ntfs_list_head *entry)
static __inline__ void list_del(struct list_head *entry)
{
__ntfs_list_del(entry->prev, entry->next);
__list_del(entry->prev, entry->next);
}
/**
* ntfs_list_del_init - deletes entry from list and reinitialize it.
* list_del_init - deletes entry from list and reinitialize it.
* @entry: the element to delete from the list.
*/
static __inline__ void ntfs_list_del_init(struct ntfs_list_head *entry)
static __inline__ void list_del_init(struct list_head *entry)
{
__ntfs_list_del(entry->prev, entry->next);
NTFS_INIT_LIST_HEAD(entry);
__list_del(entry->prev, entry->next);
INIT_LIST_HEAD(entry);
}
/**
* ntfs_list_empty - tests whether a list is empty
* list_empty - tests whether a list is empty
* @head: the list to test.
*/
static __inline__ int ntfs_list_empty(struct ntfs_list_head *head)
static __inline__ int list_empty(struct list_head *head)
{
return head->next == head;
}
/**
* ntfs_list_splice - join two lists
* list_splice - join two lists
* @list: the new list to add.
* @head: the place to add it in the first list.
*/
static __inline__ void ntfs_list_splice(struct ntfs_list_head *list,
struct ntfs_list_head *head)
static void list_splice(struct list_head *list,
struct list_head *head)
{
struct ntfs_list_head *first = list->next;
struct list_head *first = list->next;
if (first != list) {
struct ntfs_list_head *last = list->prev;
struct ntfs_list_head *at = head->next;
struct list_head *last = list->prev;
struct list_head *at = head->next;
first->prev = head;
head->next = first;
@ -164,29 +162,29 @@ static __inline__ void ntfs_list_splice(struct ntfs_list_head *list,
}
/**
* ntfs_list_entry - get the struct for this entry
* @ptr: the &struct ntfs_list_head pointer.
* list_entry - get the struct for this entry
* @ptr: the &struct list_head pointer.
* @type: the type of the struct this is embedded in.
* @member: the name of the list_struct within the struct.
*/
#define ntfs_list_entry(ptr, type, member) \
#define list_entry(ptr, type, member) \
((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
/**
* ntfs_list_for_each - iterate over a list
* @pos: the &struct ntfs_list_head to use as a loop counter.
* list_for_each - iterate over a list
* @pos: the &struct list_head to use as a loop counter.
* @head: the head for your list.
*/
#define ntfs_list_for_each(pos, head) \
#define list_for_each(pos, head) \
for (pos = (head)->next; pos != (head); pos = pos->next)
/**
* ntfs_list_for_each_safe - iterate over a list safe against removal of list entry
* @pos: the &struct ntfs_list_head to use as a loop counter.
* @n: another &struct ntfs_list_head to use as temporary storage
* list_for_each_safe - iterate over a list safe against removal of list entry
* @pos: the &struct list_head to use as a loop counter.
* @n: another &struct list_head to use as temporary storage
* @head: the head for your list.
*/
#define ntfs_list_for_each_safe(pos, n, head) \
#define list_for_each_safe(pos, n, head) \
for (pos = (head)->next, n = pos->next; pos != (head); \
pos = n, n = pos->next)

View File

@ -2,7 +2,6 @@
* logfile.h - Exports for $LogFile handling. Originated from the Linux-NTFS project.
*
* Copyright (c) 2000-2005 Anton Altaparmakov
* Copyright (c) 2016 Jean-Pierre Andre
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
@ -94,8 +93,7 @@ typedef struct {
version is 1. */
/* 28*/ sle16 major_ver; /* Log file major version. We only support
version 1.1. */
/* 30*/ le16 usn;
/* sizeof() = 32 (0x20) bytes */
/* sizeof() = 30 (0x1e) bytes */
} __attribute__((__packed__)) RESTART_PAGE_HEADER;
/*
@ -103,8 +101,8 @@ typedef struct {
* in this particular client array. Also inside the client records themselves,
* this means that there are no client records preceding or following this one.
*/
#define LOGFILE_NO_CLIENT const_cpu_to_le16(0xffff)
#define LOGFILE_NO_CLIENT_CPU 0xffff
#define LOGFILE_NO_CLIENT const_cpu_to_le16(LOGFILE_NO_CLIENT_CPU)
/*
* These are the so far known RESTART_AREA_* flags (16-bit) which contain
@ -310,36 +308,35 @@ typedef struct {
typedef struct {
/* 0 NTFS_RECORD; -- Unfolded here as gcc doesn't like unnamed structs. */
NTFS_RECORD_TYPES magic;/* Usually the magic is "RCRD". */
le16 usa_ofs; /* See NTFS_RECORD definition in layout.h.
u16 usa_ofs; /* See NTFS_RECORD definition in layout.h.
When creating, set this to be immediately
after this header structure (without any
alignment). */
le16 usa_count; /* See NTFS_RECORD definition in layout.h. */
u16 usa_count; /* See NTFS_RECORD definition in layout.h. */
union {
leLSN last_lsn;
sle64 file_offset;
LSN last_lsn;
s64 file_offset;
} __attribute__((__packed__)) copy;
le32 flags;
le16 page_count;
le16 page_position;
le16 next_record_offset;
le16 reserved[3];
leLSN last_end_lsn;
u32 flags;
u16 page_count;
u16 page_position;
union {
struct {
u16 next_record_offset;
u8 reserved[6];
LSN last_end_lsn;
} __attribute__((__packed__)) packed;
} __attribute__((__packed__)) header;
} __attribute__((__packed__)) RECORD_PAGE_HEADER;
/**
* enum LOG_RECORD_FLAGS - Possible 16-bit flags for log records.
*
* Some flags describe what kind of update is being logged.
*
* (Or is it log record pages?)
*/
typedef enum {
LOG_RECORD_MULTI_PAGE = const_cpu_to_le16(0x0001), /* ??? */
/* The flags below were introduced in Windows 10 */
LOG_RECORD_DELETING = const_cpu_to_le16(0x0002),
LOG_RECORD_ADDING = const_cpu_to_le16(0x0004),
LOG_RECORD_SIZE_PLACE_HOLDER = 0xffff,
/* This has nothing to do with the log record. It is only so
gcc knows to make the flags 16-bit. */
@ -349,120 +346,47 @@ typedef enum {
* struct LOG_CLIENT_ID - The log client id structure identifying a log client.
*/
typedef struct {
le16 seq_number;
le16 client_index;
u16 seq_number;
u16 client_index;
} __attribute__((__packed__)) LOG_CLIENT_ID;
/*
* LOG_RECORD_TYPE : types of log records
*/
enum {
LOG_STANDARD = const_cpu_to_le32(1),
LOG_CHECKPOINT = const_cpu_to_le32(2),
LOG_RECORD_TYPE_PLACE_HOLDER = 0xffffffffU
} ;
typedef le32 LOG_RECORD_TYPE;
/*
* ATTRIBUTE_FLAGS : flags describing the kind of NTFS record
* is being updated.
* These flags were introduced in Vista, only two flags are known?
*/
enum {
ACTS_ON_MFT = const_cpu_to_le16(2),
ACTS_ON_INDX = const_cpu_to_le16(8),
ATTRIBUTE_FLAGS_PLACE_HOLDER = 0xffff,
} ;
typedef le16 ATTRIBUTE_FLAGS;
#define LOG_RECORD_HEAD_SZ 0x30 /* size of header of struct LOG_RECORD */
/**
* struct LOG_RECORD - Log record header.
*
* Each log record seems to have a constant size of 0x70 bytes.
*/
typedef struct {
leLSN this_lsn;
leLSN client_previous_lsn;
leLSN client_undo_next_lsn;
le32 client_data_length;
LSN this_lsn;
LSN client_previous_lsn;
LSN client_undo_next_lsn;
u32 client_data_length;
LOG_CLIENT_ID client_id;
LOG_RECORD_TYPE record_type;
le32 transaction_id;
LOG_RECORD_FLAGS log_record_flags;
le16 reserved_or_alignment[3];
u32 record_type;
u32 transaction_id;
u16 flags;
u16 reserved_or_alignment[3];
/* Now are at ofs 0x30 into struct. */
le16 redo_operation;
le16 undo_operation;
le16 redo_offset;
le16 redo_length;
union {
struct {
le16 undo_offset;
le16 undo_length;
le16 target_attribute;
le16 lcns_to_follow; /* Number of lcn_list entries
u16 redo_operation;
u16 undo_operation;
u16 redo_offset;
u16 redo_length;
u16 undo_offset;
u16 undo_length;
u16 target_attribute;
u16 lcns_to_follow; /* Number of lcn_list entries
following this entry. */
/* Now at ofs 0x40. */
le16 record_offset;
le16 attribute_offset;
le16 cluster_index;
ATTRIBUTE_FLAGS attribute_flags;
leVCN target_vcn;
u16 record_offset;
u16 attribute_offset;
u32 alignment_or_reserved;
VCN target_vcn;
/* Now at ofs 0x50. */
leLCN lcn_list[0]; /* Only present if lcns_to_follow
is not 0. */
} __attribute__((__packed__));
struct {
leLSN transaction_lsn;
leLSN attributes_lsn;
leLSN names_lsn;
leLSN dirty_pages_lsn;
le64 unknown_list[0];
} __attribute__((__packed__));
} __attribute__((__packed__));
struct { /* Only present if lcns_to_follow
is not 0. */
LCN lcn;
} __attribute__((__packed__)) lcn_list[0];
} __attribute__((__packed__)) LOG_RECORD;
/**
* struct BITMAP_ACTION - Bitmap change being logged
*/
struct BITMAP_ACTION {
le32 firstbit;
le32 count;
} ;
/**
* struct ATTR - Attribute record.
*
* The format of an attribute record has changed from Windows 10.
* The old format was 44 bytes long, despite having 8 bytes fields,
* and this leads to alignment problems in arrays.
* This problem does not occur in the new format, which is shorter.
* The format being used can generally be determined from size.
*/
typedef struct { /* Format up to Win10 (44 bytes) */
le64 unknown1;
le64 unknown2;
le64 inode;
leLSN lsn;
le32 unknown3;
le32 type;
le32 unknown4;
} __attribute__((__packed__)) ATTR_OLD;
typedef struct { /* Format since Win10 (40 bytes) */
le64 unknown1;
le64 unknown2;
le32 type;
le32 unknown3;
le64 inode;
leLSN lsn;
} __attribute__((__packed__)) ATTR_NEW;
extern BOOL ntfs_check_logfile(ntfs_attr *log_na, RESTART_PAGE_HEADER **rp);
extern BOOL ntfs_is_logfile_clean(ntfs_attr *log_na, RESTART_PAGE_HEADER *rp);
extern int ntfs_empty_logfile(ntfs_attr *na);

View File

@ -1,8 +1,7 @@
/*
* logging.h - Centralised logging. Originated from the Linux-NTFS project.
*
* Copyright (c) 2005 Richard Russon
* Copyright (c) 2007-2008 Szabolcs Szakacsits
* Copyright (c) 2005 Richard Russon
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
@ -38,8 +37,7 @@ typedef int (ntfs_log_handler)(const char *function, const char *file, int line,
u32 level, void *data, const char *format, va_list args);
/* Set the logging handler from one of the functions, below. */
void ntfs_log_set_handler(ntfs_log_handler *handler
__attribute__((format(printf, 6, 0))));
void ntfs_log_set_handler(ntfs_log_handler *handler);
/* Logging handlers */
ntfs_log_handler ntfs_log_handler_syslog __attribute__((format(printf, 6, 0)));
@ -77,8 +75,6 @@ int ntfs_log_redirect(const char *function, const char *file, int line,
#define NTFS_LOG_LEVEL_ERROR (1 << 7) /* Operation failed, no damage done */
#define NTFS_LOG_LEVEL_PERROR (1 << 8) /* Message : standard error description */
#define NTFS_LOG_LEVEL_CRITICAL (1 << 9) /* Operation failed,damage may have occurred */
#define NTFS_LOG_LEVEL_ENTER (1 << 10) /* Enter a function */
#define NTFS_LOG_LEVEL_LEAVE (1 << 11) /* Leave a function */
/* Logging style flags - Manage the style of the output */
#define NTFS_LOG_FLAG_PREFIX (1 << 0) /* Prefix messages with "ERROR: ", etc */
@ -86,6 +82,7 @@ int ntfs_log_redirect(const char *function, const char *file, int line,
#define NTFS_LOG_FLAG_LINE (1 << 2) /* Show the line number of the message */
#define NTFS_LOG_FLAG_FUNCTION (1 << 3) /* Show the function name containing the message */
#define NTFS_LOG_FLAG_ONLYNAME (1 << 4) /* Only display the filename, not the pathname */
#define NTFS_LOG_FLAG_COLOUR (1 << 5) /* Colour highlight some messages */
/* Macros to simplify logging. One for each level defined above.
* Note, ntfs_log_debug/trace have effect only if DEBUG is defined.
@ -105,17 +102,10 @@ int ntfs_log_redirect(const char *function, const char *file, int line,
#ifdef DEBUG
#define ntfs_log_debug(FORMAT, ARGS...) ntfs_log_redirect(__FUNCTION__,__FILE__,__LINE__,NTFS_LOG_LEVEL_DEBUG,NULL,FORMAT,##ARGS)
#define ntfs_log_trace(FORMAT, ARGS...) ntfs_log_redirect(__FUNCTION__,__FILE__,__LINE__,NTFS_LOG_LEVEL_TRACE,NULL,FORMAT,##ARGS)
#define ntfs_log_enter(FORMAT, ARGS...) ntfs_log_redirect(__FUNCTION__,__FILE__,__LINE__,NTFS_LOG_LEVEL_ENTER,NULL,FORMAT,##ARGS)
#define ntfs_log_leave(FORMAT, ARGS...) ntfs_log_redirect(__FUNCTION__,__FILE__,__LINE__,NTFS_LOG_LEVEL_LEAVE,NULL,FORMAT,##ARGS)
#else
#define ntfs_log_debug(FORMAT, ARGS...)do {} while (0)
#define ntfs_log_trace(FORMAT, ARGS...)do {} while (0)
#define ntfs_log_enter(FORMAT, ARGS...)do {} while (0)
#define ntfs_log_leave(FORMAT, ARGS...)do {} while (0)
#endif /* DEBUG */
void ntfs_log_early_error(const char *format, ...)
__attribute__((format(printf, 1, 2)));
#endif /* _LOGGING_H_ */

View File

@ -3,7 +3,7 @@
*
* Copyright (c) 2000-2002 Anton Altaparmakov
* Copyright (c) 2004-2005 Richard Russon
* Copyright (c) 2006-2008 Szabolcs Szakacsits
* Copyright (c) 2006 Szabolcs Szakacsits
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
@ -27,7 +27,6 @@
#include "volume.h"
#include "inode.h"
#include "layout.h"
#include "logging.h"
extern int ntfs_mft_records_read(const ntfs_volume *vol, const MFT_REF mref,
const s64 count, MFT_RECORD *b);
@ -50,17 +49,9 @@ extern int ntfs_mft_records_read(const ntfs_volume *vol, const MFT_REF mref,
static __inline__ int ntfs_mft_record_read(const ntfs_volume *vol,
const MFT_REF mref, MFT_RECORD *b)
{
int ret;
ntfs_log_enter("Entering for inode %lld\n", (long long)MREF(mref));
ret = ntfs_mft_records_read(vol, mref, 1, b);
ntfs_log_leave("\n");
return ret;
return ntfs_mft_records_read(vol, mref, 1, b);
}
extern int ntfs_mft_record_check(const ntfs_volume *vol, const MFT_REF mref,
MFT_RECORD *m);
extern int ntfs_file_record_read(const ntfs_volume *vol, const MFT_REF mref,
MFT_RECORD **mrec, ATTR_RECORD **attr);
@ -85,12 +76,7 @@ extern int ntfs_mft_records_write(const ntfs_volume *vol, const MFT_REF mref,
static __inline__ int ntfs_mft_record_write(const ntfs_volume *vol,
const MFT_REF mref, MFT_RECORD *b)
{
int ret;
ntfs_log_enter("Entering for inode %lld\n", (long long)MREF(mref));
ret = ntfs_mft_records_write(vol, mref, 1, b);
ntfs_log_leave("\n");
return ret;
return ntfs_mft_records_write(vol, mref, 1, b);
}
/**
@ -124,8 +110,6 @@ extern int ntfs_mft_record_format(const ntfs_volume *vol, const MFT_REF mref);
extern ntfs_inode *ntfs_mft_record_alloc(ntfs_volume *vol, ntfs_inode *base_ni);
extern ntfs_inode *ntfs_mft_rec_alloc(ntfs_volume *vol, BOOL mft_data);
extern int ntfs_mft_record_free(ntfs_volume *vol, ntfs_inode *ni);
extern int ntfs_mft_usn_dec(MFT_RECORD *mrec);

View File

@ -1,32 +1,8 @@
/*
* misc.h : miscellaneous exports
* - memory allocation
*
* Copyright (c) 2008 Jean-Pierre Andre
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program/include file 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 (in the main directory of the NTFS-3G
* distribution in the file COPYING); if not, write to the Free Software
* Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _NTFS_MISC_H_
#define _NTFS_MISC_H_
void *ntfs_calloc(size_t size);
void *ntfs_malloc(size_t size);
void *ntfs_realloc(void *ptr, size_t size);
void ntfs_free(void *ptr);
#endif /* _NTFS_MISC_H_ */

View File

@ -25,11 +25,8 @@
#include "types.h"
#include "layout.h"
#include "volume.h"
extern int ntfs_mst_post_read_fixup(NTFS_RECORD *b, const u32 size);
extern int ntfs_mst_post_read_fixup_warn(NTFS_RECORD *b, const u32 size,
BOOL warn);
extern int ntfs_mst_pre_write_fixup(NTFS_RECORD *b, const u32 size);
extern void ntfs_mst_post_write_fixup(NTFS_RECORD *b);

View File

@ -3,7 +3,6 @@
*
* Copyright (c) 2005 Anton Altaparmakov
* Copyright (c) 2005 Yura Pakhuchiy
* Copyright (c) 2010 Jean-Pierre Andre
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
@ -27,105 +26,44 @@
#ifdef HAVE_TIME_H
#include <time.h>
#endif
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#ifdef HAVE_GETTIMEOFDAY
#include <sys/time.h>
#endif
#include "types.h"
/*
* assume "struct timespec" is not defined if st_mtime is not defined
*/
#if !defined(st_mtime) & !defined(__timespec_defined)
struct timespec {
time_t tv_sec;
long tv_nsec;
} ;
#endif
/*
* There are four times more conversions of internal representation
* to ntfs representation than any other conversion, so the most
* efficient internal representation is ntfs representation
* (with low endianness)
*/
typedef sle64 ntfs_time;
#define NTFS_TIME_OFFSET ((s64)(369 * 365 + 89) * 24 * 3600 * 10000000)
/**
* ntfs2timespec - Convert an NTFS time to Unix time
* ntfs2utc - Convert an NTFS time to Unix time
* @ntfs_time: An NTFS time in 100ns units since 1601
*
* NTFS stores times as the number of 100ns intervals since January 1st 1601 at
* 00:00 UTC. This system will not suffer from Y2K problems until ~57000AD.
*
* Return: A Unix time (number of seconds since 1970, and nanoseconds)
* Return: n A Unix time (number of seconds since 1970)
*/
static __inline__ struct timespec ntfs2timespec(ntfs_time ntfstime)
static __inline__ time_t ntfs2utc(s64 ntfs_time)
{
struct timespec spec;
s64 cputime;
cputime = sle64_to_cpu(ntfstime);
spec.tv_sec = (cputime - (NTFS_TIME_OFFSET)) / 10000000;
spec.tv_nsec = (cputime - (NTFS_TIME_OFFSET)
- (s64)spec.tv_sec*10000000)*100;
/* force zero nsec for overflowing dates */
if ((spec.tv_nsec < 0) || (spec.tv_nsec > 999999999))
spec.tv_nsec = 0;
return (spec);
return (sle64_to_cpu(ntfs_time) - (NTFS_TIME_OFFSET)) / 10000000;
}
/**
* timespec2ntfs - Convert Linux time to NTFS time
* utc2ntfs - Convert Linux time to NTFS time
* @utc_time: Linux time to convert to NTFS
*
* Convert the Linux time @utc_time to its corresponding NTFS time.
*
* Linux stores time in a long at present and measures it as the number of
* 1-second intervals since 1st January 1970, 00:00:00 UTC
* with a separated non-negative nanosecond value
* 1-second intervals since 1st January 1970, 00:00:00 UTC.
*
* NTFS uses Microsoft's standard time format which is stored in a sle64 and is
* NTFS uses Microsoft's standard time format which is stored in a s64 and is
* measured as the number of 100 nano-second intervals since 1st January 1601,
* 00:00:00 UTC.
*
* Return: An NTFS time (100ns units since Jan 1601)
* Return: n An NTFS time (100ns units since Jan 1601)
*/
static __inline__ ntfs_time timespec2ntfs(struct timespec spec)
static __inline__ s64 utc2ntfs(time_t utc_time)
{
s64 units;
units = (s64)spec.tv_sec * 10000000
+ NTFS_TIME_OFFSET + spec.tv_nsec/100;
return (cpu_to_sle64(units));
}
/*
* Return the current time in ntfs format
*/
static __inline__ ntfs_time ntfs_current_time(void)
{
struct timespec now;
#if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_SYS_CLOCK_GETTIME)
clock_gettime(CLOCK_REALTIME, &now);
#elif defined(HAVE_GETTIMEOFDAY)
struct timeval microseconds;
gettimeofday(&microseconds, (struct timezone*)NULL);
now.tv_sec = microseconds.tv_sec;
now.tv_nsec = microseconds.tv_usec*1000;
#else
now.tv_sec = time((time_t*)NULL);
now.tv_nsec = 0;
#endif
return (timespec2ntfs(now));
/* Convert to 100ns intervals and then add the NTFS time offset. */
return cpu_to_sle64((s64)utc_time * 10000000 + NTFS_TIME_OFFSET);
}
#endif /* _NTFS_NTFSTIME_H */

View File

@ -1,35 +0,0 @@
/*
*
* Copyright (c) 2008 Jean-Pierre Andre
*
*/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program (in the main directory of the NTFS-3G
* distribution in the file COPYING); if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef OBJECT_ID_H
#define OBJECT_ID_H
int ntfs_get_ntfs_object_id(ntfs_inode *ni, char *value, size_t size);
int ntfs_set_ntfs_object_id(ntfs_inode *ni, const char *value,
size_t size, int flags);
int ntfs_remove_ntfs_object_id(ntfs_inode *ni);
int ntfs_delete_object_id_index(ntfs_inode *ni);
#endif /* OBJECT_ID_H */

View File

@ -1,163 +0,0 @@
/*
* param.h - Parameter values for ntfs-3g
*
* Copyright (c) 2009-2010 Jean-Pierre Andre
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program/include file 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 (in the main directory of the NTFS-3G
* distribution in the file COPYING); if not, write to the Free Software
* Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _NTFS_PARAM_H
#define _NTFS_PARAM_H
#define CACHE_INODE_SIZE 32 /* inode cache, zero or >= 3 and not too big */
#define CACHE_NIDATA_SIZE 64 /* idata cache, zero or >= 3 and not too big */
#define CACHE_LOOKUP_SIZE 64 /* lookup cache, zero or >= 3 and not too big */
#define CACHE_SECURID_SIZE 16 /* securid cache, zero or >= 3 and not too big */
#define CACHE_LEGACY_SIZE 8 /* legacy cache size, zero or >= 3 and not too big */
#define FORCE_FORMAT_v1x 0 /* Insert security data as in NTFS v1.x */
#define OWNERFROMACL 1 /* Get the owner from ACL (not Windows owner) */
/* default security sub-authorities */
enum {
DEFSECAUTH1 = -1153374643, /* 3141592653 */
DEFSECAUTH2 = 589793238,
DEFSECAUTH3 = 462843383,
DEFSECBASE = 10000
};
/*
* Parameters for formatting
*/
/* Up to Windows 10, the cluster size was limited to 64K */
#define NTFS_MAX_CLUSTER_SIZE 2097152 /* Windows 10 Creators allows 2MB */
/*
* Parameters for compression
*/
/* default option for compression */
#define DEFAULT_COMPRESSION 1
/* (log2 of) number of clusters in a compression block for new files */
#define STANDARD_COMPRESSION_UNIT 4
/* maximum cluster size for allowing compression for new files */
#define MAX_COMPRESSION_CLUSTER_SIZE 4096
/*
* Parameters for default options
*/
#define DEFAULT_DMTIME 60 /* default 1mn for delay_mtime */
/*
* Use of big write buffers
*
* With small volumes, the cluster allocator may fail to allocate
* enough clusters when the volume is nearly full. At most a run
* can be allocated per bitmap chunk. So, there is a danger when the
* number of chunks (capacity/(32768*clsiz)) is less than the number
* of clusters in the biggest write buffer (131072/clsiz). Hence
* a safe minimal capacity is 4GB
*/
#define SAFE_CAPACITY_FOR_BIG_WRITES 0x100000000LL
/*
* Parameters for runlists
*/
/* only update the final extent of a runlist when appending data */
#define PARTIAL_RUNLIST_UPDATING 1
/*
* Parameters for upper-case table
*/
/* Create upper-case tables as defined by Windows 6.1 (Win7) */
#define UPCASE_MAJOR 6
#define UPCASE_MINOR 1
/*
* Parameters for user and xattr mappings
*/
#define XATTRMAPPINGFILE ".NTFS-3G/XattrMapping" /* default mapping file */
/*
* Parameters for path canonicalization
*/
#define MAPPERNAMELTH 256
/*
* Permission checking modes for high level and low level
*
* The choices for high and low lowel are independent, they have
* no effect on the library
*
* Stick to the recommended values unless you understand the consequences
* on protection and performances. Use of cacheing is good for
* performances, but bad on security with internal fuse or external
* fuse older than 2.8
*
* On Linux, cacheing is discouraged for the high level interface
* in order to get proper support of hard links. As a consequence,
* having access control in the file system leads to fewer requests
* to the file system and fewer context switches.
*
* Irrespective of the selected mode, cacheing is always used
* in read-only mounts
*
* Possible values for high level :
* 1 : no cache, kernel control (recommended)
* 4 : no cache, file system control
* 6 : kernel/fuse cache, file system control (OpenIndiana only)
* 7 : no cache, kernel control for ACLs
*
* Possible values for low level :
* 2 : no cache, kernel control
* 3 : use kernel/fuse cache, kernel control (recommended)
* 5 : no cache, file system control
* 6 : kernel/fuse cache, file system control (OpenIndiana only)
* 8 : no cache, kernel control for ACLs
* 9 : kernel/fuse cache, kernel control for ACLs (target)
*
* Use of options 7, 8 and 9 requires a fuse module upgrade
* When Posix ACLs are selected in the configure options, a value
* of 6 is added in the mount report.
*/
#define TIMEOUT_RO 600 /* Attribute time out for read-only mounts */
#if defined(__sun) && defined(__SVR4)
/*
* Access control by kernel is not implemented on OpenIndiana,
* however care is taken of cacheing hard-linked files.
*/
#define HPERMSCONFIG 6
#define LPERMSCONFIG 6
#else /* defined(__sun) && defined(__SVR4) */
/*
* Cacheing by kernel is buggy on Linux when access control is done
* by the file system, and also when using hard-linked files on
* the fuse high level interface.
* Also ACL checks by recent kernels do not prove satisfactory.
*/
#define HPERMSCONFIG 1
#define LPERMSCONFIG 3
#endif /* defined(__sun) && defined(__SVR4) */
#endif /* defined _NTFS_PARAM_H */

View File

@ -1,194 +0,0 @@
/*
* plugin.h : define interface for plugin development
*
* Copyright (c) 2015-2021 Jean-Pierre Andre
*
*/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program (in the main directory of the NTFS-3G
* distribution in the file COPYING); if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* This file defines the interface to ntfs-3g plugins which
* add support for processing some type of reparse points.
*/
#ifndef _NTFS_PLUGIN_H
#define _NTFS_PLUGIN_H
#include "layout.h"
#include "inode.h"
#include "dir.h"
struct fuse_file_info;
struct stat;
/*
* The plugin operations currently defined.
* These functions should return a non-negative value when they
* succeed, or a negative errno value when they fail.
* They must not close or free their arguments.
* The file system must be left in a consistent state after
* each individual call.
* If an operation is not defined, an EOPNOTSUPP error is
* returned to caller.
*/
typedef struct plugin_operations {
/*
* Set the attributes st_size, st_blocks and st_mode
* into a struct stat. The returned st_mode must at least
* define the file type. Depending on the permissions options
* used for mounting, the umask will be applied to the returned
* permissions, or the permissions will be changed according
* to the ACL set on the file.
*/
int (*getattr)(ntfs_inode *ni, const REPARSE_POINT *reparse,
struct stat *stbuf);
/*
* Open a file for reading or writing
* The field fi->flags indicates the kind of opening.
* The field fi->fh may be used to store some information which
* will be available to subsequent reads and writes. When used
* this field must be non-null.
* The returned value is zero for success and a negative errno
* value for failure.
*/
int (*open)(ntfs_inode *ni, const REPARSE_POINT *reparse,
struct fuse_file_info *fi);
/*
* Release an open file or directory
* This is only called if fi->fh has been set to a non-null
* value while opening. It may be used to free some context
* specific to the open file or directory
* The returned value is zero for success or a negative errno
* value for failure.
*/
int (*release)(ntfs_inode *ni, const REPARSE_POINT *reparse,
struct fuse_file_info *fi);
/*
* Read from an open file
* The returned value is the count of bytes which were read
* or a negative errno value for failure.
* If the returned value is positive, the access time stamp
* will be updated after the call.
*/
int (*read)(ntfs_inode *ni, const REPARSE_POINT *reparse,
char *buf, size_t size,
off_t offset, struct fuse_file_info *fi);
/*
* Write to an open file
* The file system must be left consistent after each write call,
* the file itself must be at least deletable if the application
* writing to it is killed for some reason.
* The returned value is the count of bytes which were written
* or a negative errno value for failure.
* If the returned value is positive, the modified time stamp
* will be updated after the call.
*/
int (*write)(ntfs_inode *ni, const REPARSE_POINT *reparse,
const char *buf, size_t size,
off_t offset, struct fuse_file_info *fi);
/*
* Get a symbolic link
* The symbolic link must be returned in an allocated buffer,
* encoded in a zero terminated multibyte string compatible
* with the locale mount option.
* The returned value is zero for success or a negative errno
* value for failure.
*/
int (*readlink)(ntfs_inode *ni, const REPARSE_POINT *reparse,
char **pbuf);
/*
* Truncate a file (shorten or append zeroes)
* The returned value is zero for success or a negative errno
* value for failure.
* If the returned value is zero, the modified time stamp
* will be updated after the call.
*/
int (*truncate)(ntfs_inode *ni, const REPARSE_POINT *reparse,
off_t size);
/*
* Open a directory
* The field fi->flags indicates the kind of opening.
* The field fi->fh may be used to store some information which
* will be available to subsequent readdir(). When used
* this field must be non-null and freed in release().
* The returned value is zero for success and a negative errno
* value for failure.
*/
int (*opendir)(ntfs_inode *ni, const REPARSE_POINT *reparse,
struct fuse_file_info *fi);
/*
* Get entries from a directory
*
* Use the filldir() function with fillctx argument to return
* the directory entries.
* Names "." and ".." are expected to be returned.
* The returned value is zero for success and a negative errno
* value for failure.
*/
int (*readdir)(ntfs_inode *ni, const REPARSE_POINT *reparse,
s64 *pos, void *fillctx, ntfs_filldir_t filldir,
struct fuse_file_info *fi);
/*
* Create a new file of any type
*
* The returned value is a pointer to the inode created, or
* NULL if failed, with errno telling why.
*/
ntfs_inode *(*create)(ntfs_inode *dir_ni, const REPARSE_POINT *reparse,
le32 securid, ntfschar *name, int name_len,
mode_t type);
/*
* Link a new name to a file or directory
* Linking a directory is needed for renaming a directory
* The returned value is zero for success or a negative errno
* value for failure.
* If the returned value is zero, the modified time stamp
* will be updated after the call.
*/
int (*link)(ntfs_inode *dir_ni, const REPARSE_POINT *reparse,
ntfs_inode *ni, ntfschar *name, int name_len);
/*
* Unlink a name from a directory
* The argument pathname may be NULL
* The returned value is zero for success or a negative errno
* value for failure.
*/
int (*unlink)(ntfs_inode *dir_ni, const REPARSE_POINT *reparse,
const char *pathname,
ntfs_inode *ni, ntfschar *name, int name_len);
} plugin_operations_t;
/*
* Plugin initialization routine
* Returns the entry table if successful, otherwise returns NULL
* and sets errno (e.g. to EINVAL if the tag is not supported by
* the plugin.)
*/
typedef const struct plugin_operations *(*plugin_init_t)(le32 tag);
const struct plugin_operations *init(le32 tag);
#endif /* _NTFS_PLUGIN_H */

View File

@ -1,24 +0,0 @@
/*
* realpath.h - realpath() aware of device mapper
*/
#ifndef REALPATH_H
#define REALPATH_H
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef HAVE_REALPATH
#define ntfs_realpath realpath
#else
extern char *ntfs_realpath(const char *path, char *resolved_path);
#endif
#ifdef linux
extern char *ntfs_realpath_canonicalize(const char *path, char *resolved_path);
#else
#define ntfs_realpath_canonicalize ntfs_realpath
#endif
#endif /* REALPATH_H */

View File

@ -1,51 +0,0 @@
/*
*
* Copyright (c) 2008 Jean-Pierre Andre
*
*/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program (in the main directory of the NTFS-3G
* distribution in the file COPYING); if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef REPARSE_H
#define REPARSE_H
char *ntfs_make_symlink(ntfs_inode *ni, const char *mnt_point);
BOOL ntfs_possible_symlink(ntfs_inode *ni);
int ntfs_get_ntfs_reparse_data(ntfs_inode *ni, char *value, size_t size);
char *ntfs_get_abslink(ntfs_volume *vol, ntfschar *junction,
int count, const char *mnt_point, BOOL isdir);
REPARSE_POINT *ntfs_get_reparse_point(ntfs_inode *ni);
int ntfs_reparse_check_wsl(ntfs_inode *ni, const REPARSE_POINT *reparse);
int ntfs_reparse_set_wsl_symlink(ntfs_inode *ni,
const ntfschar *target, int target_len);
int ntfs_reparse_set_wsl_not_symlink(ntfs_inode *ni, mode_t mode);
int ntfs_set_ntfs_reparse_data(ntfs_inode *ni, const char *value,
size_t size, int flags);
int ntfs_remove_ntfs_reparse_data(ntfs_inode *ni);
int ntfs_delete_reparse_index(ntfs_inode *ni);
#endif /* REPARSE_H */

View File

@ -49,15 +49,12 @@ struct _runlist_element {/* In memory vcn to lcn mapping structure element. */
s64 length; /* Run length in clusters. */
};
extern runlist_element *ntfs_rl_extend(ntfs_attr *na, runlist_element *rl,
int more_entries);
extern LCN ntfs_rl_vcn_to_lcn(const runlist_element *rl, const VCN vcn);
extern s64 ntfs_rl_pread(const ntfs_volume *vol, const runlist_element *rl,
const s64 pos, s64 count, void *b);
extern s64 ntfs_rl_pwrite(const ntfs_volume *vol, const runlist_element *rl,
s64 ofs, const s64 pos, s64 count, void *b);
const s64 pos, s64 count, void *b);
extern runlist_element *ntfs_runlists_merge(runlist_element *drl,
runlist_element *srl);
@ -68,14 +65,14 @@ extern runlist_element *ntfs_mapping_pairs_decompress(const ntfs_volume *vol,
extern int ntfs_get_nr_significant_bytes(const s64 n);
extern int ntfs_get_size_for_mapping_pairs(const ntfs_volume *vol,
const runlist_element *rl, const VCN start_vcn, int max_size);
const runlist_element *rl, const VCN start_vcn);
extern int ntfs_write_significant_bytes(u8 *dst, const u8 *dst_max,
const s64 n);
extern int ntfs_mapping_pairs_build(const ntfs_volume *vol, u8 *dst,
const int dst_len, const runlist_element *rl,
const VCN start_vcn, runlist_element const **stop_rl);
const VCN start_vcn, VCN *const stop_vcn);
extern int ntfs_rl_truncate(runlist **arl, const VCN start_vcn);

View File

@ -4,7 +4,6 @@
*
* Copyright (c) 2004 Anton Altaparmakov
* Copyright (c) 2005-2006 Szabolcs Szakacsits
* Copyright (c) 2007-2010 Jean-Pierre Andre
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
@ -28,311 +27,32 @@
#include "types.h"
#include "layout.h"
#include "inode.h"
#include "dir.h"
#include "endians.h"
#ifndef POSIXACLS
#define POSIXACLS 0
#endif
/*
* item in the mapping list
*/
struct MAPPING {
struct MAPPING *next;
int xid; /* linux id : uid or gid */
SID *sid; /* Windows id : usid or gsid */
int grcnt; /* group count (for users only) */
gid_t *groups; /* groups which the user is member of */
};
/*
* Entry in the permissions cache
* Note : this cache is not organized as a generic cache
*/
struct CACHED_PERMISSIONS {
uid_t uid;
gid_t gid;
le32 inh_fileid;
le32 inh_dirid;
#if POSIXACLS
struct POSIX_SECURITY *pxdesc;
unsigned int pxdescsize:16;
#endif
unsigned int mode:12;
unsigned int valid:1;
} ;
/*
* Entry in the permissions cache for directories with no security_id
*/
struct CACHED_PERMISSIONS_LEGACY {
struct CACHED_PERMISSIONS_LEGACY *next;
struct CACHED_PERMISSIONS_LEGACY *previous;
void *variable;
size_t varsize;
union ALIGNMENT payload[0];
/* above fields must match "struct CACHED_GENERIC" */
u64 mft_no;
struct CACHED_PERMISSIONS perm;
} ;
/*
* Entry in the securid cache
*/
struct CACHED_SECURID {
struct CACHED_SECURID *next;
struct CACHED_SECURID *previous;
void *variable;
size_t varsize;
union ALIGNMENT payload[0];
/* above fields must match "struct CACHED_GENERIC" */
uid_t uid;
gid_t gid;
unsigned int dmode;
le32 securid;
} ;
/*
* Header of the security cache
* (has no cache structure by itself)
*/
struct CACHED_PERMISSIONS_HEADER {
unsigned int last;
/* statistics for permissions */
unsigned long p_writes;
unsigned long p_reads;
unsigned long p_hits;
} ;
/*
* The whole permissions cache
*/
struct PERMISSIONS_CACHE {
struct CACHED_PERMISSIONS_HEADER head;
struct CACHED_PERMISSIONS *cachetable[1]; /* array of variable size */
} ;
/*
* Security flags values
*/
enum {
SECURITY_DEFAULT, /* rely on fuse for permissions checking */
SECURITY_RAW, /* force same ownership/permissions on files */
SECURITY_ACL, /* enable Posix ACLs (when compiled in) */
SECURITY_ADDSECURIDS, /* upgrade old security descriptors */
SECURITY_STATICGRPS, /* use static groups for access control */
SECURITY_WANTED /* a security related option was present */
} ;
/*
* Security context, needed by most security functions
*/
enum { MAPUSERS, MAPGROUPS, MAPCOUNT } ;
struct SECURITY_CONTEXT {
ntfs_volume *vol;
struct MAPPING *mapping[MAPCOUNT];
struct PERMISSIONS_CACHE **pseccache;
uid_t uid; /* uid of user requesting (not the mounter) */
gid_t gid; /* gid of user requesting (not the mounter) */
pid_t tid; /* thread id of thread requesting */
mode_t umask; /* umask of requesting thread */
} ;
#if POSIXACLS
/*
* Posix ACL structures
*/
struct POSIX_ACE {
u16 tag;
u16 perms;
s32 id;
} __attribute__((__packed__));
struct POSIX_ACL {
u8 version;
u8 flags;
u16 filler;
struct POSIX_ACE ace[0];
} __attribute__((__packed__));
struct POSIX_SECURITY {
mode_t mode;
int acccnt;
int defcnt;
int firstdef;
u16 tagsset;
u16 filler;
struct POSIX_ACL acl;
} ;
/*
* Posix tags, cpu-endian 16 bits
*/
enum {
POSIX_ACL_USER_OBJ = 1,
POSIX_ACL_USER = 2,
POSIX_ACL_GROUP_OBJ = 4,
POSIX_ACL_GROUP = 8,
POSIX_ACL_MASK = 16,
POSIX_ACL_OTHER = 32,
POSIX_ACL_SPECIAL = 64 /* internal use only */
} ;
#define POSIX_ACL_EXTENSIONS (POSIX_ACL_USER | POSIX_ACL_GROUP | POSIX_ACL_MASK)
/*
* Posix permissions, cpu-endian 16 bits
*/
enum {
POSIX_PERM_X = 1,
POSIX_PERM_W = 2,
POSIX_PERM_R = 4,
POSIX_PERM_DENIAL = 64 /* internal use only */
} ;
#define POSIX_VERSION 2
#endif
extern const GUID *const zero_guid;
extern BOOL ntfs_guid_is_zero(const GUID *guid);
extern char *ntfs_guid_to_mbs(const GUID *guid, char *guid_str);
/**
* ntfs_sid_is_valid - determine if a SID is valid
* @sid: SID for which to determine if it is valid
*
* Determine if the SID pointed to by @sid is valid.
*
* Return TRUE if it is valid and FALSE otherwise.
*/
static __inline__ BOOL ntfs_sid_is_valid(const SID *sid)
{
if (!sid || sid->revision != SID_REVISION ||
sid->sub_authority_count > SID_MAX_SUB_AUTHORITIES)
return FALSE;
return TRUE;
}
extern int ntfs_sid_to_mbs_size(const SID *sid);
extern char *ntfs_sid_to_mbs(const SID *sid, char *sid_str,
size_t sid_str_size);
extern void ntfs_generate_guid(GUID *guid);
extern int ntfs_sd_add_everyone(ntfs_inode *ni);
extern le32 ntfs_security_hash(const SECURITY_DESCRIPTOR_RELATIVE *sd,
const u32 len);
int ntfs_build_mapping(struct SECURITY_CONTEXT *scx, const char *usermap_path,
BOOL allowdef);
int ntfs_get_owner_mode(struct SECURITY_CONTEXT *scx,
ntfs_inode *ni, struct stat*);
int ntfs_set_mode(struct SECURITY_CONTEXT *scx, ntfs_inode *ni, mode_t mode);
BOOL ntfs_allowed_as_owner(struct SECURITY_CONTEXT *scx, ntfs_inode *ni);
int ntfs_allowed_access(struct SECURITY_CONTEXT *scx,
ntfs_inode *ni, int accesstype);
int ntfs_allowed_create(struct SECURITY_CONTEXT *scx,
ntfs_inode *ni, gid_t *pgid, mode_t *pdsetgid);
BOOL old_ntfs_allowed_dir_access(struct SECURITY_CONTEXT *scx,
const char *path, int accesstype);
#if POSIXACLS
le32 ntfs_alloc_securid(struct SECURITY_CONTEXT *scx,
uid_t uid, gid_t gid, ntfs_inode *dir_ni,
mode_t mode, BOOL isdir);
#else
le32 ntfs_alloc_securid(struct SECURITY_CONTEXT *scx,
uid_t uid, gid_t gid, mode_t mode, BOOL isdir);
#endif
int ntfs_set_owner(struct SECURITY_CONTEXT *scx, ntfs_inode *ni,
uid_t uid, gid_t gid);
int ntfs_set_ownmod(struct SECURITY_CONTEXT *scx,
ntfs_inode *ni, uid_t uid, gid_t gid, mode_t mode);
#if POSIXACLS
int ntfs_set_owner_mode(struct SECURITY_CONTEXT *scx,
ntfs_inode *ni, uid_t uid, gid_t gid,
mode_t mode, struct POSIX_SECURITY *pxdesc);
#else
int ntfs_set_owner_mode(struct SECURITY_CONTEXT *scx,
ntfs_inode *ni, uid_t uid, gid_t gid, mode_t mode);
#endif
le32 ntfs_inherited_id(struct SECURITY_CONTEXT *scx,
ntfs_inode *dir_ni, BOOL fordir);
int ntfs_open_secure(ntfs_volume *vol);
int ntfs_close_secure(ntfs_volume *vol);
void ntfs_destroy_security_context(struct SECURITY_CONTEXT *scx);
#if POSIXACLS
int ntfs_set_inherited_posix(struct SECURITY_CONTEXT *scx,
ntfs_inode *ni, uid_t uid, gid_t gid,
ntfs_inode *dir_ni, mode_t mode);
int ntfs_get_posix_acl(struct SECURITY_CONTEXT *scx, ntfs_inode *ni,
const char *name, char *value, size_t size);
int ntfs_set_posix_acl(struct SECURITY_CONTEXT *scx, ntfs_inode *ni,
const char *name, const char *value, size_t size,
int flags);
int ntfs_remove_posix_acl(struct SECURITY_CONTEXT *scx, ntfs_inode *ni,
const char *name);
#endif
int ntfs_get_ntfs_acl(struct SECURITY_CONTEXT *scx, ntfs_inode *ni,
char *value, size_t size);
int ntfs_set_ntfs_acl(struct SECURITY_CONTEXT *scx, ntfs_inode *ni,
const char *value, size_t size, int flags);
int ntfs_get_ntfs_attrib(ntfs_inode *ni, char *value, size_t size);
int ntfs_set_ntfs_attrib(ntfs_inode *ni,
const char *value, size_t size, int flags);
/*
* Security API for direct access to security descriptors
* based on Win32 API
*/
#define MAGIC_API 0x09042009
struct SECURITY_API {
u32 magic;
struct SECURITY_CONTEXT security;
struct PERMISSIONS_CACHE *seccache;
} ;
/*
* The following constants are used in interfacing external programs.
* They are not to be stored on disk and must be defined in their
* native cpu representation.
* When disk representation (le) is needed, use SE_DACL_PRESENT, etc.
*/
enum { OWNER_SECURITY_INFORMATION = 1,
GROUP_SECURITY_INFORMATION = 2,
DACL_SECURITY_INFORMATION = 4,
SACL_SECURITY_INFORMATION = 8
} ;
int ntfs_get_file_security(struct SECURITY_API *scapi,
const char *path, u32 selection,
char *buf, u32 buflen, u32 *psize);
int ntfs_set_file_security(struct SECURITY_API *scapi,
const char *path, u32 selection, const char *attr);
int ntfs_get_file_attributes(struct SECURITY_API *scapi,
const char *path);
BOOL ntfs_set_file_attributes(struct SECURITY_API *scapi,
const char *path, s32 attrib);
BOOL ntfs_read_directory(struct SECURITY_API *scapi,
const char *path, ntfs_filldir_t callback, void *context);
int ntfs_read_sds(struct SECURITY_API *scapi,
char *buf, u32 size, u32 offset);
INDEX_ENTRY *ntfs_read_sii(struct SECURITY_API *scapi,
INDEX_ENTRY *entry);
INDEX_ENTRY *ntfs_read_sdh(struct SECURITY_API *scapi,
INDEX_ENTRY *entry);
struct SECURITY_API *ntfs_initialize_file_security(const char *device,
unsigned long flags);
BOOL ntfs_leave_file_security(struct SECURITY_API *scx);
int ntfs_get_usid(struct SECURITY_API *scapi, uid_t uid, char *buf);
int ntfs_get_gsid(struct SECURITY_API *scapi, gid_t gid, char *buf);
int ntfs_get_user(struct SECURITY_API *scapi, const SID *usid);
int ntfs_get_group(struct SECURITY_API *scapi, const SID *gsid);
#endif /* defined _NTFS_SECURITY_H */

View File

@ -48,23 +48,15 @@ typedef u16 le16;
typedef u32 le32;
typedef u64 le64;
typedef u16 be16;
typedef u32 be32;
typedef u64 be64;
/*
* Declare s{l,b}e{16,32,64} to be unsigned because we do not want sign
* extension on BE architectures.
* Declare sle{16,32,64} to be unsigned because we do not want sign extension
* on BE architectures.
*/
typedef u16 sle16;
typedef u32 sle32;
typedef u64 sle64;
typedef u16 sbe16;
typedef u32 sbe32;
typedef u64 sbe64;
typedef le16 ntfschar; /* 2-byte Unicode character type. */
typedef u16 ntfschar; /* 2-byte Unicode character type. */
#define UCHAR_T_SIZE_BITS 1
/*
@ -128,13 +120,5 @@ typedef enum {
#define STATUS_KEEP_SEARCHING (-3)
#define STATUS_NOT_FOUND (-4)
/*
* Force alignment in a struct if required by processor
*/
union ALIGNMENT {
u64 u64align;
void *ptralign;
} ;
#endif /* defined _NTFS_TYPES_H */

View File

@ -30,9 +30,9 @@ extern BOOL ntfs_names_are_equal(const ntfschar *s1, size_t s1_len,
const ntfschar *s2, size_t s2_len, const IGNORE_CASE_BOOL ic,
const ntfschar *upcase, const u32 upcase_size);
extern int ntfs_names_full_collate(const ntfschar *name1, const u32 name1_len,
extern int ntfs_names_collate(const ntfschar *name1, const u32 name1_len,
const ntfschar *name2, const u32 name2_len,
const IGNORE_CASE_BOOL ic,
const int err_val, const IGNORE_CASE_BOOL ic,
const ntfschar *upcase, const u32 upcase_len);
extern int ntfs_ucsncmp(const ntfschar *s1, const ntfschar *s2, size_t n);
@ -47,75 +47,23 @@ extern ntfschar *ntfs_ucsndup(const ntfschar *s, u32 maxlen);
extern void ntfs_name_upcase(ntfschar *name, u32 name_len,
const ntfschar *upcase, const u32 upcase_len);
extern void ntfs_name_locase(ntfschar *name, u32 name_len,
const ntfschar *locase, const u32 locase_len);
extern void ntfs_file_value_upcase(FILE_NAME_ATTR *file_name_attr,
const ntfschar *upcase, const u32 upcase_len);
extern int ntfs_file_values_compare(const FILE_NAME_ATTR *file_name_attr1,
const FILE_NAME_ATTR *file_name_attr2,
const int err_val, const IGNORE_CASE_BOOL ic,
const ntfschar *upcase, const u32 upcase_len);
extern int ntfs_ucstombs(const ntfschar *ins, const int ins_len, char **outs,
int outs_len);
extern int ntfs_mbstoucs(const char *ins, ntfschar **outs);
extern char *ntfs_uppercase_mbs(const char *low,
const ntfschar *upcase, u32 upcase_len);
extern int ntfs_mbstoucs(const char *ins, ntfschar **outs, int outs_len);
extern void ntfs_upcase_table_build(ntfschar *uc, u32 uc_len);
extern u32 ntfs_upcase_build_default(ntfschar **upcase);
extern ntfschar *ntfs_locase_table_build(const ntfschar *uc, u32 uc_cnt);
extern ntfschar *ntfs_str2ucs(const char *s, int *len);
extern void ntfs_ucsfree(ntfschar *ucs);
extern BOOL ntfs_forbidden_chars(const ntfschar *name, int len, BOOL strict);
extern BOOL ntfs_forbidden_names(ntfs_volume *vol,
const ntfschar *name, int len, BOOL strict);
extern BOOL ntfs_collapsible_chars(ntfs_volume *vol,
const ntfschar *shortname, int shortlen,
const ntfschar *longname, int longlen);
extern int ntfs_set_char_encoding(const char *locale);
#if defined(__APPLE__) || defined(__DARWIN__)
/**
* Mac OS X only.
*
* Sets file name Unicode normalization form conversion on or off.
* normalize=0 : Off
* normalize=1 : On
* If set to on, all filenames returned by ntfs-3g will be converted to the NFD
* normalization form, while all filenames recieved by ntfs-3g will be converted to the NFC
* normalization form. Since Windows and most other OS:es use the NFC form while Mac OS X
* mostly uses NFD, this conversion increases compatibility between Mac applications and
* NTFS-3G.
*
* @param normalize decides whether or not the string functions will do automatic filename
* normalization when converting to and from UTF-8. 0 means normalization is disabled,
* 1 means it is enabled.
* @return -1 if the argument was invalid or an error occurred, 0 if all went well.
*/
extern int ntfs_macosx_normalize_filenames(int normalize);
/**
* Mac OS X only.
*
* Normalizes the input string "utf8_string" to one of the normalization forms NFD or NFC.
* The parameter "composed" decides whether output should be in composed, NFC, form
* (composed == 1) or decomposed, NFD, form (composed == 0).
* Input is assumed to be properly UTF-8 encoded and null-terminated. Output will be a newly
* ntfs_calloc'ed string encoded in UTF-8. It is the callers responsibility to free(...) the
* allocated string when it's no longer needed.
*
* @param utf8_string the input string, which may be in any normalization form.
* @param target a pointer where the resulting string will be stored.
* @param composed decides which composition form to normalize the input string to. 0 means
* composed form (NFC), 1 means decomposed form (NFD).
* @return -1 if the normalization failed for some reason, otherwise the length of the
* normalized string stored in target.
*/
extern int ntfs_macosx_normalize_utf8(const char *utf8_string, char **target, int composed);
#endif /* defined(__APPLE__) || defined(__DARWIN__) */
#endif /* defined _NTFS_UNISTR_H */

View File

@ -1,6 +1,8 @@
/*
* version.h - Info about the NTFS library. Originated from the Linux-NTFS project.
*
* Copyright (c) 2009 Martin Bene
* Copyright (c) 2005 Anton Altaparmakov
* Copyright (c) 2005 Richard Russon
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
@ -18,13 +20,10 @@
* Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef EFS_H
#define EFS_H
#ifndef _NTFS_VERSION_H_
#define _NTFS_VERSION_H_
int ntfs_get_efs_info(ntfs_inode *ni, char *value, size_t size);
extern const char *ntfs_libntfs_version(void);
int ntfs_set_efs_info(ntfs_inode *ni,
const char *value, size_t size, int flags);
int ntfs_efs_fixup_attribute(ntfs_attr_search_ctx *ctx, ntfs_attr *na);
#endif /* _NTFS_VERSION_H_ */
#endif /* EFS_H */

View File

@ -4,8 +4,7 @@
* Copyright (c) 2000-2004 Anton Altaparmakov
* Copyright (c) 2004-2005 Richard Russon
* Copyright (c) 2005-2006 Yura Pakhuchiy
* Copyright (c) 2005-2009 Szabolcs Szakacsits
* Copyright (c) 2010 Jean-Pierre Andre
* Copyright (c) 2005-2006 Szabolcs Szakacsits
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
@ -36,73 +35,54 @@
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
/* Do not #include <sys/mount.h> here : conflicts with <linux/fs.h> */
#ifdef HAVE_SYS_MOUNT_H
#include <sys/mount.h>
#endif
#ifdef HAVE_MNTENT_H
#include <mntent.h>
#endif
/*
* Under Cygwin, DJGPP and FreeBSD we do not have MS_RDONLY and MS_NOATIME,
* so we define them ourselves.
*/
#ifndef MS_RDONLY
#define MS_RDONLY 1
#endif
/*
* Solaris defines MS_RDONLY but not MS_NOATIME thus we need to carefully
* define MS_NOATIME.
*/
#ifndef MS_NOATIME
#if (MS_RDONLY != 1)
# define MS_NOATIME 1
#else
# define MS_NOATIME 2
#endif
#endif
/* Forward declaration */
typedef struct _ntfs_volume ntfs_volume;
#include "param.h"
#include "types.h"
#include "support.h"
#include "device.h"
#include "inode.h"
#include "attrib.h"
#include "index.h"
/**
* enum ntfs_mount_flags -
*
* Flags for the ntfs_mount() function.
*/
enum {
NTFS_MNT_NONE = 0x00000000,
NTFS_MNT_RDONLY = 0x00000001,
NTFS_MNT_MAY_RDONLY = 0x02000000, /* Allow fallback to ro */
NTFS_MNT_FORENSIC = 0x04000000, /* No modification during
* mount. */
NTFS_MNT_EXCLUSIVE = 0x08000000,
NTFS_MNT_RECOVER = 0x10000000,
NTFS_MNT_IGNORE_HIBERFILE = 0x20000000,
};
typedef unsigned long ntfs_mount_flags;
/**
* enum ntfs_mounted_flags -
*
* Flags returned by the ntfs_check_if_mounted() function.
*/
typedef enum {
NTFS_MF_MOUNTED = 1, /* Device is mounted. */
NTFS_MF_ISROOT = 2, /* Device is mounted as system root. */
NTFS_MF_READONLY = 4, /* Device is mounted read-only. */
} ntfs_mounted_flags;
} ntfs_mount_flags;
extern int ntfs_check_if_mounted(const char *file, unsigned long *mnt_flags);
typedef enum {
NTFS_VOLUME_OK = 0,
NTFS_VOLUME_SYNTAX_ERROR = 11,
NTFS_VOLUME_NOT_NTFS = 12,
NTFS_VOLUME_CORRUPT = 13,
NTFS_VOLUME_HIBERNATED = 14,
NTFS_VOLUME_UNCLEAN_UNMOUNT = 15,
NTFS_VOLUME_LOCKED = 16,
NTFS_VOLUME_RAID = 17,
NTFS_VOLUME_UNKNOWN_REASON = 18,
NTFS_VOLUME_NO_PRIVILEGE = 19,
NTFS_VOLUME_OUT_OF_MEMORY = 20,
NTFS_VOLUME_FUSE_ERROR = 21,
NTFS_VOLUME_INSECURE = 22
} ntfs_volume_status;
typedef enum {
NTFS_FILES_INTERIX,
NTFS_FILES_WSL,
} ntfs_volume_special_files;
/**
* enum ntfs_volume_state_bits -
*
@ -112,12 +92,7 @@ typedef enum {
NV_ReadOnly, /* 1: Volume is read-only. */
NV_CaseSensitive, /* 1: Volume is mounted case-sensitive. */
NV_LogFileEmpty, /* 1: $logFile journal is empty. */
NV_ShowSysFiles, /* 1: Show NTFS metafiles. */
NV_ShowHidFiles, /* 1: Show files marked hidden. */
NV_HideDotFiles, /* 1: Set hidden flag on dot files */
NV_Compression, /* 1: allow compression */
NV_NoFixupWarn, /* 1: Do not log fixup errors */
NV_FreeSpaceKnown, /* 1: The free space is now known */
NV_NoATime, /* 1: Do not update access time. */
} ntfs_volume_state_bits;
#define test_nvol_flag(nv, flag) test_bit(NV_##flag, (nv)->state)
@ -136,29 +111,9 @@ typedef enum {
#define NVolSetLogFileEmpty(nv) set_nvol_flag(nv, LogFileEmpty)
#define NVolClearLogFileEmpty(nv) clear_nvol_flag(nv, LogFileEmpty)
#define NVolShowSysFiles(nv) test_nvol_flag(nv, ShowSysFiles)
#define NVolSetShowSysFiles(nv) set_nvol_flag(nv, ShowSysFiles)
#define NVolClearShowSysFiles(nv) clear_nvol_flag(nv, ShowSysFiles)
#define NVolShowHidFiles(nv) test_nvol_flag(nv, ShowHidFiles)
#define NVolSetShowHidFiles(nv) set_nvol_flag(nv, ShowHidFiles)
#define NVolClearShowHidFiles(nv) clear_nvol_flag(nv, ShowHidFiles)
#define NVolHideDotFiles(nv) test_nvol_flag(nv, HideDotFiles)
#define NVolSetHideDotFiles(nv) set_nvol_flag(nv, HideDotFiles)
#define NVolClearHideDotFiles(nv) clear_nvol_flag(nv, HideDotFiles)
#define NVolCompression(nv) test_nvol_flag(nv, Compression)
#define NVolSetCompression(nv) set_nvol_flag(nv, Compression)
#define NVolClearCompression(nv) clear_nvol_flag(nv, Compression)
#define NVolNoFixupWarn(nv) test_nvol_flag(nv, NoFixupWarn)
#define NVolSetNoFixupWarn(nv) set_nvol_flag(nv, NoFixupWarn)
#define NVolClearNoFixupWarn(nv) clear_nvol_flag(nv, NoFixupWarn)
#define NVolFreeSpaceKnown(nv) test_nvol_flag(nv, FreeSpaceKnown)
#define NVolSetFreeSpaceKnown(nv) set_nvol_flag(nv, FreeSpaceKnown)
#define NVolClearFreeSpaceKnown(nv) clear_nvol_flag(nv, FreeSpaceKnown)
#define NVolNoATime(nv) test_nvol_flag(nv, NoATime)
#define NVolSetNoATime(nv) set_nvol_flag(nv, NoATime)
#define NVolClearNoATime(nv) clear_nvol_flag(nv, NoATime)
/*
* NTFS version 1.1 and 1.2 are used by Windows NT4.
@ -191,7 +146,7 @@ struct _ntfs_volume {
ntfs_inode *vol_ni; /* ntfs_inode structure for FILE_Volume. */
u8 major_ver; /* Ntfs major version of volume. */
u8 minor_ver; /* Ntfs minor version of volume. */
le16 flags; /* Bit array of VOLUME_* flags. */
u16 flags; /* Bit array of VOLUME_* flags. */
u16 sector_size; /* Byte size of a sector. */
u8 sector_size_bits; /* Log(2) of the byte size of a sector. */
@ -204,7 +159,6 @@ struct _ntfs_volume {
/* Variables used by the cluster and mft allocators. */
u8 mft_zone_multiplier; /* Initial mft zone multiplier. */
u8 full_zones; /* cluster zones which are full */
s64 mft_data_pos; /* Mft record number at which to allocate the
next mft record. */
LCN mft_zone_start; /* First cluster of the mft zone. */
@ -234,12 +188,6 @@ struct _ntfs_volume {
bit means that the mft record is in use and
vice versa. */
ntfs_inode *secure_ni; /* ntfs_inode structure for FILE $Secure */
ntfs_index_context *secure_xsii; /* index for using $Secure:$SII */
ntfs_index_context *secure_xsdh; /* index for using $Secure:$SDH */
int secure_reentry; /* check for non-rentries */
unsigned int secure_flags; /* flags, see security.h for values */
int mftmirr_size; /* Size of the FILE_MFTMirr in mft records. */
LCN mftmirr_lcn; /* Logical cluster number of the data attribute
for FILE_MFTMirr. */
@ -252,72 +200,34 @@ struct _ntfs_volume {
FILE_UpCase. */
u32 upcase_len; /* Length in Unicode characters of the upcase
table. */
ntfschar *locase; /* Lower case equivalents of all 65536 2-byte
Unicode characters. Only if option
case_ignore is set. */
ATTR_DEF *attrdef; /* Attribute definitions. Obtained from
FILE_AttrDef. */
s32 attrdef_len; /* Size of the attribute definition table in
bytes. */
s64 free_clusters; /* Track the number of free clusters which
greatly improves statfs() performance */
s64 free_mft_records; /* Same for free mft records (see above) */
BOOL efs_raw; /* volume is mounted for raw access to
efs-encrypted files */
ntfs_volume_special_files special_files; /* Implementation of special files */
const char *abs_mnt_point; /* Mount point */
#ifdef XATTR_MAPPINGS
struct XATTRMAPPING *xattr_mapping;
#endif /* XATTR_MAPPINGS */
#if CACHE_INODE_SIZE
struct CACHE_HEADER *xinode_cache;
#endif
#if CACHE_NIDATA_SIZE
struct CACHE_HEADER *nidata_cache;
#endif
#if CACHE_LOOKUP_SIZE
struct CACHE_HEADER *lookup_cache;
#endif
#if CACHE_SECURID_SIZE
struct CACHE_HEADER *securid_cache;
#endif
#if CACHE_LEGACY_SIZE
struct CACHE_HEADER *legacy_cache;
#endif
/* Temp: for directory handling */
void *private_data; /* ntfs_dir for . */
void *private_bmp1; /* ntfs_bmp for $MFT/$BITMAP */
void *private_bmp2; /* ntfs_bmp for $Bitmap */
};
extern const char *ntfs_home;
extern ntfs_volume *ntfs_volume_alloc(void);
extern ntfs_volume *ntfs_volume_startup(struct ntfs_device *dev,
ntfs_mount_flags flags);
unsigned long flags);
extern ntfs_volume *ntfs_device_mount(struct ntfs_device *dev,
ntfs_mount_flags flags);
unsigned long flags);
extern int ntfs_device_umount(ntfs_volume *vol, const BOOL force);
extern ntfs_volume *ntfs_mount(const char *name, ntfs_mount_flags flags);
extern ntfs_volume *ntfs_mount(const char *name, unsigned long flags);
extern int ntfs_umount(ntfs_volume *vol, const BOOL force);
extern int ntfs_version_is_supported(ntfs_volume *vol);
extern int ntfs_volume_check_hiberfile(ntfs_volume *vol, int verbose);
extern int ntfs_logfile_reset(ntfs_volume *vol);
extern int ntfs_volume_write_flags(ntfs_volume *vol, const le16 flags);
extern int ntfs_volume_error(int err);
extern void ntfs_mount_error(const char *vol, const char *mntpoint, int err);
extern int ntfs_volume_get_free_space(ntfs_volume *vol);
extern int ntfs_volume_rename(ntfs_volume *vol, const ntfschar *label,
int label_len);
extern int ntfs_set_shown_files(ntfs_volume *vol,
BOOL show_sys_files, BOOL show_hid_files, BOOL hide_dot_files);
extern int ntfs_set_locale(void);
extern int ntfs_set_ignore_case(ntfs_volume *vol);
extern int ntfs_volume_write_flags(ntfs_volume *vol, const u16 flags);
#endif /* defined _NTFS_VOLUME_H */

View File

@ -1,97 +0,0 @@
/*
* xattrs.h : definitions related to system extended attributes
*
* Copyright (c) 2010 Jean-Pierre Andre
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program/include file 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 (in the main directory of the NTFS-3G
* distribution in the file COPYING); if not, write to the Free Software
* Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _NTFS_XATTRS_H_
#define _NTFS_XATTRS_H_
/*
* Flags that modify setxattr() semantics. These flags are also used by a
* number of libntfs-3g functions, such as ntfs_set_ntfs_acl(), which were
* originally tied to extended attributes support but now can be used by
* applications even if the platform does not support extended attributes.
*
* Careful: applications including this header should define HAVE_SETXATTR or
* HAVE_SYS_XATTR_H if the platform supports extended attributes. Otherwise the
* defined flags values may be incorrect (they will be correct for Linux but not
* necessarily for other platforms).
*/
#if defined(HAVE_SETXATTR) || defined(HAVE_SYS_XATTR_H)
#include <sys/xattr.h>
#else
#include "compat.h" /* may be needed for ENODATA definition */
#define XATTR_CREATE 1
#define XATTR_REPLACE 2
#endif
/*
* Identification of data mapped to the system name space
*/
enum SYSTEMXATTRS {
XATTR_UNMAPPED,
XATTR_NTFS_ACL,
XATTR_NTFS_ATTRIB,
XATTR_NTFS_ATTRIB_BE,
XATTR_NTFS_EFSINFO,
XATTR_NTFS_REPARSE_DATA,
XATTR_NTFS_OBJECT_ID,
XATTR_NTFS_DOS_NAME,
XATTR_NTFS_TIMES,
XATTR_NTFS_TIMES_BE,
XATTR_NTFS_CRTIME,
XATTR_NTFS_CRTIME_BE,
XATTR_NTFS_EA,
XATTR_POSIX_ACC,
XATTR_POSIX_DEF
} ;
struct XATTRMAPPING {
struct XATTRMAPPING *next;
enum SYSTEMXATTRS xattr;
char name[1]; /* variable length */
} ;
#ifdef XATTR_MAPPINGS
struct XATTRMAPPING *ntfs_xattr_build_mapping(ntfs_volume *vol,
const char *path);
void ntfs_xattr_free_mapping(struct XATTRMAPPING*);
#endif /* XATTR_MAPPINGS */
enum SYSTEMXATTRS ntfs_xattr_system_type(const char *name,
ntfs_volume *vol);
struct SECURITY_CONTEXT;
int ntfs_xattr_system_getxattr(struct SECURITY_CONTEXT *scx,
enum SYSTEMXATTRS attr,
ntfs_inode *ni, ntfs_inode *dir_ni,
char *value, size_t size);
int ntfs_xattr_system_setxattr(struct SECURITY_CONTEXT *scx,
enum SYSTEMXATTRS attr,
ntfs_inode *ni, ntfs_inode *dir_ni,
const char *value, size_t size, int flags);
int ntfs_xattr_system_removexattr(struct SECURITY_CONTEXT *scx,
enum SYSTEMXATTRS attr,
ntfs_inode *ni, ntfs_inode *dir_ni);
#endif /* _NTFS_XATTRS_H_ */

View File

@ -1,34 +0,0 @@
MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
if FUSE_INTERNAL
noinst_LTLIBRARIES = libfuse-lite.la
endif
libfuse_lite_la_CFLAGS= \
$(AM_CFLAGS) \
$(LIBFUSE_LITE_CFLAGS)
libfuse_lite_la_CPPFLAGS= \
$(AM_CPPFLAGS) \
-I$(top_srcdir)/include/fuse-lite
libfuse_lite_la_LIBADD = $(LIBFUSE_LITE_LIBS)
libfuse_lite_la_SOURCES = \
fuse.c \
fuse_i.h \
fuse_kern_chan.c \
fuse_loop.c \
fuse_lowlevel.c \
fuse_misc.h \
fuse_opt.c \
fuse_session.c \
fuse_signals.c \
fusermount.c \
helper.c \
mount.c \
mount_util.c \
mount_util.h
libs: libfuse-lite.la

File diff suppressed because it is too large Load Diff

View File

@ -1,25 +0,0 @@
/*
FUSE: Filesystem in Userspace
Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
This program can be distributed under the terms of the GNU LGPLv2.
See the file COPYING.LIB
*/
#include "fuse.h"
struct fuse_session;
struct fuse_chan;
struct fuse_lowlevel_ops;
struct fuse_req;
struct fuse_cmd {
char *buf;
size_t buflen;
struct fuse_chan *ch;
};
struct fuse_chan *fuse_kern_chan_new(int fd);
void fuse_kern_unmount(const char *mountpoint, int fd);
int fuse_kern_mount(const char *mountpoint, struct fuse_args *args);

View File

@ -1,96 +0,0 @@
/*
FUSE: Filesystem in Userspace
Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
This program can be distributed under the terms of the GNU LGPLv2.
See the file COPYING.LIB
*/
#include "config.h"
#include "fuse_lowlevel.h"
#include "fuse_kernel.h"
#include "fuse_i.h"
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <assert.h>
static int fuse_kern_chan_receive(struct fuse_chan **chp, char *buf,
size_t size)
{
struct fuse_chan *ch = *chp;
int err;
ssize_t res;
struct fuse_session *se = fuse_chan_session(ch);
assert(se != NULL);
restart:
res = read(fuse_chan_fd(ch), buf, size);
err = errno;
if (fuse_session_exited(se))
return 0;
if (res == -1) {
/* ENOENT means the operation was interrupted, it's safe
to restart */
if (err == ENOENT)
goto restart;
if (err == ENODEV) {
fuse_session_exit(se);
return 0;
}
/* Errors occuring during normal operation: EINTR (read
interrupted), EAGAIN (nonblocking I/O), ENODEV (filesystem
umounted) */
if (err != EINTR && err != EAGAIN)
perror("fuse: reading device");
return -err;
}
if ((size_t) res < sizeof(struct fuse_in_header)) {
fprintf(stderr, "short read on fuse device\n");
return -EIO;
}
return res;
}
static int fuse_kern_chan_send(struct fuse_chan *ch, const struct iovec iov[],
size_t count)
{
if (iov) {
ssize_t res = writev(fuse_chan_fd(ch), iov, count);
int err = errno;
if (res == -1) {
struct fuse_session *se = fuse_chan_session(ch);
assert(se != NULL);
/* ENOENT means the operation was interrupted */
if (!fuse_session_exited(se) && err != ENOENT)
perror("fuse: writing device");
return -err;
}
}
return 0;
}
static void fuse_kern_chan_destroy(struct fuse_chan *ch)
{
close(fuse_chan_fd(ch));
}
#define MIN_BUFSIZE 0x21000
struct fuse_chan *fuse_kern_chan_new(int fd)
{
struct fuse_chan_ops op = {
.receive = fuse_kern_chan_receive,
.send = fuse_kern_chan_send,
.destroy = fuse_kern_chan_destroy,
};
size_t bufsize = getpagesize() + 0x1000;
bufsize = bufsize < MIN_BUFSIZE ? MIN_BUFSIZE : bufsize;
return fuse_chan_new(&op, fd, bufsize, NULL);
}

View File

@ -1,40 +0,0 @@
/*
FUSE: Filesystem in Userspace
Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
This program can be distributed under the terms of the GNU LGPLv2.
See the file COPYING.LIB
*/
#include "config.h"
#include "fuse_lowlevel.h"
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
int fuse_session_loop(struct fuse_session *se)
{
int res = 0;
struct fuse_chan *ch = fuse_session_next_chan(se, NULL);
size_t bufsize = fuse_chan_bufsize(ch);
char *buf = (char *) malloc(bufsize);
if (!buf) {
fprintf(stderr, "fuse: failed to allocate read buffer\n");
return -1;
}
while (!fuse_session_exited(se)) {
struct fuse_chan *tmpch = ch;
res = fuse_chan_recv(&tmpch, buf, bufsize);
if (res == -EINTR)
continue;
if (res <= 0)
break;
fuse_session_process(se, buf, res, tmpch);
}
free(buf);
fuse_session_reset(se);
return res < 0 ? -1 : 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,51 +0,0 @@
/*
FUSE: Filesystem in Userspace
Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
This program can be distributed under the terms of the GNU LGPLv2.
See the file COPYING.LIB
*/
#include "config.h"
#include <pthread.h>
#ifndef USE_UCLIBC
#define fuse_mutex_init(mut) pthread_mutex_init(mut, NULL)
#else
static inline void fuse_mutex_init(pthread_mutex_t *mut)
{
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ADAPTIVE_NP);
pthread_mutex_init(mut, &attr);
pthread_mutexattr_destroy(&attr);
}
#endif
#ifdef HAVE_STRUCT_STAT_ST_ATIM
/* Linux */
#define ST_ATIM_NSEC(stbuf) ((stbuf)->st_atim.tv_nsec)
#define ST_CTIM_NSEC(stbuf) ((stbuf)->st_ctim.tv_nsec)
#define ST_MTIM_NSEC(stbuf) ((stbuf)->st_mtim.tv_nsec)
#define ST_ATIM_NSEC_SET(stbuf, val) (stbuf)->st_atim.tv_nsec = (val)
#define ST_MTIM_NSEC_SET(stbuf, val) (stbuf)->st_mtim.tv_nsec = (val)
#elif defined(HAVE_STRUCT_STAT_ST_ATIMESPEC)
/* FreeBSD */
#define ST_ATIM_NSEC(stbuf) ((stbuf)->st_atimespec.tv_nsec)
#define ST_CTIM_NSEC(stbuf) ((stbuf)->st_ctimespec.tv_nsec)
#define ST_MTIM_NSEC(stbuf) ((stbuf)->st_mtimespec.tv_nsec)
#define ST_ATIM_NSEC_SET(stbuf, val) (stbuf)->st_atimespec.tv_nsec = (val)
#define ST_MTIM_NSEC_SET(stbuf, val) (stbuf)->st_mtimespec.tv_nsec = (val)
#elif defined(HAVE_STRUCT_STAT_ST_ATIMENSEC)
#define ST_ATIM_NSEC(stbuf) ((stbuf)->st_atimensec)
#define ST_CTIM_NSEC(stbuf) ((stbuf)->st_ctimensec)
#define ST_MTIM_NSEC(stbuf) ((stbuf)->st_mtimensec)
#define ST_ATIM_NSEC_SET(stbuf, val) (stbuf)->st_atimensec = (val)
#define ST_MTIM_NSEC_SET(stbuf, val) (stbuf)->st_mtimensec = (val)
#else
#define ST_ATIM_NSEC(stbuf) 0
#define ST_CTIM_NSEC(stbuf) 0
#define ST_MTIM_NSEC(stbuf) 0
#define ST_ATIM_NSEC_SET(stbuf, val) do { } while (0)
#define ST_MTIM_NSEC_SET(stbuf, val) do { } while (0)
#endif

View File

@ -1,382 +0,0 @@
/*
FUSE: Filesystem in Userspace
Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
This program can be distributed under the terms of the GNU LGPLv2.
See the file COPYING.LIB
*/
#include "config.h"
#include "fuse_opt.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
struct fuse_opt_context {
void *data;
const struct fuse_opt *opt;
fuse_opt_proc_t proc;
int argctr;
int argc;
char **argv;
struct fuse_args outargs;
char *opts;
int nonopt;
};
void fuse_opt_free_args(struct fuse_args *args)
{
if (args) {
if (args->argv && args->allocated) {
int i;
for (i = 0; i < args->argc; i++)
free(args->argv[i]);
free(args->argv);
}
args->argc = 0;
args->argv = NULL;
args->allocated = 0;
}
}
static int alloc_failed(void)
{
fprintf(stderr, "fuse: memory allocation failed\n");
return -1;
}
int fuse_opt_add_arg(struct fuse_args *args, const char *arg)
{
char **newargv;
char *newarg;
assert(!args->argv || args->allocated);
newargv = realloc(args->argv, (args->argc + 2) * sizeof(char *));
newarg = newargv ? strdup(arg) : NULL;
if (!newargv || !newarg)
return alloc_failed();
args->argv = newargv;
args->allocated = 1;
args->argv[args->argc++] = newarg;
args->argv[args->argc] = NULL;
return 0;
}
int fuse_opt_insert_arg(struct fuse_args *args, int pos, const char *arg)
{
assert(pos <= args->argc);
if (fuse_opt_add_arg(args, arg) == -1)
return -1;
if (pos != args->argc - 1) {
char *newarg = args->argv[args->argc - 1];
memmove(&args->argv[pos + 1], &args->argv[pos],
sizeof(char *) * (args->argc - pos - 1));
args->argv[pos] = newarg;
}
return 0;
}
static int next_arg(struct fuse_opt_context *ctx, const char *opt)
{
if (ctx->argctr + 1 >= ctx->argc) {
fprintf(stderr, "fuse: missing argument after `%s'\n", opt);
return -1;
}
ctx->argctr++;
return 0;
}
static int add_arg(struct fuse_opt_context *ctx, const char *arg)
{
return fuse_opt_add_arg(&ctx->outargs, arg);
}
int fuse_opt_add_opt(char **opts, const char *opt)
{
char *newopts;
if (!*opts)
newopts = strdup(opt);
else {
unsigned oldlen = strlen(*opts);
newopts = realloc(*opts, oldlen + 1 + strlen(opt) + 1);
if (newopts) {
newopts[oldlen] = ',';
strcpy(newopts + oldlen + 1, opt);
}
}
if (!newopts)
return alloc_failed();
*opts = newopts;
return 0;
}
static int add_opt(struct fuse_opt_context *ctx, const char *opt)
{
return fuse_opt_add_opt(&ctx->opts, opt);
}
static int call_proc(struct fuse_opt_context *ctx, const char *arg, int key,
int iso)
{
if (key == FUSE_OPT_KEY_DISCARD)
return 0;
if (key != FUSE_OPT_KEY_KEEP && ctx->proc) {
int res = ctx->proc(ctx->data, arg, key, &ctx->outargs);
if (res == -1 || !res)
return res;
}
if (iso)
return add_opt(ctx, arg);
else
return add_arg(ctx, arg);
}
static int match_template(const char *t, const char *arg, unsigned *sepp)
{
int arglen = strlen(arg);
const char *sep = strchr(t, '=');
sep = sep ? sep : strchr(t, ' ');
if (sep && (!sep[1] || sep[1] == '%')) {
int tlen = sep - t;
if (sep[0] == '=')
tlen ++;
if (arglen >= tlen && strncmp(arg, t, tlen) == 0) {
*sepp = sep - t;
return 1;
}
}
if (strcmp(t, arg) == 0) {
*sepp = 0;
return 1;
}
return 0;
}
static const struct fuse_opt *find_opt(const struct fuse_opt *opt,
const char *arg, unsigned *sepp)
{
for (; opt && opt->templ; opt++)
if (match_template(opt->templ, arg, sepp))
return opt;
return NULL;
}
int fuse_opt_match(const struct fuse_opt *opts, const char *opt)
{
unsigned dummy;
return find_opt(opts, opt, &dummy) ? 1 : 0;
}
static int process_opt_param(void *var, const char *format, const char *param,
const char *arg)
{
assert(format[0] == '%');
if (format[1] == 's') {
char *copy = strdup(param);
if (!copy)
return alloc_failed();
*(char **) var = copy;
} else {
if (sscanf(param, format, var) != 1) {
fprintf(stderr, "fuse: invalid parameter in option `%s'\n", arg);
return -1;
}
}
return 0;
}
static int process_opt(struct fuse_opt_context *ctx,
const struct fuse_opt *opt, unsigned sep,
const char *arg, int iso)
{
if (opt->offset == -1U) {
if (call_proc(ctx, arg, opt->value, iso) == -1)
return -1;
} else {
void *var = (char *)ctx->data + opt->offset;
if (sep && opt->templ[sep + 1]) {
const char *param = arg + sep;
if (opt->templ[sep] == '=')
param ++;
if (process_opt_param(var, opt->templ + sep + 1,
param, arg) == -1)
return -1;
} else
*(int *)var = opt->value;
}
return 0;
}
static int process_opt_sep_arg(struct fuse_opt_context *ctx,
const struct fuse_opt *opt, unsigned sep,
const char *arg, int iso)
{
int res;
char *newarg;
char *param;
if (next_arg(ctx, arg) == -1)
return -1;
param = ctx->argv[ctx->argctr];
newarg = malloc(sep + strlen(param) + 1);
if (!newarg)
return alloc_failed();
memcpy(newarg, arg, sep);
strcpy(newarg + sep, param);
res = process_opt(ctx, opt, sep, newarg, iso);
free(newarg);
return res;
}
static int process_gopt(struct fuse_opt_context *ctx, const char *arg, int iso)
{
unsigned sep;
const struct fuse_opt *opt = find_opt(ctx->opt, arg, &sep);
if (opt) {
for (; opt; opt = find_opt(opt + 1, arg, &sep)) {
int res;
if (sep && opt->templ[sep] == ' ' && !arg[sep])
res = process_opt_sep_arg(ctx, opt, sep, arg, iso);
else
res = process_opt(ctx, opt, sep, arg, iso);
if (res == -1)
return -1;
}
return 0;
} else
return call_proc(ctx, arg, FUSE_OPT_KEY_OPT, iso);
}
static int process_real_option_group(struct fuse_opt_context *ctx, char *opts)
{
char *sep;
do {
int res;
#ifdef __SOLARIS__
/*
* On Solaris, the device name contains commas, so the
* option "fsname" has to be the last one and its commas
* should not be interpreted as option separators.
* This had to be hardcoded because the option "fsname"
* may be found though not present in option list.
*/
if (!strncmp(opts,"fsname=",7))
sep = (char*)NULL;
else
#endif /* __SOLARIS__ */
{
sep = strchr(opts, ',');
if (sep)
*sep = '\0';
}
res = process_gopt(ctx, opts, 1);
if (res == -1)
return -1;
opts = sep + 1;
} while (sep);
return 0;
}
static int process_option_group(struct fuse_opt_context *ctx, const char *opts)
{
int res;
char *copy;
const char *sep = strchr(opts, ',');
if (!sep)
return process_gopt(ctx, opts, 1);
copy = strdup(opts);
if (!copy) {
fprintf(stderr, "fuse: memory allocation failed\n");
return -1;
}
res = process_real_option_group(ctx, copy);
free(copy);
return res;
}
static int process_one(struct fuse_opt_context *ctx, const char *arg)
{
if (ctx->nonopt || arg[0] != '-')
return call_proc(ctx, arg, FUSE_OPT_KEY_NONOPT, 0);
else if (arg[1] == 'o') {
if (arg[2])
return process_option_group(ctx, arg + 2);
else {
if (next_arg(ctx, arg) == -1)
return -1;
return process_option_group(ctx, ctx->argv[ctx->argctr]);
}
} else if (arg[1] == '-' && !arg[2]) {
if (add_arg(ctx, arg) == -1)
return -1;
ctx->nonopt = ctx->outargs.argc;
return 0;
} else
return process_gopt(ctx, arg, 0);
}
static int opt_parse(struct fuse_opt_context *ctx)
{
if (ctx->argc) {
if (add_arg(ctx, ctx->argv[0]) == -1)
return -1;
}
for (ctx->argctr = 1; ctx->argctr < ctx->argc; ctx->argctr++)
if (process_one(ctx, ctx->argv[ctx->argctr]) == -1)
return -1;
if (ctx->opts) {
if (fuse_opt_insert_arg(&ctx->outargs, 1, "-o") == -1 ||
fuse_opt_insert_arg(&ctx->outargs, 2, ctx->opts) == -1)
return -1;
}
if (ctx->nonopt && ctx->nonopt == ctx->outargs.argc) {
free(ctx->outargs.argv[ctx->outargs.argc - 1]);
ctx->outargs.argv[--ctx->outargs.argc] = NULL;
}
return 0;
}
int fuse_opt_parse(struct fuse_args *args, void *data,
const struct fuse_opt opts[], fuse_opt_proc_t proc)
{
int res;
struct fuse_opt_context ctx = {
.data = data,
.opt = opts,
.proc = proc,
};
if (!args || !args->argv || !args->argc)
return 0;
ctx.argc = args->argc;
ctx.argv = args->argv;
res = opt_parse(&ctx);
if (res != -1) {
struct fuse_args tmp = *args;
*args = ctx.outargs;
ctx.outargs = tmp;
}
free(ctx.opts);
fuse_opt_free_args(&ctx.outargs);
return res;
}

View File

@ -1,193 +0,0 @@
/*
FUSE: Filesystem in Userspace
Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
This program can be distributed under the terms of the GNU LGPLv2.
See the file COPYING.LIB
*/
#include "config.h"
#include "fuse_lowlevel.h"
#include "fuse_lowlevel_compat.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
struct fuse_session {
struct fuse_session_ops op;
void *data;
volatile int exited;
struct fuse_chan *ch;
};
struct fuse_chan {
struct fuse_chan_ops op;
struct fuse_session *se;
int fd;
size_t bufsize;
void *data;
};
struct fuse_session *fuse_session_new(struct fuse_session_ops *op, void *data)
{
struct fuse_session *se = (struct fuse_session *) malloc(sizeof(*se));
if (se == NULL) {
fprintf(stderr, "fuse: failed to allocate session\n");
return NULL;
}
memset(se, 0, sizeof(*se));
se->op = *op;
se->data = data;
return se;
}
void fuse_session_add_chan(struct fuse_session *se, struct fuse_chan *ch)
{
assert(se->ch == NULL);
assert(ch->se == NULL);
se->ch = ch;
ch->se = se;
}
void fuse_session_remove_chan(struct fuse_chan *ch)
{
struct fuse_session *se = ch->se;
if (se) {
assert(se->ch == ch);
se->ch = NULL;
ch->se = NULL;
}
}
struct fuse_chan *fuse_session_next_chan(struct fuse_session *se,
struct fuse_chan *ch)
{
assert(ch == NULL || ch == se->ch);
if (ch == NULL)
return se->ch;
else
return NULL;
}
void fuse_session_process(struct fuse_session *se, const char *buf, size_t len,
struct fuse_chan *ch)
{
se->op.process(se->data, buf, len, ch);
}
void fuse_session_destroy(struct fuse_session *se)
{
if (se->op.destroy)
se->op.destroy(se->data);
if (se->ch != NULL)
fuse_chan_destroy(se->ch);
free(se);
}
void fuse_session_exit(struct fuse_session *se)
{
if (se->op.exit)
se->op.exit(se->data, 1);
se->exited = 1;
}
void fuse_session_reset(struct fuse_session *se)
{
if (se->op.exit)
se->op.exit(se->data, 0);
se->exited = 0;
}
int fuse_session_exited(struct fuse_session *se)
{
if (se->op.exited)
return se->op.exited(se->data);
else
return se->exited;
}
static struct fuse_chan *fuse_chan_new_common(struct fuse_chan_ops *op, int fd,
size_t bufsize, void *data)
{
struct fuse_chan *ch = (struct fuse_chan *) malloc(sizeof(*ch));
if (ch == NULL) {
fprintf(stderr, "fuse: failed to allocate channel\n");
return NULL;
}
memset(ch, 0, sizeof(*ch));
ch->op = *op;
ch->fd = fd;
ch->bufsize = bufsize;
ch->data = data;
return ch;
}
struct fuse_chan *fuse_chan_new(struct fuse_chan_ops *op, int fd,
size_t bufsize, void *data)
{
return fuse_chan_new_common(op, fd, bufsize, data);
}
int fuse_chan_fd(struct fuse_chan *ch)
{
return ch->fd;
}
size_t fuse_chan_bufsize(struct fuse_chan *ch)
{
return ch->bufsize;
}
void *fuse_chan_data(struct fuse_chan *ch)
{
return ch->data;
}
struct fuse_session *fuse_chan_session(struct fuse_chan *ch)
{
return ch->se;
}
int fuse_chan_recv(struct fuse_chan **chp, char *buf, size_t size)
{
struct fuse_chan *ch = *chp;
return ch->op.receive(chp, buf, size);
}
#ifdef __SOLARIS__
int fuse_chan_receive(struct fuse_chan *ch, char *buf, size_t size)
{
int res;
res = fuse_chan_recv(&ch, buf, size);
return res >= 0 ? res : (res != -EINTR && res != -EAGAIN) ? -1 : 0;
}
#endif /* __SOLARIS__ */
int fuse_chan_send(struct fuse_chan *ch, const struct iovec iov[], size_t count)
{
return ch->op.send(ch, iov, count);
}
void fuse_chan_destroy(struct fuse_chan *ch)
{
fuse_session_remove_chan(ch);
if (ch->op.destroy)
ch->op.destroy(ch);
free(ch);
}

View File

@ -1,73 +0,0 @@
/*
FUSE: Filesystem in Userspace
Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
This program can be distributed under the terms of the GNU LGPLv2.
See the file COPYING.LIB
*/
#include "config.h"
#include "fuse_lowlevel.h"
#include <stdio.h>
#include <string.h>
#include <signal.h>
static struct fuse_session *fuse_instance;
static void exit_handler(int sig)
{
(void) sig;
if (fuse_instance)
fuse_session_exit(fuse_instance);
}
static int set_one_signal_handler(int sig, void (*handler)(int), int remove)
{
struct sigaction sa;
struct sigaction old_sa;
memset(&sa, 0, sizeof(struct sigaction));
sa.sa_handler = remove ? SIG_DFL : handler;
sigemptyset(&(sa.sa_mask));
sa.sa_flags = 0;
if (sigaction(sig, NULL, &old_sa) == -1) {
perror("fuse: cannot get old signal handler");
return -1;
}
if (old_sa.sa_handler == (remove ? handler : SIG_DFL) &&
sigaction(sig, &sa, NULL) == -1) {
perror("fuse: cannot set signal handler");
return -1;
}
return 0;
}
int fuse_set_signal_handlers(struct fuse_session *se)
{
if (set_one_signal_handler(SIGHUP, exit_handler, 0) == -1 ||
set_one_signal_handler(SIGINT, exit_handler, 0) == -1 ||
set_one_signal_handler(SIGTERM, exit_handler, 0) == -1 ||
set_one_signal_handler(SIGPIPE, SIG_IGN, 0) == -1)
return -1;
fuse_instance = se;
return 0;
}
void fuse_remove_signal_handlers(struct fuse_session *se)
{
if (fuse_instance != se)
fprintf(stderr,
"fuse: fuse_remove_signal_handlers: unknown session\n");
else
fuse_instance = NULL;
set_one_signal_handler(SIGHUP, exit_handler, 1);
set_one_signal_handler(SIGINT, exit_handler, 1);
set_one_signal_handler(SIGTERM, exit_handler, 1);
set_one_signal_handler(SIGPIPE, SIG_IGN, 1);
}

View File

@ -1,705 +0,0 @@
/*
FUSE: Filesystem in Userspace
Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
This program can be distributed under the terms of the GNU GPL.
See the file COPYING.
*/
/* This program does the mounting and unmounting of FUSE filesystems */
#include <config.h>
#include "mount_util.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <getopt.h>
#include <errno.h>
#include <fcntl.h>
#include <pwd.h>
#include <paths.h>
#ifdef __SOLARIS__
#include <sys/mnttab.h>
#else /* __SOLARIS__ */
#include <grp.h>
#include <mntent.h>
#include <sys/fsuid.h>
#endif /* __SOLARIS__ */
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/mount.h>
#include <sys/socket.h>
#include <sys/utsname.h>
#define FUSE_DEV_NEW "/dev/fuse"
#ifndef MS_DIRSYNC
#define MS_DIRSYNC 128
#endif
static const char *progname = "ntfs-3g-mount";
static int mount_max = 1000;
int drop_privs(void);
int restore_privs(void);
#ifdef __SOLARIS__
/*
* fusermount is not implemented in fuse-lite for Solaris,
* only the minimal functions are provided.
*/
/*
* Solaris doesn't have setfsuid/setfsgid.
* This doesn't really matter anyway as this program shouldn't be made
* suid on Solaris. It should instead be used via a profile with the
* sys_mount privilege.
*/
int drop_privs(void)
{
return (0);
}
int restore_privs(void)
{
return (0);
}
#else /* __SOLARIS__ */
static const char *get_user_name(void)
{
struct passwd *pw = getpwuid(getuid());
if (pw != NULL && pw->pw_name != NULL)
return pw->pw_name;
else {
fprintf(stderr, "%s: could not determine username\n", progname);
return NULL;
}
}
int drop_privs(void)
{
if (!getegid()) {
gid_t new_gid = getgid();
if (setresgid(-1, new_gid, getegid()) < 0) {
perror("priv drop: setresgid failed");
return -1;
}
if (getegid() != new_gid){
perror("dropping group privilege failed");
return -1;
}
}
if (!geteuid()) {
uid_t new_uid = getuid();
if (setresuid(-1, new_uid, geteuid()) < 0) {
perror("priv drop: setresuid failed");
return -1;
}
if (geteuid() != new_uid){
perror("dropping user privilege failed");
return -1;
}
}
return 0;
}
int restore_privs(void)
{
if (geteuid()) {
uid_t ruid, euid, suid;
if (getresuid(&ruid, &euid, &suid) < 0) {
perror("priv restore: getresuid failed");
return -1;
}
if (setresuid(-1, suid, -1) < 0) {
perror("priv restore: setresuid failed");
return -1;
}
if (geteuid() != suid) {
perror("restoring privilege failed");
return -1;
}
}
if (getegid()) {
gid_t rgid, egid, sgid;
if (getresgid(&rgid, &egid, &sgid) < 0) {
perror("priv restore: getresgid failed");
return -1;
}
if (setresgid(-1, sgid, -1) < 0) {
perror("priv restore: setresgid failed");
return -1;
}
if (getegid() != sgid){
perror("restoring group privilege failed");
return -1;
}
}
return 0;
}
#ifndef IGNORE_MTAB
static int add_mount(const char *source, const char *mnt, const char *type,
const char *opts)
{
return fuse_mnt_add_mount(progname, source, mnt, type, opts);
}
static int count_fuse_fs(void)
{
struct mntent *entp;
int count = 0;
const char *mtab = _PATH_MOUNTED;
FILE *fp = setmntent(mtab, "r");
if (fp == NULL) {
fprintf(stderr, "%s: failed to open %s: %s\n", progname, mtab,
strerror(errno));
return -1;
}
while ((entp = getmntent(fp)) != NULL) {
if (strcmp(entp->mnt_type, "fuse") == 0 ||
strncmp(entp->mnt_type, "fuse.", 5) == 0)
count ++;
}
endmntent(fp);
return count;
}
#else /* IGNORE_MTAB */
static int count_fuse_fs()
{
return 0;
}
static int add_mount(const char *source, const char *mnt, const char *type,
const char *opts)
{
(void) source;
(void) mnt;
(void) type;
(void) opts;
return 0;
}
#endif /* IGNORE_MTAB */
static int begins_with(const char *s, const char *beg)
{
if (strncmp(s, beg, strlen(beg)) == 0)
return 1;
else
return 0;
}
struct mount_flags {
const char *opt;
unsigned long flag;
int on;
int safe;
};
static struct mount_flags mount_flags[] = {
{"rw", MS_RDONLY, 0, 1},
{"ro", MS_RDONLY, 1, 1},
{"suid", MS_NOSUID, 0, 0},
{"nosuid", MS_NOSUID, 1, 1},
{"dev", MS_NODEV, 0, 0},
{"nodev", MS_NODEV, 1, 1},
{"exec", MS_NOEXEC, 0, 1},
{"noexec", MS_NOEXEC, 1, 1},
{"async", MS_SYNCHRONOUS, 0, 1},
{"sync", MS_SYNCHRONOUS, 1, 1},
{"atime", MS_NOATIME, 0, 1},
{"noatime", MS_NOATIME, 1, 1},
{"dirsync", MS_DIRSYNC, 1, 1},
{NULL, 0, 0, 0}
};
static int find_mount_flag(const char *s, unsigned len, int *on, int *flag)
{
int i;
for (i = 0; mount_flags[i].opt != NULL; i++) {
const char *opt = mount_flags[i].opt;
if (strlen(opt) == len && strncmp(opt, s, len) == 0) {
*on = mount_flags[i].on;
*flag = mount_flags[i].flag;
if (!mount_flags[i].safe && getuid() != 0) {
*flag = 0;
fprintf(stderr, "%s: unsafe option '%s' ignored\n",
progname, opt);
}
return 1;
}
}
return 0;
}
static int add_option(char **optsp, const char *opt, unsigned expand)
{
char *newopts;
if (*optsp == NULL)
newopts = strdup(opt);
else {
unsigned oldsize = strlen(*optsp);
unsigned newsize = oldsize + 1 + strlen(opt) + expand + 1;
newopts = (char *) realloc(*optsp, newsize);
if (newopts)
sprintf(newopts + oldsize, ",%s", opt);
}
if (newopts == NULL) {
fprintf(stderr, "%s: failed to allocate memory\n", progname);
return -1;
}
*optsp = newopts;
return 0;
}
static int get_mnt_opts(int flags, char *opts, char **mnt_optsp)
{
int i;
int l;
if (!(flags & MS_RDONLY) && add_option(mnt_optsp, "rw", 0) == -1)
return -1;
for (i = 0; mount_flags[i].opt != NULL; i++) {
if (mount_flags[i].on && (flags & mount_flags[i].flag) &&
add_option(mnt_optsp, mount_flags[i].opt, 0) == -1)
return -1;
}
if (add_option(mnt_optsp, opts, 0) == -1)
return -1;
/* remove comma from end of opts*/
l = strlen(*mnt_optsp);
if ((*mnt_optsp)[l-1] == ',')
(*mnt_optsp)[l-1] = '\0';
if (getuid() != 0) {
const char *user = get_user_name();
if (user == NULL)
return -1;
if (add_option(mnt_optsp, "user=", strlen(user)) == -1)
return -1;
strcat(*mnt_optsp, user);
}
return 0;
}
static int opt_eq(const char *s, unsigned len, const char *opt)
{
if(strlen(opt) == len && strncmp(s, opt, len) == 0)
return 1;
else
return 0;
}
static int get_string_opt(const char *s, unsigned len, const char *opt,
char **val)
{
unsigned opt_len = strlen(opt);
if (*val)
free(*val);
*val = (char *) malloc(len - opt_len + 1);
if (!*val) {
fprintf(stderr, "%s: failed to allocate memory\n", progname);
return 0;
}
memcpy(*val, s + opt_len, len - opt_len);
(*val)[len - opt_len] = '\0';
return 1;
}
static int do_mount(const char *mnt, char **typep, mode_t rootmode,
int fd, const char *opts, const char *dev, char **sourcep,
char **mnt_optsp)
{
int res;
int flags = MS_NOSUID | MS_NODEV;
char *optbuf;
char *mnt_opts = NULL;
const char *s;
char *d;
char *fsname = NULL;
char *source = NULL;
char *type = NULL;
int blkdev = 0;
optbuf = (char *) malloc(strlen(opts) + 128);
if (!optbuf) {
fprintf(stderr, "%s: failed to allocate memory\n", progname);
return -1;
}
for (s = opts, d = optbuf; *s;) {
unsigned len;
const char *fsname_str = "fsname=";
for (len = 0; s[len] && s[len] != ','; len++);
if (begins_with(s, fsname_str)) {
if (!get_string_opt(s, len, fsname_str, &fsname))
goto err;
} else if (opt_eq(s, len, "blkdev")) {
blkdev = 1;
} else if (!begins_with(s, "fd=") &&
!begins_with(s, "rootmode=") &&
!begins_with(s, "user_id=") &&
!begins_with(s, "group_id=")) {
int on;
int flag;
int skip_option = 0;
if (opt_eq(s, len, "large_read")) {
struct utsname utsname;
unsigned kmaj, kmin;
res = uname(&utsname);
if (res == 0 &&
sscanf(utsname.release, "%u.%u", &kmaj, &kmin) == 2 &&
(kmaj > 2 || (kmaj == 2 && kmin > 4))) {
fprintf(stderr, "%s: note: 'large_read' mount option is "
"deprecated for %i.%i kernels\n", progname, kmaj, kmin);
skip_option = 1;
}
}
if (!skip_option) {
if (find_mount_flag(s, len, &on, &flag)) {
if (on)
flags |= flag;
else
flags &= ~flag;
} else {
memcpy(d, s, len);
d += len;
*d++ = ',';
}
}
}
s += len;
if (*s)
s++;
}
*d = '\0';
res = get_mnt_opts(flags, optbuf, &mnt_opts);
if (res == -1)
goto err;
sprintf(d, "fd=%i,rootmode=%o,user_id=%i,group_id=%i",
fd, rootmode, getuid(), getgid());
source = malloc((fsname ? strlen(fsname) : 0) + strlen(dev) + 32);
type = malloc(32);
if (!type || !source) {
fprintf(stderr, "%s: failed to allocate memory\n", progname);
goto err;
}
strcpy(type, blkdev ? "fuseblk" : "fuse");
if (fsname)
strcpy(source, fsname);
else
strcpy(source, dev);
if (restore_privs())
goto err;
res = mount(source, mnt, type, flags, optbuf);
if (res == -1 && errno == EINVAL) {
/* It could be an old version not supporting group_id */
sprintf(d, "fd=%i,rootmode=%o,user_id=%i", fd, rootmode, getuid());
res = mount(source, mnt, type, flags, optbuf);
}
if (drop_privs())
goto err;
if (res == -1) {
int errno_save = errno;
if (blkdev && errno == ENODEV && !fuse_mnt_check_fuseblk())
fprintf(stderr, "%s: 'fuseblk' support missing\n", progname);
else {
fprintf(stderr, "%s: mount failed: %s\n", progname, strerror(errno_save));
if (errno_save == EPERM)
fprintf(stderr, "User doesn't have privilege to mount. "
"For more information\nplease see: "
"http://tuxera.com/community/ntfs-3g-faq/#unprivileged\n");
}
goto err;
} else {
*sourcep = source;
*typep = type;
*mnt_optsp = mnt_opts;
}
out:
free(fsname);
free(optbuf);
return res;
err:
free(source);
free(type);
free(mnt_opts);
res = -1;
goto out;
}
static int check_perm(const char **mntp, struct stat *stbuf, int *currdir_fd,
int *mountpoint_fd)
{
int res;
const char *mnt = *mntp;
const char *origmnt = mnt;
res = stat(mnt, stbuf);
if (res == -1) {
fprintf(stderr, "%s: failed to access mountpoint %s: %s\n",
progname, mnt, strerror(errno));
return -1;
}
/* No permission checking is done for root */
if (getuid() == 0)
return 0;
if (S_ISDIR(stbuf->st_mode)) {
*currdir_fd = open(".", O_RDONLY);
if (*currdir_fd == -1) {
fprintf(stderr, "%s: failed to open current directory: %s\n",
progname, strerror(errno));
return -1;
}
res = chdir(mnt);
if (res == -1) {
fprintf(stderr, "%s: failed to chdir to mountpoint: %s\n",
progname, strerror(errno));
return -1;
}
mnt = *mntp = ".";
res = lstat(mnt, stbuf);
if (res == -1) {
fprintf(stderr, "%s: failed to access mountpoint %s: %s\n",
progname, origmnt, strerror(errno));
return -1;
}
if ((stbuf->st_mode & S_ISVTX) && stbuf->st_uid != getuid()) {
fprintf(stderr, "%s: mountpoint %s not owned by user\n",
progname, origmnt);
return -1;
}
res = access(mnt, W_OK);
if (res == -1) {
fprintf(stderr, "%s: user has no write access to mountpoint %s\n",
progname, origmnt);
return -1;
}
} else if (S_ISREG(stbuf->st_mode)) {
static char procfile[256];
*mountpoint_fd = open(mnt, O_WRONLY);
if (*mountpoint_fd == -1) {
fprintf(stderr, "%s: failed to open %s: %s\n", progname, mnt,
strerror(errno));
return -1;
}
res = fstat(*mountpoint_fd, stbuf);
if (res == -1) {
fprintf(stderr, "%s: failed to access mountpoint %s: %s\n",
progname, mnt, strerror(errno));
return -1;
}
if (!S_ISREG(stbuf->st_mode)) {
fprintf(stderr, "%s: mountpoint %s is no longer a regular file\n",
progname, mnt);
return -1;
}
sprintf(procfile, "/proc/self/fd/%i", *mountpoint_fd);
*mntp = procfile;
} else {
fprintf(stderr,
"%s: mountpoint %s is not a directory or a regular file\n",
progname, mnt);
return -1;
}
return 0;
}
static int try_open(const char *dev, char **devp)
{
int fd;
if (restore_privs())
return -1;
fd = open(dev, O_RDWR);
if (drop_privs())
return -1;
if (fd != -1) {
*devp = strdup(dev);
if (*devp == NULL) {
fprintf(stderr, "%s: failed to allocate memory\n", progname);
close(fd);
fd = -1;
}
} else if (errno == ENODEV ||
errno == ENOENT) /* check for ENOENT too, for the udev case */
return -2;
else {
fprintf(stderr, "%s: failed to open %s: %s\n", progname, dev,
strerror(errno));
}
return fd;
}
static int open_fuse_device(char **devp)
{
int fd;
fd = try_open(FUSE_DEV_NEW, devp);
if (fd >= -1)
return fd;
fprintf(stderr, "%s: fuse device is missing, try 'modprobe fuse' as root\n",
progname);
return -1;
}
static int mount_fuse(const char *mnt, const char *opts)
{
int res;
int fd;
char *dev;
struct stat stbuf;
char *type = NULL;
char *source = NULL;
char *mnt_opts = NULL;
const char *real_mnt = mnt;
int currdir_fd = -1;
int mountpoint_fd = -1;
fd = open_fuse_device(&dev);
if (fd == -1)
return -1;
if (getuid() != 0 && mount_max != -1) {
if (count_fuse_fs() >= mount_max) {
fprintf(stderr, "%s: too many mounted FUSE filesystems (%d+)\n",
progname, mount_max);
goto err;
}
}
res = check_perm(&real_mnt, &stbuf, &currdir_fd, &mountpoint_fd);
if (res != -1)
res = do_mount(real_mnt, &type, stbuf.st_mode & S_IFMT, fd, opts, dev,
&source, &mnt_opts);
if (currdir_fd != -1) {
__attribute__((unused))int ignored_fchdir_status =
fchdir(currdir_fd);
close(currdir_fd);
}
if (mountpoint_fd != -1)
close(mountpoint_fd);
if (res == -1)
goto err;
if (restore_privs())
goto err;
if (geteuid() == 0) {
if (setgroups(0, NULL) == -1) {
perror("priv drop: setgroups failed");
goto err;
}
res = add_mount(source, mnt, type, mnt_opts);
if (res == -1) {
umount2(mnt, 2); /* lazy umount */
drop_privs();
goto err;
}
}
if (drop_privs())
goto err;
out:
free(source);
free(type);
free(mnt_opts);
free(dev);
return fd;
err:
close(fd);
fd = -1;
goto out;
}
int fusermount(int unmount, int quiet, int lazy, const char *opts,
const char *origmnt)
{
int res = -1;
char *mnt;
mode_t old_umask;
mnt = fuse_mnt_resolve_path(progname, origmnt);
if (mnt == NULL)
return -1;
old_umask = umask(033);
if (unmount) {
if (restore_privs())
goto out;
if (geteuid() == 0)
res = fuse_mnt_umount(progname, mnt, lazy);
else {
res = umount2(mnt, lazy ? 2 : 0);
if (res == -1 && !quiet)
fprintf(stderr, "%s: failed to unmount %s: %s\n", progname,
mnt, strerror(errno));
}
if (drop_privs())
res = -1;
} else
res = mount_fuse(mnt, opts);
out:
umask(old_umask);
free(mnt);
return res;
}
#endif /* __SOLARIS__ */

View File

@ -1,61 +0,0 @@
/*
FUSE: Filesystem in Userspace
Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
This program can be distributed under the terms of the GNU LGPLv2.
See the file COPYING.LIB.
*/
#include "config.h"
#include "fuse_i.h"
#include "fuse_lowlevel.h"
struct fuse_chan *fuse_mount(const char *mountpoint, struct fuse_args *args)
{
struct fuse_chan *ch;
int fd;
#ifdef __SOLARIS__
/*
* Make sure file descriptors 0, 1 and 2 are open, otherwise chaos
* would ensue.
*/
do {
fd = open("/dev/null", O_RDWR);
if (fd > 2)
close(fd);
} while (fd >= 0 && fd <= 2);
#endif /* __SOLARIS__ */
fd = fuse_kern_mount(mountpoint, args);
if (fd == -1)
return NULL;
ch = fuse_kern_chan_new(fd);
if (!ch)
fuse_kern_unmount(mountpoint, fd);
return ch;
}
void fuse_unmount(const char *mountpoint, struct fuse_chan *ch)
{
int fd = ch ? fuse_chan_fd(ch) : -1;
fuse_kern_unmount(mountpoint, fd);
fuse_chan_destroy(ch);
}
int fuse_version(void)
{
return FUSE_VERSION;
}
#ifdef __SOLARIS__
#undef fuse_main
int fuse_main(void);
int fuse_main(void)
{
fprintf(stderr, "fuse_main(): This function does not exist\n");
return -1;
}
#endif /* __SOLARIS__ */

View File

@ -1,734 +0,0 @@
/*
FUSE: Filesystem in Userspace
Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
This program can be distributed under the terms of the GNU LGPLv2.
See the file COPYING.LIB.
*/
#include "config.h"
#include "fuse_i.h"
#include "fuse_opt.h"
#include "mount_util.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <stddef.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/poll.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/wait.h>
#include <sys/mount.h>
#ifdef __SOLARIS__
#define FUSERMOUNT_PROG "fusermount"
#define FUSE_COMMFD_ENV "_FUSE_COMMFD"
#ifndef FUSERMOUNT_DIR
#define FUSERMOUNT_DIR "/usr"
#endif /* FUSERMOUNT_DIR */
#ifndef HAVE_FORK
#define fork() vfork()
#endif
#endif /* __SOLARIS__ */
#ifndef MS_DIRSYNC
#define MS_DIRSYNC 128
#endif
enum {
KEY_KERN_FLAG,
KEY_KERN_OPT,
KEY_FUSERMOUNT_OPT,
KEY_SUBTYPE_OPT,
KEY_MTAB_OPT,
KEY_ALLOW_ROOT,
KEY_RO,
KEY_HELP,
KEY_VERSION,
};
struct mount_opts {
int allow_other;
int allow_root;
int ishelp;
int flags;
#ifdef __SOLARIS__
int nonempty;
int blkdev;
char *fsname;
char *subtype;
char *subtype_opt;
#else
int blkdev;
char *fsname;
#endif
char *mtab_opts;
char *fusermount_opts;
char *kernel_opts;
};
#define FUSE_MOUNT_OPT(t, p) { t, offsetof(struct mount_opts, p), 1 }
static const struct fuse_opt fuse_mount_opts[] = {
#ifdef __SOLARIS__
FUSE_MOUNT_OPT("allow_other", allow_other),
FUSE_MOUNT_OPT("allow_root", allow_root),
FUSE_MOUNT_OPT("nonempty", nonempty),
FUSE_MOUNT_OPT("blkdev", blkdev),
FUSE_MOUNT_OPT("fsname=%s", fsname),
FUSE_MOUNT_OPT("subtype=%s", subtype),
FUSE_OPT_KEY("allow_other", KEY_KERN_OPT),
FUSE_OPT_KEY("allow_root", KEY_ALLOW_ROOT),
FUSE_OPT_KEY("nonempty", KEY_FUSERMOUNT_OPT),
FUSE_OPT_KEY("blkdev", KEY_FUSERMOUNT_OPT),
FUSE_OPT_KEY("fsname=", KEY_FUSERMOUNT_OPT),
FUSE_OPT_KEY("subtype=", KEY_SUBTYPE_OPT),
FUSE_OPT_KEY("large_read", KEY_KERN_OPT),
FUSE_OPT_KEY("blksize=", KEY_KERN_OPT),
FUSE_OPT_KEY("default_permissions", KEY_KERN_OPT),
FUSE_OPT_KEY("max_read=", KEY_KERN_OPT),
FUSE_OPT_KEY("max_read=", FUSE_OPT_KEY_KEEP),
FUSE_OPT_KEY("user=", KEY_MTAB_OPT),
FUSE_OPT_KEY("-r", KEY_RO),
FUSE_OPT_KEY("ro", KEY_KERN_FLAG),
FUSE_OPT_KEY("rw", KEY_KERN_FLAG),
FUSE_OPT_KEY("suid", KEY_KERN_FLAG),
FUSE_OPT_KEY("nosuid", KEY_KERN_FLAG),
FUSE_OPT_KEY("-g", KEY_KERN_FLAG),
FUSE_OPT_KEY("-m", KEY_KERN_FLAG),
FUSE_OPT_KEY("-O", KEY_KERN_FLAG),
FUSE_OPT_KEY("setuid", KEY_KERN_OPT),
FUSE_OPT_KEY("nosetuid", KEY_KERN_OPT),
FUSE_OPT_KEY("devices", KEY_KERN_OPT),
FUSE_OPT_KEY("nodevices", KEY_KERN_OPT),
FUSE_OPT_KEY("exec", KEY_KERN_OPT),
FUSE_OPT_KEY("noexec", KEY_KERN_OPT),
FUSE_OPT_KEY("nbmand", KEY_KERN_OPT),
FUSE_OPT_KEY("nonbmand", KEY_KERN_OPT),
#else /* __SOLARIS__ */
FUSE_MOUNT_OPT("allow_other", allow_other),
FUSE_MOUNT_OPT("allow_root", allow_root),
FUSE_MOUNT_OPT("blkdev", blkdev),
FUSE_MOUNT_OPT("fsname=%s", fsname),
FUSE_OPT_KEY("allow_other", KEY_KERN_OPT),
FUSE_OPT_KEY("allow_root", KEY_ALLOW_ROOT),
FUSE_OPT_KEY("blkdev", KEY_FUSERMOUNT_OPT),
FUSE_OPT_KEY("fsname=", KEY_FUSERMOUNT_OPT),
FUSE_OPT_KEY("large_read", KEY_KERN_OPT),
FUSE_OPT_KEY("blksize=", KEY_KERN_OPT),
FUSE_OPT_KEY("default_permissions", KEY_KERN_OPT),
FUSE_OPT_KEY("context=", KEY_KERN_OPT),
FUSE_OPT_KEY("max_read=", KEY_KERN_OPT),
FUSE_OPT_KEY("max_read=", FUSE_OPT_KEY_KEEP),
FUSE_OPT_KEY("user=", KEY_MTAB_OPT),
FUSE_OPT_KEY("-r", KEY_RO),
FUSE_OPT_KEY("ro", KEY_KERN_FLAG),
FUSE_OPT_KEY("rw", KEY_KERN_FLAG),
FUSE_OPT_KEY("suid", KEY_KERN_FLAG),
FUSE_OPT_KEY("nosuid", KEY_KERN_FLAG),
FUSE_OPT_KEY("dev", KEY_KERN_FLAG),
FUSE_OPT_KEY("nodev", KEY_KERN_FLAG),
FUSE_OPT_KEY("exec", KEY_KERN_FLAG),
FUSE_OPT_KEY("noexec", KEY_KERN_FLAG),
FUSE_OPT_KEY("async", KEY_KERN_FLAG),
FUSE_OPT_KEY("sync", KEY_KERN_FLAG),
FUSE_OPT_KEY("dirsync", KEY_KERN_FLAG),
FUSE_OPT_KEY("atime", KEY_KERN_FLAG),
FUSE_OPT_KEY("noatime", KEY_KERN_FLAG),
#endif /* __SOLARIS__ */
FUSE_OPT_KEY("-h", KEY_HELP),
FUSE_OPT_KEY("--help", KEY_HELP),
FUSE_OPT_KEY("-V", KEY_VERSION),
FUSE_OPT_KEY("--version", KEY_VERSION),
FUSE_OPT_END
};
#ifdef __SOLARIS__
static void mount_help(void)
{
fprintf(stderr,
" -o allow_other allow access to other users\n"
" -o allow_root allow access to root\n"
" -o nonempty allow mounts over non-empty file/dir\n"
" -o default_permissions enable permission checking by kernel\n"
" -o fsname=NAME set filesystem name\n"
" -o subtype=NAME set filesystem type\n"
" -o large_read issue large read requests (2.4 only)\n"
" -o max_read=N set maximum size of read requests\n"
"\n"
);
}
static void exec_fusermount(const char *argv[])
{
execv(FUSERMOUNT_DIR "/" FUSERMOUNT_PROG, (char **) argv);
execvp(FUSERMOUNT_PROG, (char **) argv);
}
static void mount_version(void)
{
int pid = fork();
if (!pid) {
const char *argv[] = { FUSERMOUNT_PROG, "--version", NULL };
exec_fusermount(argv);
_exit(1);
} else if (pid != -1)
waitpid(pid, NULL, 0);
}
#endif /* __SOLARIS__ */
struct mount_flags {
const char *opt;
unsigned long flag;
int on;
};
static struct mount_flags mount_flags[] = {
{"rw", MS_RDONLY, 0},
{"ro", MS_RDONLY, 1},
{"suid", MS_NOSUID, 0},
{"nosuid", MS_NOSUID, 1},
#ifndef __SOLARIS__
{"dev", MS_NODEV, 0},
{"nodev", MS_NODEV, 1},
{"exec", MS_NOEXEC, 0},
{"noexec", MS_NOEXEC, 1},
{"async", MS_SYNCHRONOUS, 0},
{"sync", MS_SYNCHRONOUS, 1},
{"atime", MS_NOATIME, 0},
{"noatime", MS_NOATIME, 1},
{"dirsync", MS_DIRSYNC, 1},
#else /* __SOLARIS__ */
{"-g", MS_GLOBAL, 1}, /* 1eaf4 */
{"-m", MS_NOMNTTAB, 1}, /* 1eb00 */
{"-O", MS_OVERLAY, 1}, /* 1eb0c */
#endif /* __SOLARIS__ */
{NULL, 0, 0}
};
#ifdef __SOLARIS__
/*
* See comments in fuse_kern_mount()
*/
struct solaris_mount_opts {
int nosuid;
int setuid;
int nosetuid;
int devices;
int nodevices;
};
#define SOLARIS_MOUNT_OPT(t, p, n) \
{ t, offsetof(struct solaris_mount_opts, p), n }
static const struct fuse_opt solaris_mnt_opts[] = {
SOLARIS_MOUNT_OPT("suid", setuid, 1),
SOLARIS_MOUNT_OPT("suid", devices, 1),
SOLARIS_MOUNT_OPT("nosuid", nosuid, 1),
SOLARIS_MOUNT_OPT("setuid", setuid, 1),
SOLARIS_MOUNT_OPT("nosetuid", nosetuid, 1),
SOLARIS_MOUNT_OPT("devices", devices, 1),
SOLARIS_MOUNT_OPT("nodevices", nodevices, 1),
FUSE_OPT_END
};
#endif /* __SOLARIS__ */
static void set_mount_flag(const char *s, int *flags)
{
int i;
for (i = 0; mount_flags[i].opt != NULL; i++) {
const char *opt = mount_flags[i].opt;
if (strcmp(opt, s) == 0) {
if (mount_flags[i].on)
*flags |= mount_flags[i].flag;
else
*flags &= ~mount_flags[i].flag;
return;
}
}
fprintf(stderr, "fuse: internal error, can't find mount flag\n");
abort();
}
static int fuse_mount_opt_proc(void *data, const char *arg, int key,
struct fuse_args *outargs)
{
struct mount_opts *mo = data;
switch (key) {
case KEY_ALLOW_ROOT:
if (fuse_opt_add_opt(&mo->kernel_opts, "allow_other") == -1 ||
fuse_opt_add_arg(outargs, "-oallow_root") == -1)
return -1;
return 0;
case KEY_RO:
arg = "ro";
/* fall through */
case KEY_KERN_FLAG:
set_mount_flag(arg, &mo->flags);
return 0;
case KEY_KERN_OPT:
return fuse_opt_add_opt(&mo->kernel_opts, arg);
case KEY_FUSERMOUNT_OPT:
return fuse_opt_add_opt(&mo->fusermount_opts, arg);
#ifdef __SOLARIS__
case KEY_SUBTYPE_OPT:
return fuse_opt_add_opt(&mo->subtype_opt, arg);
#endif /* __SOLARIS__ */
case KEY_MTAB_OPT:
return fuse_opt_add_opt(&mo->mtab_opts, arg);
case KEY_HELP:
#ifdef __SOLARIS__
mount_help();
#endif /* __SOLARIS__ */
mo->ishelp = 1;
break;
case KEY_VERSION:
#ifdef __SOLARIS__
mount_version();
#endif /* __SOLARIS__ */
mo->ishelp = 1;
break;
}
return 1;
}
#ifdef __SOLARIS__
/* return value:
* >= 0 => fd
* -1 => error
*/
static int receive_fd(int fd)
{
struct msghdr msg;
struct iovec iov;
char buf[1];
int rv;
size_t ccmsg[CMSG_SPACE(sizeof(int)) / sizeof(size_t)];
struct cmsghdr *cmsg;
iov.iov_base = buf;
iov.iov_len = 1;
msg.msg_name = 0;
msg.msg_namelen = 0;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
/* old BSD implementations should use msg_accrights instead of
* msg_control; the interface is different. */
msg.msg_control = ccmsg;
msg.msg_controllen = sizeof(ccmsg);
while(((rv = recvmsg(fd, &msg, 0)) == -1) && errno == EINTR);
if (rv == -1) {
perror("recvmsg");
return -1;
}
if(!rv) {
/* EOF */
return -1;
}
cmsg = CMSG_FIRSTHDR(&msg);
if (cmsg->cmsg_type != SCM_RIGHTS) {
fprintf(stderr, "got control message of unknown type %d\n",
cmsg->cmsg_type);
return -1;
}
return *(int*)CMSG_DATA(cmsg);
}
#endif /* __SOLARIS__ */
void fuse_kern_unmount(const char *mountpoint, int fd)
{
int res;
#ifdef __SOLARIS__
int pid;
#endif /* __SOLARIS__ */
if (!mountpoint)
return;
if (fd != -1) {
struct pollfd pfd;
pfd.fd = fd;
pfd.events = 0;
res = poll(&pfd, 1, 0);
/* If file poll returns POLLERR on the device file descriptor,
then the filesystem is already unmounted */
if (res == 1 && (pfd.revents & POLLERR))
return;
/*
* Need to close file descriptor, otherwise synchronous umount
* would recurse into filesystem, and deadlock.
*/
close(fd);
}
#ifndef __SOLARIS__
fusermount(1, 0, 1, "", mountpoint);
#else /* __SOLARIS__ */
if (geteuid() == 0) {
fuse_mnt_umount("fuse", mountpoint, 1);
return;
}
res = umount2(mountpoint, 2);
if (res == 0)
return;
pid = fork();
if(pid == -1)
return;
if(pid == 0) {
const char *argv[] =
{ FUSERMOUNT_PROG, "-u", "-q", "-z", "--", mountpoint, NULL };
exec_fusermount(argv);
_exit(1);
}
waitpid(pid, NULL, 0);
#endif /* __SOLARIS__ */
}
#ifdef __SOLARIS__
static int fuse_mount_fusermount(const char *mountpoint, const char *opts,
int quiet)
{
int fds[2], pid;
int res;
int rv;
if (!mountpoint) {
fprintf(stderr, "fuse: missing mountpoint\n");
return -1;
}
res = socketpair(PF_UNIX, SOCK_STREAM, 0, fds);
if(res == -1) {
perror("fuse: socketpair() failed");
return -1;
}
pid = fork();
if(pid == -1) {
perror("fuse: fork() failed");
close(fds[0]);
close(fds[1]);
return -1;
}
if(pid == 0) {
char env[10];
const char *argv[32];
int a = 0;
if (quiet) {
int fd = open("/dev/null", O_RDONLY);
dup2(fd, 1);
dup2(fd, 2);
}
argv[a++] = FUSERMOUNT_PROG;
if (opts) {
argv[a++] = "-o";
argv[a++] = opts;
}
argv[a++] = "--";
argv[a++] = mountpoint;
argv[a++] = NULL;
close(fds[1]);
fcntl(fds[0], F_SETFD, 0);
snprintf(env, sizeof(env), "%i", fds[0]);
setenv(FUSE_COMMFD_ENV, env, 1);
exec_fusermount(argv);
perror("fuse: failed to exec fusermount");
_exit(1);
}
close(fds[0]);
rv = receive_fd(fds[1]);
close(fds[1]);
waitpid(pid, NULL, 0); /* bury zombie */
return rv;
}
static int fuse_mount_sys(const char *mnt, struct mount_opts *mo,
const char *mnt_opts)
{
char tmp[128];
const char *devname = "/dev/fuse";
char *source = NULL;
char *type = NULL;
struct stat stbuf;
int fd;
int res;
if (!mnt) {
fprintf(stderr, "fuse: missing mountpoint\n");
return -1;
}
res = lstat(mnt, &stbuf);
if (res == -1) {
fprintf(stderr ,"fuse: failed to access mountpoint %s: %s\n",
mnt, strerror(errno));
return -1;
}
if (!mo->nonempty) {
res = fuse_mnt_check_empty("fuse", mnt, stbuf.st_mode, stbuf.st_size);
if (res == -1)
return -1;
}
fd = open(devname, O_RDWR);
if (fd == -1) {
if (errno == ENODEV || errno == ENOENT)
fprintf(stderr,
"fuse: device not found, try 'modprobe fuse' first\n");
else
fprintf(stderr, "fuse: failed to open %s: %s\n", devname,
strerror(errno));
return -1;
}
snprintf(tmp, sizeof(tmp), "fd=%i,rootmode=%o,user_id=%i,group_id=%i", fd,
stbuf.st_mode & S_IFMT, getuid(), getgid());
res = fuse_opt_add_opt(&mo->kernel_opts, tmp);
if (res == -1)
goto out_close;
source = malloc((mo->fsname ? strlen(mo->fsname) : 0) +
(mo->subtype ? strlen(mo->subtype) : 0) +
strlen(devname) + 32);
type = malloc((mo->subtype ? strlen(mo->subtype) : 0) + 32);
if (!type || !source) {
fprintf(stderr, "fuse: failed to allocate memory\n");
goto out_close;
}
strcpy(type, mo->blkdev ? "fuseblk" : "fuse");
if (mo->subtype) {
strcat(type, ".");
strcat(type, mo->subtype);
}
strcpy(source,
mo->fsname ? mo->fsname : (mo->subtype ? mo->subtype : devname));
/* JPA added two final zeroes */
res = mount(source, mnt, MS_OPTIONSTR|mo->flags, type, NULL, 0,
mo->kernel_opts, MAX_MNTOPT_STR, 0, 0);
if (res == -1 && errno == EINVAL && mo->subtype) {
/* Probably missing subtype support */
strcpy(type, mo->blkdev ? "fuseblk" : "fuse");
if (mo->fsname) {
if (!mo->blkdev)
sprintf(source, "%s#%s", mo->subtype, mo->fsname);
} else {
strcpy(source, type);
}
/* JPA two null args added */
res = mount(source, mnt, MS_OPTIONSTR|mo->flags, type, NULL, 0,
mo->kernel_opts, MAX_MNTOPT_STR, 0, 0);
}
if (res == -1) {
/*
* Maybe kernel doesn't support unprivileged mounts, in this
* case try falling back to fusermount
*/
if (errno == EPERM) {
res = -2;
} else {
int errno_save = errno;
if (mo->blkdev && errno == ENODEV && !fuse_mnt_check_fuseblk())
fprintf(stderr, "fuse: 'fuseblk' support missing\n");
else
fprintf(stderr, "fuse: mount failed: %s\n",
strerror(errno_save));
}
goto out_close;
}
return fd;
out_umount:
umount2(mnt, 2); /* lazy umount */
out_close:
free(type);
free(source);
close(fd);
return res;
}
#endif /* __SOLARIS__ */
static int get_mnt_flag_opts(char **mnt_optsp, int flags)
{
int i;
if (!(flags & MS_RDONLY) && fuse_opt_add_opt(mnt_optsp, "rw") == -1)
return -1;
for (i = 0; mount_flags[i].opt != NULL; i++) {
if (mount_flags[i].on && (flags & mount_flags[i].flag) &&
fuse_opt_add_opt(mnt_optsp, mount_flags[i].opt) == -1)
return -1;
}
return 0;
}
int fuse_kern_mount(const char *mountpoint, struct fuse_args *args)
{
struct mount_opts mo;
int res = -1;
char *mnt_opts = NULL;
#ifdef __SOLARIS__
struct solaris_mount_opts smo;
struct fuse_args sa = FUSE_ARGS_INIT(0, NULL);
#endif /* __SOLARIS__ */
memset(&mo, 0, sizeof(mo));
#ifndef __SOLARIS__
if (getuid())
mo.flags = MS_NOSUID | MS_NODEV;
#else /* __SOLARIS__ */
mo.flags = 0;
memset(&smo, 0, sizeof(smo));
if (args != NULL) {
while (args->argv[sa.argc] != NULL)
fuse_opt_add_arg(&sa, args->argv[sa.argc]);
}
#endif /* __SOLARIS__ */
if (args &&
fuse_opt_parse(args, &mo, fuse_mount_opts, fuse_mount_opt_proc) == -1)
#ifndef __SOLARIS__
return -1;
#else /* __SOLARIS__ */
goto out; /* if SOLARIS, clean up 'sa' */
/*
* In Solaris, nosuid is equivalent to nosetuid + nodevices. We only
* have MS_NOSUID for mount flags (no MS_(NO)SETUID, etc.). But if
* we set that as a default, it restricts specifying just nosetuid
* or nodevices; there is no way for the user to specify setuid +
* nodevices or vice-verse. So we parse the existing options, then
* add restrictive defaults if needed.
*/
if (fuse_opt_parse(&sa, &smo, solaris_mnt_opts, NULL) == -1)
goto out;
if (smo.nosuid || (!smo.nodevices && !smo.devices
&& !smo.nosetuid && !smo.setuid)) {
mo.flags |= MS_NOSUID;
} else {
/*
* Defaults; if neither nodevices|devices,nosetuid|setuid has
* been specified, add the default negative option string. If
* both have been specified (i.e., -osuid,nosuid), leave them
* alone; the last option will have precedence.
*/
if (!smo.nodevices && !smo.devices)
if (fuse_opt_add_opt(&mo.kernel_opts, "nodevices") == -1)
goto out;
if (!smo.nosetuid && !smo.setuid)
if (fuse_opt_add_opt(&mo.kernel_opts, "nosetuid") == -1)
goto out;
}
#endif /* __SOLARIS__ */
if (mo.allow_other && mo.allow_root) {
fprintf(stderr, "fuse: 'allow_other' and 'allow_root' options are mutually exclusive\n");
goto out;
}
res = -1;
if (mo.ishelp)
goto out;
if (get_mnt_flag_opts(&mnt_opts, mo.flags) == -1)
goto out;
#ifndef __SOLARIS__
if (!(mo.flags & MS_NODEV) && fuse_opt_add_opt(&mnt_opts, "dev") == -1)
goto out;
if (!(mo.flags & MS_NOSUID) && fuse_opt_add_opt(&mnt_opts, "suid") == -1)
goto out;
if (mo.kernel_opts && fuse_opt_add_opt(&mnt_opts, mo.kernel_opts) == -1)
goto out;
if (mo.mtab_opts && fuse_opt_add_opt(&mnt_opts, mo.mtab_opts) == -1)
goto out;
if (mo.fusermount_opts && fuse_opt_add_opt(&mnt_opts, mo.fusermount_opts) < 0)
goto out;
res = fusermount(0, 0, 0, mnt_opts ? mnt_opts : "", mountpoint);
#else /* __SOLARIS__ */
if (mo.kernel_opts && fuse_opt_add_opt(&mnt_opts, mo.kernel_opts) == -1)
goto out;
if (mo.mtab_opts && fuse_opt_add_opt(&mnt_opts, mo.mtab_opts) == -1)
goto out;
res = fuse_mount_sys(mountpoint, &mo, mnt_opts);
if (res == -2) {
if (mo.fusermount_opts &&
fuse_opt_add_opt(&mnt_opts, mo.fusermount_opts) == -1)
goto out;
if (mo.subtype) {
char *tmp_opts = NULL;
res = -1;
if (fuse_opt_add_opt(&tmp_opts, mnt_opts) == -1 ||
fuse_opt_add_opt(&tmp_opts, mo.subtype_opt) == -1) {
free(tmp_opts);
goto out;
}
res = fuse_mount_fusermount(mountpoint, tmp_opts, 1);
free(tmp_opts);
if (res == -1)
res = fuse_mount_fusermount(mountpoint, mnt_opts, 0);
} else {
res = fuse_mount_fusermount(mountpoint, mnt_opts, 0);
}
}
#endif /* __SOLARIS__ */
out:
free(mnt_opts);
#ifdef __SOLARIS__
fuse_opt_free_args(&sa);
free(mo.subtype);
free(mo.subtype_opt);
#endif /* __SOLARIS__ */
free(mo.fsname);
free(mo.fusermount_opts);
free(mo.kernel_opts);
free(mo.mtab_opts);
return res;
}

View File

@ -1,476 +0,0 @@
/*
FUSE: Filesystem in Userspace
Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
This program can be distributed under the terms of the GNU LGPLv2.
See the file COPYING.LIB.
*/
#include "config.h"
#include "mount_util.h"
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <errno.h>
#include <limits.h>
#include <paths.h>
#include <sys/stat.h>
#include <sys/wait.h>
#ifdef __SOLARIS__
#else /* __SOLARIS__ */
#include <mntent.h>
#include <sys/mount.h>
#include <sys/param.h>
#endif /* __SOLARIS__ */
#ifdef __SOLARIS__
char *mkdtemp(char *template);
#ifndef _PATH_MOUNTED
#define _PATH_MOUNTED "/etc/mnttab"
#endif /* _PATH_MOUNTED */
#ifndef IGNORE_MTAB
static int mtab_needs_update(const char *mnt)
{
struct stat stbuf;
/* If mtab is within new mount, don't touch it */
if (strncmp(mnt, _PATH_MOUNTED, strlen(mnt)) == 0 &&
_PATH_MOUNTED[strlen(mnt)] == '/')
return 0;
if (lstat(_PATH_MOUNTED, &stbuf) != -1 && S_ISLNK(stbuf.st_mode))
return 0;
return 1;
}
#endif /* IGNORE_MTAB */
int fuse_mnt_add_mount(const char *progname, const char *fsname,
const char *mnt, const char *type, const char *opts)
{
int res;
int status;
#ifndef IGNORE_MTAB
if (!mtab_needs_update(mnt))
return 0;
#endif /* IGNORE_MTAB */
res = fork();
if (res == -1) {
fprintf(stderr, "%s: fork: %s\n", progname, strerror(errno));
return -1;
}
if (res == 0) {
char *env = NULL;
char templ[] = "/tmp/fusermountXXXXXX";
char *tmp;
setuid(geteuid());
/*
* hide in a directory, where mount isn't able to resolve
* fsname as a valid path
*/
tmp = mkdtemp(templ);
if (!tmp) {
fprintf(stderr, "%s: failed to create temporary directory\n",
progname);
exit(1);
}
if (chdir(tmp)) {
fprintf(stderr, "%s: failed to chdir to %s: %s\n",
progname, tmp, strerror(errno));
exit(1);
}
rmdir(tmp);
execle("/sbin/mount", "/sbin/mount", "-F", type, "-o", opts,
fsname, mnt, NULL, &env);
fprintf(stderr, "%s: failed to execute /sbin/mount: %s\n", progname,
strerror(errno));
exit(1);
}
res = waitpid(res, &status, 0);
if (res == -1) {
fprintf(stderr, "%s: waitpid: %s\n", progname, strerror(errno));
return -1;
}
if (status != 0)
return -1;
return 0;
}
int fuse_mnt_umount(const char *progname, const char *mnt, int lazy)
{
int res;
int status;
#ifndef IGNORE_MTAB
if (!mtab_needs_update(mnt))
return 0;
#endif /* IGNORE_MTAB */
res = fork();
if (res == -1) {
fprintf(stderr, "%s: fork: %s\n", progname, strerror(errno));
return -1;
}
if (res == 0) {
char *env = NULL;
setuid(geteuid());
if (lazy) {
execle("/sbin/umount", "/sbin/umount", mnt,
NULL, &env);
} else {
execle("/sbin/umount", "/sbin/umount", "-f", mnt,
NULL, &env);
}
fprintf(stderr, "%s: failed to execute /sbin/umount: %s\n", progname,
strerror(errno));
exit(1);
}
res = waitpid(res, &status, 0);
if (res == -1) {
fprintf(stderr, "%s: waitpid: %s\n", progname, strerror(errno));
return -1;
}
if (status != 0)
return -1;
return 0;
}
char *fuse_mnt_resolve_path(const char *progname, const char *orig)
{
char buf[PATH_MAX];
char *copy;
char *dst;
char *end;
char *lastcomp;
const char *toresolv;
if (!orig[0]) {
fprintf(stderr, "%s: invalid mountpoint '%s'\n", progname, orig);
return NULL;
}
copy = strdup(orig);
if (copy == NULL) {
fprintf(stderr, "%s: failed to allocate memory\n", progname);
return NULL;
}
toresolv = copy;
lastcomp = NULL;
for (end = copy + strlen(copy) - 1; end > copy && *end == '/'; end --);
if (end[0] != '/') {
char *tmp;
end[1] = '\0';
tmp = strrchr(copy, '/');
if (tmp == NULL) {
lastcomp = copy;
toresolv = ".";
} else {
lastcomp = tmp + 1;
if (tmp == copy)
toresolv = "/";
}
if (strcmp(lastcomp, ".") == 0 || strcmp(lastcomp, "..") == 0) {
lastcomp = NULL;
toresolv = copy;
}
else if (tmp)
tmp[0] = '\0';
}
if (realpath(toresolv, buf) == NULL) {
fprintf(stderr, "%s: bad mount point %s: %s\n", progname, orig,
strerror(errno));
free(copy);
return NULL;
}
if (lastcomp == NULL)
dst = strdup(buf);
else {
dst = (char *) malloc(strlen(buf) + 1 + strlen(lastcomp) + 1);
if (dst) {
unsigned buflen = strlen(buf);
if (buflen && buf[buflen-1] == '/')
sprintf(dst, "%s%s", buf, lastcomp);
else
sprintf(dst, "%s/%s", buf, lastcomp);
}
}
free(copy);
if (dst == NULL)
fprintf(stderr, "%s: failed to allocate memory\n", progname);
return dst;
}
int fuse_mnt_check_empty(const char *progname, const char *mnt,
mode_t rootmode, off_t rootsize)
{
int isempty = 1;
if (S_ISDIR(rootmode)) {
struct dirent *ent;
DIR *dp = opendir(mnt);
if (dp == NULL) {
fprintf(stderr, "%s: failed to open mountpoint for reading: %s\n",
progname, strerror(errno));
return -1;
}
while ((ent = readdir(dp)) != NULL) {
if (strcmp(ent->d_name, ".") != 0 &&
strcmp(ent->d_name, "..") != 0) {
isempty = 0;
break;
}
}
closedir(dp);
} else if (rootsize)
isempty = 0;
if (!isempty) {
fprintf(stderr, "%s: mountpoint is not empty\n", progname);
fprintf(stderr, "%s: if you are sure this is safe, use the 'nonempty' mount option\n", progname);
return -1;
}
return 0;
}
int fuse_mnt_check_fuseblk(void)
{
char buf[256];
FILE *f = fopen("/proc/filesystems", "r");
if (!f)
return 1;
while (fgets(buf, sizeof(buf), f))
if (strstr(buf, "fuseblk\n")) {
fclose(f);
return 1;
}
fclose(f);
return 0;
}
#else /* __SOLARIS__ */
static int mtab_needs_update(const char *mnt)
{
int res;
struct stat stbuf;
/* If mtab is within new mount, don't touch it */
if (strncmp(mnt, _PATH_MOUNTED, strlen(mnt)) == 0 &&
_PATH_MOUNTED[strlen(mnt)] == '/')
return 0;
/*
* Skip mtab update if /etc/mtab:
*
* - doesn't exist,
* - is a symlink,
* - is on a read-only filesystem.
*/
res = lstat(_PATH_MOUNTED, &stbuf);
if (res == -1) {
if (errno == ENOENT)
return 0;
} else {
if (S_ISLNK(stbuf.st_mode))
return 0;
res = access(_PATH_MOUNTED, W_OK);
if (res == -1 && errno == EROFS)
return 0;
}
return 1;
}
int fuse_mnt_add_mount(const char *progname, const char *fsname,
const char *mnt, const char *type, const char *opts)
{
int res;
if (!mtab_needs_update(mnt))
return 0;
res = fork();
if (res == -1) {
fprintf(stderr, "%s: fork: %s\n", progname, strerror(errno));
return 0;
}
if (res == 0) {
char *env = NULL;
char templ[] = "/tmp/fusermountXXXXXX";
char *tmp;
if (setuid(geteuid()))
fprintf(stderr, "%s: failed to setuid : %s\n", progname,
strerror(errno));
/*
* hide in a directory, where mount isn't able to resolve
* fsname as a valid path
*/
tmp = mkdtemp(templ);
if (!tmp) {
fprintf(stderr, "%s: failed to create temporary directory\n",
progname);
exit(1);
}
if (chdir(tmp)) {
fprintf(stderr, "%s: failed to chdir to %s: %s\n",
progname, tmp, strerror(errno));
exit(1);
}
rmdir(tmp);
execle("/bin/mount", "/bin/mount", "-i", "-f", "-t", type, "-o", opts,
fsname, mnt, NULL, &env);
fprintf(stderr, "%s: failed to execute /bin/mount: %s\n", progname,
strerror(errno));
exit(1);
}
return 0;
}
int fuse_mnt_umount(const char *progname, const char *mnt, int lazy)
{
int res;
int status;
if (!mtab_needs_update(mnt)) {
res = umount2(mnt, lazy ? 2 : 0);
if (res == -1)
fprintf(stderr, "%s: failed to unmount %s: %s\n", progname,
mnt, strerror(errno));
return res;
}
res = fork();
if (res == -1) {
fprintf(stderr, "%s: fork: %s\n", progname, strerror(errno));
return -1;
}
if (res == 0) {
char *env = NULL;
if (setuid(geteuid()))
fprintf(stderr, "%s: failed to setuid : %s\n", progname,
strerror(errno));
if (lazy) {
execle("/bin/umount", "/bin/umount", "-i", mnt, "-l",
NULL, &env);
} else {
execle("/bin/umount", "/bin/umount", "-i", mnt,
NULL, &env);
}
fprintf(stderr, "%s: failed to execute /bin/umount: %s\n", progname,
strerror(errno));
exit(1);
}
res = waitpid(res, &status, 0);
if (res == -1) {
fprintf(stderr, "%s: waitpid: %s\n", progname, strerror(errno));
return -1;
}
if (status != 0)
return -1;
return 0;
}
char *fuse_mnt_resolve_path(const char *progname, const char *orig)
{
char buf[PATH_MAX];
char *copy;
char *dst;
char *end;
char *lastcomp;
const char *toresolv;
if (!orig[0]) {
fprintf(stderr, "%s: invalid mountpoint '%s'\n", progname, orig);
return NULL;
}
copy = strdup(orig);
if (copy == NULL) {
fprintf(stderr, "%s: failed to allocate memory\n", progname);
return NULL;
}
toresolv = copy;
lastcomp = NULL;
for (end = copy + strlen(copy) - 1; end > copy && *end == '/'; end --);
if (end[0] != '/') {
char *tmp;
end[1] = '\0';
tmp = strrchr(copy, '/');
if (tmp == NULL) {
lastcomp = copy;
toresolv = ".";
} else {
lastcomp = tmp + 1;
if (tmp == copy)
toresolv = "/";
}
if (strcmp(lastcomp, ".") == 0 || strcmp(lastcomp, "..") == 0) {
lastcomp = NULL;
toresolv = copy;
}
else if (tmp)
tmp[0] = '\0';
}
if (realpath(toresolv, buf) == NULL) {
fprintf(stderr, "%s: bad mount point %s: %s\n", progname, orig,
strerror(errno));
free(copy);
return NULL;
}
if (lastcomp == NULL)
dst = strdup(buf);
else {
dst = (char *) malloc(strlen(buf) + 1 + strlen(lastcomp) + 1);
if (dst) {
unsigned buflen = strlen(buf);
if (buflen && buf[buflen-1] == '/')
sprintf(dst, "%s%s", buf, lastcomp);
else
sprintf(dst, "%s/%s", buf, lastcomp);
}
}
free(copy);
if (dst == NULL)
fprintf(stderr, "%s: failed to allocate memory\n", progname);
return dst;
}
int fuse_mnt_check_fuseblk(void)
{
char buf[256];
FILE *f = fopen("/proc/filesystems", "r");
if (!f)
return 1;
while (fgets(buf, sizeof(buf), f))
if (strstr(buf, "fuseblk\n")) {
fclose(f);
return 1;
}
fclose(f);
return 0;
}
#endif /* __SOLARIS__ */

View File

@ -1,27 +0,0 @@
/*
FUSE: Filesystem in Userspace
Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
This program can be distributed under the terms of the GNU LGPLv2.
See the file COPYING.LIB.
*/
#include <sys/types.h>
int fuse_mnt_add_mount(const char *progname, const char *fsname,
const char *mnt, const char *type, const char *opts);
int fuse_mnt_umount(const char *progname, const char *mnt, int lazy);
char *fuse_mnt_resolve_path(const char *progname, const char *orig);
int fuse_mnt_check_fuseblk(void);
#ifdef __SOLARIS__
int fuse_mnt_check_empty(const char *progname, const char *mnt,
mode_t rootmode, off_t rootsize);
#else /* __SOLARIS__ */
int fusermount(int unmount, int quiet, int lazy, const char *opts,
const char *origmnt);
#endif /* __SOLARIS__ */

View File

@ -1,84 +1,64 @@
#
# Before making a release, the LTVERSION string should be modified.
# The string is of the form CURRENT:REVISION:AGE.
#
# CURRENT (C)
# The most recent interface number that this library implements.
#
# REVISION (R)
# The implementation number that this library implements.
#
# AGE (A)
# The difference between the newest and oldest interfaces that this
# library implements. In other works, the library implements all the
# interface numbers in the range from number 'CURRENT - AGE' to
# 'CURRENT'.
#
# This means that:
#
# - If interfaces have been changed or added, but binary compatibility has
# been preserved, change to C+1:0:A+1
#
# - If binary compatibility has been broken (eg removed or changed
# interfaces) change to C+1:0:0
#
# - If the interface is the same as the previous version, change to C:R+1:A
#
MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
if INSTALL_LIBRARY
rootlib_LTLIBRARIES=#Create directory
lib_LTLIBRARIES = libntfs-3g.la
pkgconfig_DATA = libntfs-3g.pc
else
noinst_LTLIBRARIES = libntfs-3g.la
endif
libntfs_3g_la_CFLAGS = $(AM_CFLAGS)
libntfs_3g_la_CPPFLAGS= $(AM_CPPFLAGS) $(LIBNTFS_CPPFLAGS) -I$(top_srcdir)/include/ntfs-3g
libntfs_3g_la_LIBADD = $(LIBNTFS_LIBS)
libntfs_3g_la_LDFLAGS = -version-info $(LIBNTFS_3G_VERSION) -no-undefined
linux_ntfsincludedir = -I$(top_srcdir)/include/ntfs-3g
lib_LTLIBRARIES = libntfs-3g.la
libntfs_3g_la_CFLAGS = $(LIBNTFS_3G_CFLAGS)
libntfs_3g_la_SOURCES = \
acls.c \
attrib.c \
attrlist.c \
bitmap.c \
bootsect.c \
cache.c \
collate.c \
compat.c \
compress.c \
debug.c \
device.c \
dir.c \
ea.c \
efs.c \
index.c \
inode.c \
ioctl.c \
lcnalloc.c \
logfile.c \
logging.c \
mft.c \
misc.c \
mst.c \
object_id.c \
realpath.c \
reparse.c \
runlist.c \
security.c \
unistr.c \
volume.c \
xattrs.c
attrib.c \
attrlist.c \
bitmap.c \
bootsect.c \
collate.c \
compat.c \
compress.c \
debug.c \
device.c \
device_io.c \
dir.c \
index.c \
inode.c \
lcnalloc.c \
logfile.c \
logging.c \
mft.c \
misc.c \
mst.c \
runlist.c \
security.c \
unistr.c \
version.c \
volume.c
if NTFS_DEVICE_DEFAULT_IO_OPS
if WINDOWS
libntfs_3g_la_SOURCES += win32_io.c
else
libntfs_3g_la_SOURCES += unix_io.c
endif
endif
AM_CPPFLAGS = $(linux_ntfsincludedir) $(all_includes)
# We may need to move .so files to root
# And create ldscript or symbolic link from /usr
install-exec-hook: install-rootlibLTLIBRARIES
if INSTALL_LIBRARY
if [ ! "$(rootlibdir)" -ef "$(libdir)" ]; then \
$(MV) -f "$(DESTDIR)/$(libdir)"/libntfs-3g.so* "$(DESTDIR)/$(rootlibdir)"; \
fi
if GENERATE_LDSCRIPT
if [ ! "$(rootlibdir)" -ef "$(libdir)" ]; then \
$(install_sh_PROGRAM) "libntfs-3g.script.so" "$(DESTDIR)/$(libdir)/libntfs-3g.so"; \
fi
else
if [ ! "$(rootlibdir)" -ef "$(libdir)" ]; then \
$(LN_S) "$(rootlibdir)/libntfs-3g.so" "$(DESTDIR)/$(libdir)/libntfs-3g.so"; \
fi
endif
endif
EXTRA_DIST = unix_io.c
uninstall-local:
if INSTALL_LIBRARY
$(RM) -f "$(DESTDIR)/$(rootlibdir)"/libntfs-3g.so*
endif
MAINTAINERCLEANFILES = Makefile.in
if ENABLE_NTFSPROGS
libs: $(lib_LTLIBRARIES)
endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -107,7 +107,7 @@ int ntfs_attrlist_need(ntfs_inode *ni)
int ntfs_attrlist_entry_add(ntfs_inode *ni, ATTR_RECORD *attr)
{
ATTR_LIST_ENTRY *ale;
leMFT_REF mref;
MFT_REF mref;
ntfs_attr *na = NULL;
ntfs_attr_search_ctx *ctx;
u8 *new_al;
@ -145,12 +145,13 @@ int ntfs_attrlist_entry_add(ntfs_inode *ni, ATTR_RECORD *attr)
ctx = ntfs_attr_get_search_ctx(ni, NULL);
if (!ctx) {
err = errno;
ntfs_log_trace("Failed to obtain attribute search context.\n");
goto err_out;
}
if (!ntfs_attr_lookup(attr->type, (attr->name_length) ? (ntfschar*)
((u8*)attr + le16_to_cpu(attr->name_offset)) :
AT_UNNAMED, attr->name_length, CASE_SENSITIVE,
(attr->non_resident) ? sle64_to_cpu(attr->lowest_vcn) :
(attr->non_resident) ? le64_to_cpu(attr->lowest_vcn) :
0, (attr->non_resident) ? NULL : ((u8*)attr +
le16_to_cpu(attr->value_offset)), (attr->non_resident) ?
0 : le32_to_cpu(attr->value_length), ctx)) {
@ -193,7 +194,7 @@ int ntfs_attrlist_entry_add(ntfs_inode *ni, ATTR_RECORD *attr)
if (attr->non_resident)
ale->lowest_vcn = attr->lowest_vcn;
else
ale->lowest_vcn = const_cpu_to_sle64(0);
ale->lowest_vcn = 0;
ale->mft_reference = mref;
ale->instance = attr->instance;
memcpy(ale->name, (u8 *)attr + le16_to_cpu(attr->name_offset),
@ -265,7 +266,7 @@ int ntfs_attrlist_entry_rm(ntfs_attr_search_ctx *ctx)
ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x, lowest_vcn %lld.\n",
(long long) ctx->ntfs_ino->mft_no,
(unsigned) le32_to_cpu(ctx->al_entry->type),
(long long) sle64_to_cpu(ctx->al_entry->lowest_vcn));
(long long) le64_to_cpu(ctx->al_entry->lowest_vcn));
if (!NInoAttrList(base_ni)) {
ntfs_log_trace("Attribute list isn't present.\n");

View File

@ -3,7 +3,7 @@
*
* Copyright (c) 2002-2006 Anton Altaparmakov
* Copyright (c) 2004-2005 Richard Russon
* Copyright (c) 2004-2008 Szabolcs Szakacsits
* Copyright (c) 2004-2006 Szabolcs Szakacsits
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
@ -117,12 +117,10 @@ static int ntfs_bitmap_set_bits_in_run(ntfs_attr *na, s64 start_bit,
{
s64 bufsize, br;
u8 *buf, *lastbyte_buf;
int bit, firstbyte, lastbyte, lastbyte_pos, tmp, ret = -1;
int bit, firstbyte, lastbyte, lastbyte_pos, tmp, err;
if (!na || start_bit < 0 || count < 0) {
errno = EINVAL;
ntfs_log_perror("%s: Invalid argument (%p, %lld, %lld)",
__FUNCTION__, na, (long long)start_bit, (long long)count);
return -1;
}
@ -149,9 +147,9 @@ static int ntfs_bitmap_set_bits_in_run(ntfs_attr *na, s64 start_bit,
/* read it in... */
br = ntfs_attr_pread(na, start_bit >> 3, 1, buf);
if (br != 1) {
if (br >= 0)
errno = EIO;
goto free_err_out;
free(buf);
errno = EIO;
return -1;
}
/* and set or clear the appropriate bits in it. */
while ((bit & 7) && count--) {
@ -174,9 +172,9 @@ static int ntfs_bitmap_set_bits_in_run(ntfs_attr *na, s64 start_bit,
lastbyte_pos = ((count + 7) >> 3) + firstbyte;
if (!lastbyte_pos) {
// FIXME: Eeek! BUG!
ntfs_log_error("Lastbyte is zero. Leaving "
ntfs_log_trace("Eeek! lastbyte is zero. Leaving "
"inconsistent metadata.\n");
errno = EIO;
err = EIO;
goto free_err_out;
}
/* and it is in the currently loaded bitmap window... */
@ -188,11 +186,10 @@ static int ntfs_bitmap_set_bits_in_run(ntfs_attr *na, s64 start_bit,
3, 1, lastbyte_buf);
if (br != 1) {
// FIXME: Eeek! We need rollback! (AIA)
if (br >= 0)
errno = EIO;
ntfs_log_perror("Reading of last byte "
"failed (%lld). Leaving inconsistent "
"metadata", (long long)br);
ntfs_log_trace("Eeek! Read of last byte "
"failed. Leaving "
"inconsistent metadata.\n");
err = EIO;
goto free_err_out;
}
/* and set/clear the appropriate bits in it. */
@ -214,11 +211,9 @@ static int ntfs_bitmap_set_bits_in_run(ntfs_attr *na, s64 start_bit,
br = ntfs_attr_pwrite(na, tmp, bufsize, buf);
if (br != bufsize) {
// FIXME: Eeek! We need rollback! (AIA)
if (br >= 0)
errno = EIO;
ntfs_log_perror("Failed to write buffer to bitmap "
"(%lld != %lld). Leaving inconsistent metadata",
(long long)br, (long long)bufsize);
ntfs_log_trace("Eeek! Failed to write buffer to bitmap. "
"Leaving inconsistent metadata.\n");
err = EIO;
goto free_err_out;
}
@ -239,19 +234,22 @@ static int ntfs_bitmap_set_bits_in_run(ntfs_attr *na, s64 start_bit,
if (lastbyte && count != 0) {
// FIXME: Eeek! BUG!
ntfs_log_error("Last buffer but count is not zero "
"(%lld). Leaving inconsistent metadata.\n",
(long long)count);
errno = EIO;
ntfs_log_trace("Eeek! Last buffer but count is not zero (= "
"%lli). Leaving inconsistent metadata.\n",
(long long)count);
err = EIO;
goto free_err_out;
}
} while (count > 0);
ret = 0;
/* Done! */
free(buf);
return 0;
free_err_out:
free(buf);
return ret;
errno = err;
return -1;
}
/**
@ -267,13 +265,7 @@ free_err_out:
*/
int ntfs_bitmap_set_run(ntfs_attr *na, s64 start_bit, s64 count)
{
int ret;
ntfs_log_enter("Set from bit %lld, count %lld\n",
(long long)start_bit, (long long)count);
ret = ntfs_bitmap_set_bits_in_run(na, start_bit, count, 1);
ntfs_log_leave("\n");
return ret;
return ntfs_bitmap_set_bits_in_run(na, start_bit, count, 1);
}
/**
@ -289,12 +281,9 @@ int ntfs_bitmap_set_run(ntfs_attr *na, s64 start_bit, s64 count)
*/
int ntfs_bitmap_clear_run(ntfs_attr *na, s64 start_bit, s64 count)
{
int ret;
ntfs_log_enter("Clear from bit %lld, count %lld\n",
ntfs_log_trace("Dealloc from bit 0x%llx, count 0x%llx.\n",
(long long)start_bit, (long long)count);
ret = ntfs_bitmap_set_bits_in_run(na, start_bit, count, 0);
ntfs_log_leave("\n");
return ret;
return ntfs_bitmap_set_bits_in_run(na, start_bit, count, 0);
}

View File

@ -2,7 +2,7 @@
* bootsect.c - Boot sector handling code. Originated from the Linux-NTFS project.
*
* Copyright (c) 2000-2006 Anton Altaparmakov
* Copyright (c) 2003-2008 Szabolcs Szakacsits
* Copyright (c) 2003-2004 Szabolcs Szakacsits
* Copyright (c) 2005 Yura Pakhuchiy
*
* This program/include file is free software; you can redistribute it and/or
@ -38,7 +38,6 @@
#include <errno.h>
#endif
#include "param.h"
#include "compat.h"
#include "bootsect.h"
#include "debug.h"
@ -58,128 +57,109 @@
*
* Return TRUE if @b contains a valid ntfs boot sector and FALSE if not.
*/
BOOL ntfs_boot_sector_is_ntfs(NTFS_BOOT_SECTOR *b)
BOOL ntfs_boot_sector_is_ntfs(NTFS_BOOT_SECTOR *b, const BOOL silent __attribute__((unused)))
{
u32 i;
BOOL ret = FALSE;
u16 sectors_per_cluster;
ntfs_log_debug("Beginning bootsector check.\n");
ntfs_log_debug("\nBeginning bootsector check...\n");
ntfs_log_debug("Checking OEMid, NTFS signature.\n");
if (b->oem_id != const_cpu_to_le64(0x202020205346544eULL)) { /* "NTFS " */
ntfs_log_error("NTFS signature is missing.\n");
goto not_ntfs;
/* Calculate the checksum. Note, this is just a simple addition of
all u32 values in the bootsector starting at the beginning and
finishing at the offset of the checksum itself (i.e. not including
the checksum...). */
if ((void*)b < (void*)&b->checksum) {
u32 *u = (u32 *)b;
u32 *bi = (u32 *)(&b->checksum);
ntfs_log_debug("Calculating bootsector checksum... ");
for (i = 0; u < bi; ++u)
i += le32_to_cpup(u);
if (le32_to_cpu(b->checksum) && le32_to_cpu(b->checksum) != i)
goto not_ntfs;
ntfs_log_debug("OK\n");
}
ntfs_log_debug("Checking bytes per sector.\n");
if (le16_to_cpu(b->bpb.bytes_per_sector) < 256 ||
le16_to_cpu(b->bpb.bytes_per_sector) > 4096) {
ntfs_log_error("Unexpected bytes per sector value (%d).\n",
le16_to_cpu(b->bpb.bytes_per_sector));
/* Check OEMidentifier is "NTFS " */
ntfs_log_debug("Checking OEMid... ");
if (b->oem_id != cpu_to_le64(0x202020205346544eULL)) /* "NTFS " */
goto not_ntfs;
}
ntfs_log_debug("OK\n");
ntfs_log_debug("Checking sectors per cluster.\n");
/* Check bytes per sector value is between 256 and 4096. */
ntfs_log_debug("Checking bytes per sector... ");
if (le16_to_cpu(b->bpb.bytes_per_sector) < 0x100 ||
le16_to_cpu(b->bpb.bytes_per_sector) > 0x1000)
goto not_ntfs;
ntfs_log_debug("OK\n");
/* Check sectors per cluster value is valid. */
ntfs_log_debug("Checking sectors per cluster... ");
switch (b->bpb.sectors_per_cluster) {
case 1: case 2: case 4: case 8: case 16: case 32: case 64: case 128:
break;
default:
if ((b->bpb.sectors_per_cluster < 240)
|| (b->bpb.sectors_per_cluster > 253)) {
if (b->bpb.sectors_per_cluster > 128)
ntfs_log_error("Unexpected sectors"
" per cluster value (code 0x%x)\n",
b->bpb.sectors_per_cluster);
else
ntfs_log_error("Unexpected sectors"
" per cluster value (%d).\n",
b->bpb.sectors_per_cluster);
goto not_ntfs;
}
}
ntfs_log_debug("Checking cluster size.\n");
if (b->bpb.sectors_per_cluster > 128)
sectors_per_cluster = 1 << (256 - b->bpb.sectors_per_cluster);
else
sectors_per_cluster = b->bpb.sectors_per_cluster;
i = (u32)le16_to_cpu(b->bpb.bytes_per_sector) * sectors_per_cluster;
if (i > NTFS_MAX_CLUSTER_SIZE) {
ntfs_log_error("Unexpected cluster size (%d).\n", i);
goto not_ntfs;
}
ntfs_log_debug("OK\n");
ntfs_log_debug("Checking reserved fields are zero.\n");
/* Check the cluster size is not above 65536 bytes. */
ntfs_log_debug("Checking cluster size... ");
if ((u32)le16_to_cpu(b->bpb.bytes_per_sector) *
b->bpb.sectors_per_cluster > 0x10000)
goto not_ntfs;
ntfs_log_debug("OK\n");
/* Check reserved/unused fields are really zero. */
ntfs_log_debug("Checking reserved fields are zero... ");
if (le16_to_cpu(b->bpb.reserved_sectors) ||
le16_to_cpu(b->bpb.root_entries) ||
le16_to_cpu(b->bpb.sectors) ||
le16_to_cpu(b->bpb.sectors_per_fat) ||
le32_to_cpu(b->bpb.large_sectors) ||
b->bpb.fats) {
ntfs_log_error("Reserved fields aren't zero "
"(%d, %d, %d, %d, %d, %d).\n",
le16_to_cpu(b->bpb.reserved_sectors),
le16_to_cpu(b->bpb.root_entries),
le16_to_cpu(b->bpb.sectors),
le16_to_cpu(b->bpb.sectors_per_fat),
le32_to_cpu(b->bpb.large_sectors),
b->bpb.fats);
b->bpb.fats)
goto not_ntfs;
}
ntfs_log_debug("OK\n");
ntfs_log_debug("Checking clusters per mft record.\n");
/* Check clusters per file mft record value is valid. */
ntfs_log_debug("Checking clusters per mft record... ");
if ((u8)b->clusters_per_mft_record < 0xe1 ||
(u8)b->clusters_per_mft_record > 0xf7) {
switch (b->clusters_per_mft_record) {
case 1: case 2: case 4: case 8: case 0x10: case 0x20: case 0x40:
break;
default:
ntfs_log_error("Unexpected clusters per mft record "
"(%d).\n", b->clusters_per_mft_record);
goto not_ntfs;
}
}
ntfs_log_debug("OK\n");
ntfs_log_debug("Checking clusters per index block.\n");
/* Check clusters per index block value is valid. */
ntfs_log_debug("Checking clusters per index block... ");
if ((u8)b->clusters_per_index_record < 0xe1 ||
(u8)b->clusters_per_index_record > 0xf7) {
switch (b->clusters_per_index_record) {
case 1: case 2: case 4: case 8: case 0x10: case 0x20: case 0x40:
break;
default:
ntfs_log_error("Unexpected clusters per index record "
"(%d).\n", b->clusters_per_index_record);
goto not_ntfs;
}
}
ntfs_log_debug("OK\n");
/* MFT and MFTMirr may not overlap the boot sector or be the same */
if (((s64)sle64_to_cpu(b->mft_lcn) <= 0)
|| ((s64)sle64_to_cpu(b->mftmirr_lcn) <= 0)
|| (b->mft_lcn == b->mftmirr_lcn)) {
ntfs_log_error("Invalid location of MFT or MFTMirr.\n");
goto not_ntfs;
}
if (b->end_of_sector_marker != const_cpu_to_le16(0xaa55))
ntfs_log_debug("Warning: Bootsector has invalid end of sector "
"marker.\n");
if (b->end_of_sector_marker != cpu_to_le16(0xaa55))
ntfs_log_debug("Warning: Bootsector has invalid end of sector marker.\n");
ntfs_log_debug("Bootsector check completed successfully.\n");
ret = TRUE;
return TRUE;
not_ntfs:
return ret;
ntfs_log_debug("FAILED\n");
ntfs_log_debug("Bootsector check failed. Aborting...\n");
return FALSE;
}
static const char *last_sector_error =
"HINTS: Either the volume is a RAID/LDM but it wasn't setup yet,\n"
" or it was not setup correctly (e.g. by not using mdadm --build ...),\n"
" or a wrong device is tried to be mounted,\n"
" or the partition table is corrupt (partition is smaller than NTFS),\n"
" or the NTFS boot sector is corrupt (NTFS size is not valid).\n";
/**
* ntfs_boot_sector_parse - setup an ntfs volume from an ntfs boot sector
* @vol: ntfs_volume to setup
@ -192,9 +172,8 @@ static const char *last_sector_error =
*/
int ntfs_boot_sector_parse(ntfs_volume *vol, const NTFS_BOOT_SECTOR *bs)
{
s64 sectors;
u16 sectors_per_cluster;
s8 c;
u8 sectors_per_cluster;
s8 c;
/* We return -1 with errno = EINVAL on error. */
errno = EINVAL;
@ -208,51 +187,35 @@ int ntfs_boot_sector_parse(ntfs_volume *vol, const NTFS_BOOT_SECTOR *bs)
* below or equal the number_of_clusters) really belong in the
* ntfs_boot_sector_is_ntfs but in this way we can just do this once.
*/
if (bs->bpb.sectors_per_cluster > 128)
sectors_per_cluster = 1 << (256 - bs->bpb.sectors_per_cluster);
else
sectors_per_cluster = bs->bpb.sectors_per_cluster;
sectors_per_cluster = bs->bpb.sectors_per_cluster;
ntfs_log_debug("NumberOfSectors = %lli\n", sle64_to_cpu(bs->number_of_sectors));
ntfs_log_debug("SectorsPerCluster = 0x%x\n", sectors_per_cluster);
if (sectors_per_cluster & (sectors_per_cluster - 1)) {
ntfs_log_error("sectors_per_cluster (%d) is not a power of 2."
"\n", sectors_per_cluster);
ntfs_log_debug("Error: %s is not a valid NTFS partition! "
"sectors_per_cluster is not a power of 2.\n",
vol->dev->d_name);
return -1;
}
sectors = sle64_to_cpu(bs->number_of_sectors);
ntfs_log_debug("NumberOfSectors = %lld\n", (long long)sectors);
if (!sectors) {
ntfs_log_error("Volume size is set to zero.\n");
return -1;
}
if (vol->dev->d_ops->seek(vol->dev,
(sectors - 1) << vol->sector_size_bits,
SEEK_SET) == -1) {
ntfs_log_perror("Failed to read last sector (%lld)",
(long long)(sectors - 1));
ntfs_log_error("%s", last_sector_error);
return -1;
}
vol->nr_clusters = sectors >> (ffs(sectors_per_cluster) - 1);
vol->nr_clusters = sle64_to_cpu(bs->number_of_sectors) >>
(ffs(sectors_per_cluster) - 1);
vol->mft_lcn = sle64_to_cpu(bs->mft_lcn);
vol->mftmirr_lcn = sle64_to_cpu(bs->mftmirr_lcn);
ntfs_log_debug("MFT LCN = %lld\n", (long long)vol->mft_lcn);
ntfs_log_debug("MFTMirr LCN = %lld\n", (long long)vol->mftmirr_lcn);
if ((vol->mft_lcn < 0 || vol->mft_lcn > vol->nr_clusters) ||
(vol->mftmirr_lcn < 0 || vol->mftmirr_lcn > vol->nr_clusters)) {
ntfs_log_error("$MFT LCN (%lld) or $MFTMirr LCN (%lld) is "
"greater than the number of clusters (%lld).\n",
(long long)vol->mft_lcn, (long long)vol->mftmirr_lcn,
(long long)vol->nr_clusters);
ntfs_log_debug("MFT LCN = 0x%llx\n", vol->mft_lcn);
ntfs_log_debug("MFTMirr LCN = 0x%llx\n", vol->mftmirr_lcn);
if (vol->mft_lcn > vol->nr_clusters ||
vol->mftmirr_lcn > vol->nr_clusters) {
ntfs_log_debug("Error: %s is not a valid NTFS partition!\n",
vol->dev->d_name);
ntfs_log_debug("($Mft LCN or $MftMirr LCN is greater than the "
"number of clusters!)\n");
return -1;
}
vol->cluster_size = sectors_per_cluster * vol->sector_size;
if (vol->cluster_size & (vol->cluster_size - 1)) {
ntfs_log_error("cluster_size (%d) is not a power of 2.\n",
vol->cluster_size);
ntfs_log_debug("Error: %s is not a valid NTFS partition! "
"cluster_size is not a power of 2.\n",
vol->dev->d_name);
return -1;
}
vol->cluster_size_bits = ffs(vol->cluster_size) - 1;
@ -276,8 +239,9 @@ int ntfs_boot_sector_parse(ntfs_volume *vol, const NTFS_BOOT_SECTOR *bs)
else
vol->mft_record_size = c << vol->cluster_size_bits;
if (vol->mft_record_size & (vol->mft_record_size - 1)) {
ntfs_log_error("mft_record_size (%d) is not a power of 2.\n",
vol->mft_record_size);
ntfs_log_debug("Error: %s is not a valid NTFS partition! "
"mft_record_size is not a power of 2.\n",
vol->dev->d_name);
return -1;
}
vol->mft_record_size_bits = ffs(vol->mft_record_size) - 1;
@ -307,4 +271,3 @@ int ntfs_boot_sector_parse(ntfs_volume *vol, const NTFS_BOOT_SECTOR *bs)
vol->mftmirr_size = vol->cluster_size / vol->mft_record_size;
return 0;
}

View File

@ -1,606 +0,0 @@
/**
* cache.c : deal with LRU caches
*
* Copyright (c) 2008-2010 Jean-Pierre Andre
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program/include file 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 (in the main directory of the NTFS-3G
* distribution in the file COPYING); if not, write to the Free Software
* Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#include "types.h"
#include "security.h"
#include "cache.h"
#include "misc.h"
#include "logging.h"
/*
* General functions to deal with LRU caches
*
* The cached data have to be organized in a structure in which
* the first fields must follow a mandatory pattern and further
* fields may contain any fixed size data. They are stored in an
* LRU list.
*
* A compare function must be provided for finding a wanted entry
* in the cache. Another function may be provided for invalidating
* an entry to facilitate multiple invalidation.
*
* These functions never return error codes. When there is a
* shortage of memory, data is simply not cached.
* When there is a hashing bug, hashing is dropped, and sequential
* searches are used.
*/
/*
* Enter a new hash index, after a new record has been inserted
*
* Do not call when a record has been modified (with no key change)
*/
static void inserthashindex(struct CACHE_HEADER *cache,
struct CACHED_GENERIC *current)
{
int h;
struct HASH_ENTRY *link;
struct HASH_ENTRY *first;
if (cache->dohash) {
h = cache->dohash(current);
if ((h >= 0) && (h < cache->max_hash)) {
/* get a free link and insert at top of hash list */
link = cache->free_hash;
if (link) {
cache->free_hash = link->next;
first = cache->first_hash[h];
if (first)
link->next = first;
else
link->next = NULL;
link->entry = current;
cache->first_hash[h] = link;
} else {
ntfs_log_error("No more hash entries,"
" cache %s hashing dropped\n",
cache->name);
cache->dohash = (cache_hash)NULL;
}
} else {
ntfs_log_error("Illegal hash value,"
" cache %s hashing dropped\n",
cache->name);
cache->dohash = (cache_hash)NULL;
}
}
}
/*
* Drop a hash index when a record is about to be deleted
*/
static void drophashindex(struct CACHE_HEADER *cache,
const struct CACHED_GENERIC *current, int hash)
{
struct HASH_ENTRY *link;
struct HASH_ENTRY *previous;
if (cache->dohash) {
if ((hash >= 0) && (hash < cache->max_hash)) {
/* find the link and unlink */
link = cache->first_hash[hash];
previous = (struct HASH_ENTRY*)NULL;
while (link && (link->entry != current)) {
previous = link;
link = link->next;
}
if (link) {
if (previous)
previous->next = link->next;
else
cache->first_hash[hash] = link->next;
link->next = cache->free_hash;
cache->free_hash = link;
} else {
ntfs_log_error("Bad hash list,"
" cache %s hashing dropped\n",
cache->name);
cache->dohash = (cache_hash)NULL;
}
} else {
ntfs_log_error("Illegal hash value,"
" cache %s hashing dropped\n",
cache->name);
cache->dohash = (cache_hash)NULL;
}
}
}
/*
* Fetch an entry from cache
*
* returns the cache entry, or NULL if not available
* The returned entry may be modified, but not freed
*/
struct CACHED_GENERIC *ntfs_fetch_cache(struct CACHE_HEADER *cache,
const struct CACHED_GENERIC *wanted, cache_compare compare)
{
struct CACHED_GENERIC *current;
struct CACHED_GENERIC *previous;
struct HASH_ENTRY *link;
int h;
current = (struct CACHED_GENERIC*)NULL;
if (cache) {
if (cache->dohash) {
/*
* When possible, use the hash table to
* locate the entry if present
*/
h = cache->dohash(wanted);
link = cache->first_hash[h];
while (link && compare(link->entry, wanted))
link = link->next;
if (link)
current = link->entry;
}
if (!cache->dohash) {
/*
* Search sequentially in LRU list if no hash table
* or if hashing has just failed
*/
current = cache->most_recent_entry;
while (current
&& compare(current, wanted)) {
current = current->next;
}
}
if (current) {
previous = current->previous;
cache->hits++;
if (previous) {
/*
* found and not at head of list, unlink from current
* position and relink as head of list
*/
previous->next = current->next;
if (current->next)
current->next->previous
= current->previous;
else
cache->oldest_entry
= current->previous;
current->next = cache->most_recent_entry;
current->previous
= (struct CACHED_GENERIC*)NULL;
cache->most_recent_entry->previous = current;
cache->most_recent_entry = current;
}
}
cache->reads++;
}
return (current);
}
/*
* Enter an inode number into cache
* returns the cache entry or NULL if not possible
*/
struct CACHED_GENERIC *ntfs_enter_cache(struct CACHE_HEADER *cache,
const struct CACHED_GENERIC *item,
cache_compare compare)
{
struct CACHED_GENERIC *current;
struct CACHED_GENERIC *before;
struct HASH_ENTRY *link;
int h;
current = (struct CACHED_GENERIC*)NULL;
if (cache) {
if (cache->dohash) {
/*
* When possible, use the hash table to
* find out whether the entry if present
*/
h = cache->dohash(item);
link = cache->first_hash[h];
while (link && compare(link->entry, item))
link = link->next;
if (link) {
current = link->entry;
}
}
if (!cache->dohash) {
/*
* Search sequentially in LRU list to locate the end,
* and find out whether the entry is already in list
* As we normally go to the end, no statistics is
* kept.
*/
current = cache->most_recent_entry;
while (current
&& compare(current, item)) {
current = current->next;
}
}
if (!current) {
/*
* Not in list, get a free entry or reuse the
* last entry, and relink as head of list
* Note : we assume at least three entries, so
* before, previous and first are different when
* an entry is reused.
*/
if (cache->free_entry) {
current = cache->free_entry;
cache->free_entry = cache->free_entry->next;
if (item->varsize) {
current->variable = ntfs_malloc(
item->varsize);
} else
current->variable = (void*)NULL;
current->varsize = item->varsize;
if (!cache->oldest_entry)
cache->oldest_entry = current;
} else {
/* reusing the oldest entry */
current = cache->oldest_entry;
before = current->previous;
before->next = (struct CACHED_GENERIC*)NULL;
if (cache->dohash)
drophashindex(cache,current,
cache->dohash(current));
if (cache->dofree)
cache->dofree(current);
cache->oldest_entry = current->previous;
if (item->varsize) {
if (current->varsize)
current->variable = realloc(
current->variable,
item->varsize);
else
current->variable = ntfs_malloc(
item->varsize);
} else {
if (current->varsize)
free(current->variable);
current->variable = (void*)NULL;
}
current->varsize = item->varsize;
}
current->next = cache->most_recent_entry;
current->previous = (struct CACHED_GENERIC*)NULL;
if (cache->most_recent_entry)
cache->most_recent_entry->previous = current;
cache->most_recent_entry = current;
memcpy(current->payload, item->payload, cache->fixed_size);
if (item->varsize) {
if (current->variable) {
memcpy(current->variable,
item->variable, item->varsize);
} else {
/*
* no more memory for variable part
* recycle entry in free list
* not an error, just uncacheable
*/
cache->most_recent_entry = current->next;
current->next = cache->free_entry;
cache->free_entry = current;
current = (struct CACHED_GENERIC*)NULL;
}
} else {
current->variable = (void*)NULL;
current->varsize = 0;
}
if (cache->dohash && current)
inserthashindex(cache,current);
}
cache->writes++;
}
return (current);
}
/*
* Invalidate a cache entry
* The entry is moved to the free entry list
* A specific function may be called for entry deletion
*/
static void do_invalidate(struct CACHE_HEADER *cache,
struct CACHED_GENERIC *current, int flags)
{
struct CACHED_GENERIC *previous;
previous = current->previous;
if ((flags & CACHE_FREE) && cache->dofree)
cache->dofree(current);
/*
* Relink into free list
*/
if (current->next)
current->next->previous = current->previous;
else
cache->oldest_entry = current->previous;
if (previous)
previous->next = current->next;
else
cache->most_recent_entry = current->next;
current->next = cache->free_entry;
cache->free_entry = current;
if (current->variable)
free(current->variable);
current->varsize = 0;
}
/*
* Invalidate entries in cache
*
* Several entries may have to be invalidated (at least for inodes
* associated to directories which have been renamed), a different
* compare function may be provided to select entries to invalidate
*
* Returns the number of deleted entries, this can be used by
* the caller to signal a cache corruption if the entry was
* supposed to be found.
*/
int ntfs_invalidate_cache(struct CACHE_HEADER *cache,
const struct CACHED_GENERIC *item, cache_compare compare,
int flags)
{
struct CACHED_GENERIC *current;
struct CACHED_GENERIC *next;
struct HASH_ENTRY *link;
int count;
int h;
current = (struct CACHED_GENERIC*)NULL;
count = 0;
if (cache) {
if (!(flags & CACHE_NOHASH) && cache->dohash) {
/*
* When possible, use the hash table to
* find out whether the entry if present
*/
h = cache->dohash(item);
link = cache->first_hash[h];
while (link) {
if (compare(link->entry, item))
link = link->next;
else {
current = link->entry;
link = link->next;
if (current) {
drophashindex(cache,current,h);
do_invalidate(cache,
current,flags);
count++;
}
}
}
}
if ((flags & CACHE_NOHASH) || !cache->dohash) {
/*
* Search sequentially in LRU list
*/
current = cache->most_recent_entry;
while (current) {
if (!compare(current, item)) {
next = current->next;
if (cache->dohash)
drophashindex(cache,current,
cache->dohash(current));
do_invalidate(cache,current,flags);
current = next;
count++;
} else {
current = current->next;
}
}
}
}
return (count);
}
int ntfs_remove_cache(struct CACHE_HEADER *cache,
struct CACHED_GENERIC *item, int flags)
{
int count;
count = 0;
if (cache) {
if (cache->dohash)
drophashindex(cache,item,cache->dohash(item));
do_invalidate(cache,item,flags);
count++;
}
return (count);
}
/*
* Free memory allocated to a cache
*/
static void ntfs_free_cache(struct CACHE_HEADER *cache)
{
struct CACHED_GENERIC *entry;
if (cache) {
for (entry=cache->most_recent_entry; entry; entry=entry->next) {
if (cache->dofree)
cache->dofree(entry);
if (entry->variable)
free(entry->variable);
}
free(cache);
}
}
/*
* Create a cache
*
* Returns the cache header, or NULL if the cache could not be created
*/
static struct CACHE_HEADER *ntfs_create_cache(const char *name,
cache_free dofree, cache_hash dohash,
int full_item_size,
int item_count, int max_hash)
{
struct CACHE_HEADER *cache;
struct CACHED_GENERIC *pc;
struct CACHED_GENERIC *qc;
struct HASH_ENTRY *ph;
struct HASH_ENTRY *qh;
struct HASH_ENTRY **px;
size_t size;
int i;
size = sizeof(struct CACHE_HEADER) + item_count*full_item_size;
if (max_hash)
size += item_count*sizeof(struct HASH_ENTRY)
+ max_hash*sizeof(struct HASH_ENTRY*);
cache = (struct CACHE_HEADER*)ntfs_malloc(size);
if (cache) {
/* header */
cache->name = name;
cache->dofree = dofree;
if (dohash && max_hash) {
cache->dohash = dohash;
cache->max_hash = max_hash;
} else {
cache->dohash = (cache_hash)NULL;
cache->max_hash = 0;
}
cache->fixed_size = full_item_size - sizeof(struct CACHED_GENERIC);
cache->reads = 0;
cache->writes = 0;
cache->hits = 0;
/* chain the data entries, and mark an invalid entry */
cache->most_recent_entry = (struct CACHED_GENERIC*)NULL;
cache->oldest_entry = (struct CACHED_GENERIC*)NULL;
cache->free_entry = &cache->entry[0];
pc = &cache->entry[0];
for (i=0; i<(item_count - 1); i++) {
qc = (struct CACHED_GENERIC*)((char*)pc
+ full_item_size);
pc->next = qc;
pc->variable = (void*)NULL;
pc->varsize = 0;
pc = qc;
}
/* special for the last entry */
pc->next = (struct CACHED_GENERIC*)NULL;
pc->variable = (void*)NULL;
pc->varsize = 0;
if (max_hash) {
/* chain the hash entries */
ph = (struct HASH_ENTRY*)(((char*)pc) + full_item_size);
cache->free_hash = ph;
for (i=0; i<(item_count - 1); i++) {
qh = &ph[1];
ph->next = qh;
ph = qh;
}
/* special for the last entry */
if (item_count) {
ph->next = (struct HASH_ENTRY*)NULL;
}
/* create and initialize the hash indexes */
px = (struct HASH_ENTRY**)&ph[1];
cache->first_hash = px;
for (i=0; i<max_hash; i++)
px[i] = (struct HASH_ENTRY*)NULL;
} else {
cache->free_hash = (struct HASH_ENTRY*)NULL;
cache->first_hash = (struct HASH_ENTRY**)NULL;
}
}
return (cache);
}
/*
* Create all LRU caches
*
* No error return, if creation is not possible, cacheing will
* just be not available
*/
void ntfs_create_lru_caches(ntfs_volume *vol)
{
#if CACHE_INODE_SIZE
/* inode cache */
vol->xinode_cache = ntfs_create_cache("inode",(cache_free)NULL,
ntfs_dir_inode_hash, sizeof(struct CACHED_INODE),
CACHE_INODE_SIZE, 2*CACHE_INODE_SIZE);
#endif
#if CACHE_NIDATA_SIZE
/* idata cache */
vol->nidata_cache = ntfs_create_cache("nidata",
ntfs_inode_nidata_free, ntfs_inode_nidata_hash,
sizeof(struct CACHED_NIDATA),
CACHE_NIDATA_SIZE, 2*CACHE_NIDATA_SIZE);
#endif
#if CACHE_LOOKUP_SIZE
/* lookup cache */
vol->lookup_cache = ntfs_create_cache("lookup",
(cache_free)NULL, ntfs_dir_lookup_hash,
sizeof(struct CACHED_LOOKUP),
CACHE_LOOKUP_SIZE, 2*CACHE_LOOKUP_SIZE);
#endif
vol->securid_cache = ntfs_create_cache("securid",(cache_free)NULL,
(cache_hash)NULL,sizeof(struct CACHED_SECURID), CACHE_SECURID_SIZE, 0);
#if CACHE_LEGACY_SIZE
vol->legacy_cache = ntfs_create_cache("legacy",(cache_free)NULL,
(cache_hash)NULL, sizeof(struct CACHED_PERMISSIONS_LEGACY), CACHE_LEGACY_SIZE, 0);
#endif
}
/*
* Free all LRU caches
*/
void ntfs_free_lru_caches(ntfs_volume *vol)
{
#if CACHE_INODE_SIZE
ntfs_free_cache(vol->xinode_cache);
#endif
#if CACHE_NIDATA_SIZE
ntfs_free_cache(vol->nidata_cache);
#endif
#if CACHE_LOOKUP_SIZE
ntfs_free_cache(vol->lookup_cache);
#endif
ntfs_free_cache(vol->securid_cache);
#if CACHE_LEGACY_SIZE
ntfs_free_cache(vol->legacy_cache);
#endif
}

View File

@ -23,23 +23,36 @@
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#include "attrib.h"
#include "index.h"
#include "collate.h"
#include "debug.h"
#include "unistr.h"
#include "logging.h"
BOOL ntfs_is_collation_rule_supported(COLLATION_RULES cr)
{
int i;
/*
* FIXME: At the moment we only support COLLATION_BINARY,
* COLLATION_NTOFS_ULONG and COLLATION_FILE_NAME so we return false
* for everything else.
*/
if (cr != COLLATION_BINARY && cr != COLLATION_NTOFS_ULONG &&
cr != COLLATION_FILE_NAME)
return FALSE;
i = le32_to_cpu(cr);
if (((i >= 0) && (i <= 0x02)) ||
((i >= 0x10) && (i <= 0x13)))
return TRUE;
return FALSE;
}
/**
* ntfs_collate_binary - Which of two binary objects should be listed first
* @vol: unused
@ -108,101 +121,6 @@ static int ntfs_collate_ntofs_ulong(ntfs_volume *vol __attribute__((unused)),
return rc;
}
/**
* ntfs_collate_ntofs_ulongs - Which of two le32 arrays should be listed first
*
* Returns: -1, 0 or 1 depending of how the arrays compare
*/
static int ntfs_collate_ntofs_ulongs(ntfs_volume *vol __attribute__((unused)),
const void *data1, const int data1_len,
const void *data2, const int data2_len)
{
int rc;
int len;
const le32 *p1, *p2;
u32 d1, d2;
ntfs_log_trace("Entering.\n");
if ((data1_len != data2_len) || (data1_len <= 0) || (data1_len & 3)) {
ntfs_log_error("data1_len or data2_len not valid\n");
return NTFS_COLLATION_ERROR;
}
p1 = (const le32*)data1;
p2 = (const le32*)data2;
len = data1_len;
do {
d1 = le32_to_cpup(p1);
p1++;
d2 = le32_to_cpup(p2);
p2++;
} while ((d1 == d2) && ((len -= 4) > 0));
if (d1 < d2)
rc = -1;
else {
if (d1 == d2)
rc = 0;
else
rc = 1;
}
ntfs_log_trace("Done, returning %i.\n", rc);
return rc;
}
/**
* ntfs_collate_ntofs_security_hash - Which of two security descriptors
* should be listed first
* @vol: unused
* @data1:
* @data1_len:
* @data2:
* @data2_len:
*
* JPA compare two security hash keys made of two unsigned le32
*
* Returns: -1, 0 or 1 depending of how the keys compare
*/
static int ntfs_collate_ntofs_security_hash(ntfs_volume *vol __attribute__((unused)),
const void *data1, const int data1_len,
const void *data2, const int data2_len)
{
int rc;
u32 d1, d2;
const le32 *p1, *p2;
ntfs_log_trace("Entering.\n");
if (data1_len != data2_len || data1_len != 8) {
ntfs_log_error("data1_len or/and data2_len not equal to 8.\n");
return NTFS_COLLATION_ERROR;
}
p1 = (const le32*)data1;
p2 = (const le32*)data2;
d1 = le32_to_cpup(p1);
d2 = le32_to_cpup(p2);
if (d1 < d2)
rc = -1;
else {
if (d1 > d2)
rc = 1;
else {
p1++;
p2++;
d1 = le32_to_cpup(p1);
d2 = le32_to_cpup(p2);
if (d1 < d2)
rc = -1;
else {
if (d1 > d2)
rc = 1;
else
rc = 0;
}
}
}
ntfs_log_trace("Done, returning %i.\n", rc);
return rc;
}
/**
* ntfs_collate_file_name - Which of two filenames should be listed first
* @vol:
@ -219,53 +137,85 @@ static int ntfs_collate_file_name(ntfs_volume *vol,
const void *data1, const int data1_len __attribute__((unused)),
const void *data2, const int data2_len __attribute__((unused)))
{
const FILE_NAME_ATTR *file_name_attr1;
const FILE_NAME_ATTR *file_name_attr2;
int rc;
ntfs_log_trace("Entering.\n");
file_name_attr1 = (const FILE_NAME_ATTR*)data1;
file_name_attr2 = (const FILE_NAME_ATTR*)data2;
rc = ntfs_names_full_collate(
(ntfschar*)&file_name_attr1->file_name,
file_name_attr1->file_name_length,
(ntfschar*)&file_name_attr2->file_name,
file_name_attr2->file_name_length,
CASE_SENSITIVE, vol->upcase, vol->upcase_len);
rc = ntfs_file_values_compare(data1, data2, NTFS_COLLATION_ERROR,
IGNORE_CASE, vol->upcase, vol->upcase_len);
if (!rc)
rc = ntfs_file_values_compare(data1, data2,
NTFS_COLLATION_ERROR, CASE_SENSITIVE,
vol->upcase, vol->upcase_len);
ntfs_log_trace("Done, returning %i.\n", rc);
return rc;
}
/*
* Get a pointer to appropriate collation function.
typedef int (*ntfs_collate_func_t)(ntfs_volume *, const void *, const int,
const void *, const int);
static ntfs_collate_func_t ntfs_do_collate0x0[3] = {
ntfs_collate_binary,
ntfs_collate_file_name,
NULL/*ntfs_collate_unicode_string*/,
};
static ntfs_collate_func_t ntfs_do_collate0x1[4] = {
ntfs_collate_ntofs_ulong,
NULL/*ntfs_collate_ntofs_sid*/,
NULL/*ntfs_collate_ntofs_security_hash*/,
NULL/*ntfs_collate_ntofs_ulongs*/,
};
/**
* ntfs_collate - collate two data items using a specified collation rule
* @vol: ntfs volume to which the data items belong
* @cr: collation rule to use when comparing the items
* @data1: first data item to collate
* @data1_len: length in bytes of @data1
* @data2: second data item to collate
* @data2_len: length in bytes of @data2
*
* Returns NULL if the needed function is not implemented
* Collate the two data items @data1 and @data2 using the collation rule @cr
* and return -1, 0, or 1 if @data1 is found, respectively, to collate before,
* to match, or to collate after @data2.
*
* For speed we use the collation rule @cr as an index into two tables of
* function pointers to call the appropriate collation function.
*
* Return NTFS_COLLATION_ERROR if error occurred.
*/
COLLATE ntfs_get_collate_function(COLLATION_RULES cr)
int ntfs_collate(ntfs_volume *vol, COLLATION_RULES cr,
const void *data1, const int data1_len,
const void *data2, const int data2_len)
{
COLLATE collate;
int i;
switch (cr) {
case COLLATION_BINARY :
collate = ntfs_collate_binary;
break;
case COLLATION_FILE_NAME :
collate = ntfs_collate_file_name;
break;
case COLLATION_NTOFS_SECURITY_HASH :
collate = ntfs_collate_ntofs_security_hash;
break;
case COLLATION_NTOFS_ULONG :
collate = ntfs_collate_ntofs_ulong;
break;
case COLLATION_NTOFS_ULONGS :
collate = ntfs_collate_ntofs_ulongs;
break;
default :
errno = EOPNOTSUPP;
collate = (COLLATE)NULL;
break;
ntfs_log_trace("Entering.\n");
if (!vol || !data1 || !data2 || data1_len < 0 || data2_len < 0) {
ntfs_log_error("Invalid arguments passed.\n");
return NTFS_COLLATION_ERROR;
}
return (collate);
/*
* FIXME: At the moment we only support COLLATION_BINARY,
* COLLATION_NTOFS_ULONG and COLLATION_FILE_NAME so we return error
* for everything else.
*/
if (cr != COLLATION_BINARY && cr != COLLATION_NTOFS_ULONG &&
cr != COLLATION_FILE_NAME)
goto err;
i = le32_to_cpu(cr);
if (i < 0)
goto err;
if (i <= 0x02)
return ntfs_do_collate0x0[i](vol, data1, data1_len,
data2, data2_len);
if (i < 0x10)
goto err;
i -= 0x10;
if (i <= 3)
return ntfs_do_collate0x1[i](vol, data1, data1_len,
data2, data2_len);
err:
ntfs_log_debug("Unknown collation rule.\n");
return NTFS_COLLATION_ERROR;
}

View File

@ -20,12 +20,16 @@
* Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef WINDOWS
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "compat.h"
/* TODO: Add check for FFS in the configure script... (AIA) */
#ifndef HAVE_FFS
/**
* ffs - Find the first set bit in an int
@ -65,186 +69,5 @@ int ffs(int x)
}
#endif /* HAVE_FFS */
#ifndef HAVE_DAEMON
/* ************************************************************
* From: src.opensolaris.org
* src/lib/libresolv2/common/bsd/daemon.c
*/
/*
* Copyright (c) 1997-2000 by Sun Microsystems, Inc.
* All rights reserved.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static const char sccsid[] = "@(#)daemon.c 8.1 (Berkeley) 6/4/93";
static const char rcsid[] = "$Id: compat.c,v 1.1.1.1.2.1 2008-08-16 15:17:44 jpandre Exp $";
#endif /* LIBC_SCCS and not lint */
/*
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
int daemon(int nochdir, int noclose) {
int fd;
switch (fork()) {
case -1:
return (-1);
case 0:
break;
default:
_exit(0);
}
if (setsid() == -1)
return (-1);
if (!nochdir)
(void)chdir("/");
if (!noclose && (fd = open("/dev/null", O_RDWR, 0)) != -1) {
(void)dup2(fd, 0);
(void)dup2(fd, 1);
(void)dup2(fd, 2);
if (fd > 2)
(void)close (fd);
}
return (0);
}
/*
* End: src/lib/libresolv2/common/bsd/daemon.c
*************************************************************/
#endif /* HAVE_DAEMON */
#ifndef HAVE_STRSEP
/* ************************************************************
* From: src.opensolaris.org
* src/lib/libresolv2/common/bsd/strsep.c
*/
/*
* Copyright (c) 1997, by Sun Microsystems, Inc.
* All rights reserved.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static const char sccsid[] = "strsep.c 8.1 (Berkeley) 6/4/93";
static const char rcsid[] = "$Id: compat.c,v 1.1.1.1.2.1 2008-08-16 15:17:44 jpandre Exp $";
#endif /* LIBC_SCCS and not lint */
/*
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef HAVE_STDIO_H
#include <stdio.h>
#endif
/*
* Get next token from string *stringp, where tokens are possibly-empty
* strings separated by characters from delim.
*
* Writes NULs into the string at *stringp to end tokens.
* delim need not remain constant from call to call.
* On return, *stringp points past the last NUL written (if there might
* be further tokens), or is NULL (if there are definitely no more tokens).
*
* If *stringp is NULL, strsep returns NULL.
*/
char *strsep(char **stringp, const char *delim) {
char *s;
const char *spanp;
int c, sc;
char *tok;
if ((s = *stringp) == NULL)
return (NULL);
for (tok = s;;) {
c = *s++;
spanp = delim;
do {
if ((sc = *spanp++) == c) {
if (c == 0)
s = NULL;
else
s[-1] = 0;
*stringp = s;
return (tok);
}
} while (sc != 0);
}
/* NOTREACHED */
}
/*
* End: src/lib/libresolv2/common/bsd/strsep.c
*************************************************************/
#endif /* HAVE_STRSEP */
#endif /* WINDOWS */

File diff suppressed because it is too large Load Diff

View File

@ -63,15 +63,9 @@ void ntfs_debug_runlist_dump(const runlist_element *rl)
if (idx > -LCN_EINVAL - 1)
idx = 4;
ntfs_log_debug("%-16lld %s %-16lld%s\n",
(long long)rl[i].vcn, lcn_str[idx],
(long long)rl[i].length,
rl[i].length ? "" : " (runlist end)");
ntfs_log_debug("%-16llx %s %-16llx%s\n", rl[i].vcn, lcn_str[idx], rl[i].length, rl[i].length ? "" : " (runlist end)");
} else
ntfs_log_debug("%-16lld %-16lld %-16lld%s\n",
(long long)rl[i].vcn, (long long)rl[i].lcn,
(long long)rl[i].length,
rl[i].length ? "" : " (runlist end)");
ntfs_log_debug("%-16llx %-16llx %-16llx%s\n", rl[i].vcn, rl[i].lcn, rl[i].length, rl[i].length ? "" : " (runlist end)");
} while (rl[i++].length);
}

View File

@ -1,10 +1,8 @@
/**
* device.c - Low level device io functions. Originated from the Linux-NTFS project.
*
* Copyright (c) 2004-2013 Anton Altaparmakov
* Copyright (c) 2004-2006 Anton Altaparmakov
* Copyright (c) 2004-2006 Szabolcs Szakacsits
* Copyright (c) 2010 Jean-Pierre Andre
* Copyright (c) 2008-2013 Tuxera Inc.
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
@ -59,18 +57,12 @@
#ifdef HAVE_SYS_MOUNT_H
#include <sys/mount.h>
#endif
#ifdef HAVE_SYS_DISK_H
#include <sys/disk.h>
#endif
#ifdef HAVE_LINUX_FD_H
#include <linux/fd.h>
#endif
#ifdef HAVE_LINUX_HDREG_H
#include <linux/hdreg.h>
#endif
#ifdef ENABLE_HD
#include <hd.h>
#endif
#include "types.h"
#include "mst.h"
@ -132,8 +124,6 @@ struct ntfs_device *ntfs_device_alloc(const char *name, const long state,
dev->d_ops = dops;
dev->d_state = state;
dev->d_private = priv_data;
dev->d_heads = -1;
dev->d_sectors_per_track = -1;
}
return dev;
}
@ -164,25 +154,6 @@ int ntfs_device_free(struct ntfs_device *dev)
return 0;
}
/*
* Sync the device
*
* returns zero if successful.
*/
int ntfs_device_sync(struct ntfs_device *dev)
{
int ret;
struct ntfs_device_operations *dops;
if (NDevDirty(dev)) {
dops = dev->d_ops;
ret = dops->sync(dev);
} else
ret = 0;
return ret;
}
/**
* ntfs_pread - positioned read from disk
* @dev: device to read from
@ -207,19 +178,23 @@ s64 ntfs_pread(struct ntfs_device *dev, const s64 pos, s64 count, void *b)
s64 br, total;
struct ntfs_device_operations *dops;
ntfs_log_trace("pos %lld, count %lld\n",(long long)pos,(long long)count);
ntfs_log_trace("Entering for pos 0x%llx, count 0x%llx.\n", pos, count);
if (!b || count < 0 || pos < 0) {
errno = EINVAL;
return -1;
}
if (!count)
return 0;
dops = dev->d_ops;
/* Locate to position. */
if (dops->seek(dev, pos, SEEK_SET) == (off_t)-1) {
ntfs_log_perror("ntfs_pread: device seek to 0x%llx returned error",
pos);
return -1;
}
/* Read the data. */
for (total = 0; count; count -= br, total += br) {
br = dops->pread(dev, (char*)b + total, count, pos + total);
br = dops->read(dev, (char*)b + total, count);
/* If everything ok, continue. */
if (br > 0)
continue;
@ -258,8 +233,7 @@ s64 ntfs_pwrite(struct ntfs_device *dev, const s64 pos, s64 count,
s64 written, total, ret = -1;
struct ntfs_device_operations *dops;
ntfs_log_trace("pos %lld, count %lld\n",(long long)pos,(long long)count);
ntfs_log_trace("Entering for pos 0x%llx, count 0x%llx.\n", pos, count);
if (!b || count < 0 || pos < 0) {
errno = EINVAL;
goto out;
@ -270,13 +244,16 @@ s64 ntfs_pwrite(struct ntfs_device *dev, const s64 pos, s64 count,
errno = EROFS;
goto out;
}
dops = dev->d_ops;
/* Locate to position. */
if (dops->seek(dev, pos, SEEK_SET) == (off_t)-1) {
ntfs_log_perror("ntfs_pwrite: seek to 0x%llx returned error",
pos);
goto out;
}
NDevSetDirty(dev);
for (total = 0; count; count -= written, total += written) {
written = dops->pwrite(dev, (const char*)b + total, count,
pos + total);
written = dops->write(dev, (const char*)b + total, count);
/* If everything ok, continue. */
if (written > 0)
continue;
@ -289,9 +266,6 @@ s64 ntfs_pwrite(struct ntfs_device *dev, const s64 pos, s64 count,
total = written;
break;
}
if (NDevSync(dev) && total && dops->sync(dev)) {
total--; /* on sync error, return partially written */
}
ret = total;
out:
return ret;
@ -442,8 +416,7 @@ s64 ntfs_cluster_read(const ntfs_volume *vol, const s64 lcn, const s64 count,
if (vol->nr_clusters < lcn + count) {
errno = ESPIPE;
ntfs_log_perror("Trying to read outside of volume "
"(%lld < %lld)", (long long)vol->nr_clusters,
(long long)lcn + count);
"(%lld < %lld)", vol->nr_clusters, lcn + count);
return -1;
}
br = ntfs_pread(vol->dev, lcn << vol->cluster_size_bits,
@ -478,8 +451,7 @@ s64 ntfs_cluster_write(const ntfs_volume *vol, const s64 lcn,
if (vol->nr_clusters < lcn + count) {
errno = ESPIPE;
ntfs_log_perror("Trying to write outside of volume "
"(%lld < %lld)", (long long)vol->nr_clusters,
(long long)lcn + count);
"(%lld < %lld)", vol->nr_clusters, lcn + count);
return -1;
}
if (!NVolReadOnly(vol))
@ -565,36 +537,6 @@ s64 ntfs_device_size_get(struct ntfs_device *dev, int block_size)
return (s64)this_floppy.size * 512 / block_size;
}
}
#endif
#ifdef DIOCGMEDIASIZE
{
/* FreeBSD */
off_t size;
if (dev->d_ops->ioctl(dev, DIOCGMEDIASIZE, &size) >= 0) {
ntfs_log_debug("DIOCGMEDIASIZE nr bytes = %llu (0x%llx)\n",
(unsigned long long)size,
(unsigned long long)size);
return (s64)size / block_size;
}
}
#endif
#ifdef DKIOCGETBLOCKCOUNT
{
/* Mac OS X */
uint64_t blocks;
int sector_size;
sector_size = ntfs_device_sector_size_get(dev);
if (sector_size >= 0 && dev->d_ops->ioctl(dev,
DKIOCGETBLOCKCOUNT, &blocks) >= 0)
{
ntfs_log_debug("DKIOCGETBLOCKCOUNT nr blocks = %llu (0x%llx)\n",
(unsigned long long) blocks,
(unsigned long long) blocks);
return blocks * sector_size / block_size;
}
}
#endif
/*
* We couldn't figure it out by using a specialized ioctl,
@ -648,132 +590,6 @@ s64 ntfs_device_partition_start_sector_get(struct ntfs_device *dev)
return -1;
}
static int ntfs_device_get_geo(struct ntfs_device *dev)
{
int err;
if (!dev) {
errno = EINVAL;
return -1;
}
err = EOPNOTSUPP;
#ifdef ENABLE_HD
{
hd_data_t *hddata;
hd_t *hd, *devlist, *partlist = NULL;
str_list_t *names;
hd_res_t *res;
const int d_name_len = strlen(dev->d_name) + 1;
int done = 0;
hddata = calloc(1, sizeof(*hddata));
if (!hddata) {
err = ENOMEM;
goto skip_hd;
}
/* List all "disk" class devices on the system. */
devlist = hd_list(hddata, hw_disk, 1, NULL);
if (!devlist) {
free(hddata);
err = ENOMEM;
goto skip_hd;
}
/*
* Loop over each disk device looking for the device with the
* same unix name as @dev.
*/
for (hd = devlist; hd; hd = hd->next) {
if (hd->unix_dev_name && !strncmp(dev->d_name,
hd->unix_dev_name, d_name_len))
goto got_hd;
if (hd->unix_dev_name2 && !strncmp(dev->d_name,
hd->unix_dev_name2, d_name_len))
goto got_hd;
for (names = hd->unix_dev_names; names;
names = names->next) {
if (names->str && !strncmp(dev->d_name,
names->str, d_name_len))
goto got_hd;
}
}
/*
* Device was not a whole disk device. Unless it is a file it
* is likely to be a partition device. List all "partition"
* class devices on the system.
*/
partlist = hd_list(hddata, hw_partition, 1, NULL);
for (hd = partlist; hd; hd = hd->next) {
if (hd->unix_dev_name && !strncmp(dev->d_name,
hd->unix_dev_name, d_name_len))
goto got_part_hd;
if (hd->unix_dev_name2 && !strncmp(dev->d_name,
hd->unix_dev_name2, d_name_len))
goto got_part_hd;
for (names = hd->unix_dev_names; names;
names = names->next) {
if (names->str && !strncmp(dev->d_name,
names->str, d_name_len))
goto got_part_hd;
}
}
/* Failed to find the device. Stop trying and clean up. */
goto end_hd;
got_part_hd:
/* Get the whole block device the partition device is on. */
hd = hd_get_device_by_idx(hddata, hd->attached_to);
if (!hd)
goto end_hd;
got_hd:
/*
* @hd is now the whole block device either being formatted or
* that the partition being formatted is on.
*
* Loop over each resource of the disk device looking for the
* BIOS legacy geometry obtained from EDD which is what Windows
* needs to boot.
*/
for (res = hd->res; res; res = res->next) {
/* geotype 3 is BIOS legacy. */
if (res->any.type != res_disk_geo ||
res->disk_geo.geotype != 3)
continue;
dev->d_heads = res->disk_geo.heads;
dev->d_sectors_per_track = res->disk_geo.sectors;
done = 1;
}
end_hd:
if (partlist)
hd_free_hd_list(partlist);
hd_free_hd_list(devlist);
hd_free_hd_data(hddata);
free(hddata);
if (done) {
ntfs_log_debug("EDD/BIOD legacy heads = %u, sectors "
"per track = %u\n", dev->d_heads,
dev->d_sectors_per_track);
return 0;
}
}
skip_hd:
#endif
#ifdef HDIO_GETGEO
{ struct hd_geometry geo;
if (!dev->d_ops->ioctl(dev, HDIO_GETGEO, &geo)) {
dev->d_heads = geo.heads;
dev->d_sectors_per_track = geo.sectors;
ntfs_log_debug("HDIO_GETGEO heads = %u, sectors per "
"track = %u\n", dev->d_heads,
dev->d_sectors_per_track);
return 0;
}
err = errno;
}
#endif
errno = err;
return -1;
}
/**
* ntfs_device_heads_get - get number of heads of device
* @dev: open device
@ -785,7 +601,6 @@ skip_hd:
* EINVAL Input parameter error
* EOPNOTSUPP System does not support HDIO_GETGEO ioctl
* ENOTTY @dev is a file or a device not supporting HDIO_GETGEO
* ENOMEM Not enough memory to complete the request
*/
int ntfs_device_heads_get(struct ntfs_device *dev)
{
@ -793,15 +608,20 @@ int ntfs_device_heads_get(struct ntfs_device *dev)
errno = EINVAL;
return -1;
}
if (dev->d_heads == -1) {
if (ntfs_device_get_geo(dev) == -1)
return -1;
if (dev->d_heads == -1) {
errno = EINVAL;
return -1;
#ifdef HDIO_GETGEO
{ struct hd_geometry geo;
if (!dev->d_ops->ioctl(dev, HDIO_GETGEO, &geo)) {
ntfs_log_debug("HDIO_GETGEO heads = %u (0x%x)\n",
(unsigned)geo.heads,
(unsigned)geo.heads);
return geo.heads;
}
}
return dev->d_heads;
#else
errno = EOPNOTSUPP;
#endif
return -1;
}
/**
@ -815,7 +635,6 @@ int ntfs_device_heads_get(struct ntfs_device *dev)
* EINVAL Input parameter error
* EOPNOTSUPP System does not support HDIO_GETGEO ioctl
* ENOTTY @dev is a file or a device not supporting HDIO_GETGEO
* ENOMEM Not enough memory to complete the request
*/
int ntfs_device_sectors_per_track_get(struct ntfs_device *dev)
{
@ -823,15 +642,20 @@ int ntfs_device_sectors_per_track_get(struct ntfs_device *dev)
errno = EINVAL;
return -1;
}
if (dev->d_sectors_per_track == -1) {
if (ntfs_device_get_geo(dev) == -1)
return -1;
if (dev->d_sectors_per_track == -1) {
errno = EINVAL;
return -1;
#ifdef HDIO_GETGEO
{ struct hd_geometry geo;
if (!dev->d_ops->ioctl(dev, HDIO_GETGEO, &geo)) {
ntfs_log_debug("HDIO_GETGEO sectors_per_track = %u (0x%x)\n",
(unsigned)geo.sectors,
(unsigned)geo.sectors);
return geo.sectors;
}
}
return dev->d_sectors_per_track;
#else
errno = EOPNOTSUPP;
#endif
return -1;
}
/**
@ -862,28 +686,6 @@ int ntfs_device_sector_size_get(struct ntfs_device *dev)
return sect_size;
}
}
#elif defined(DIOCGSECTORSIZE)
{
/* FreeBSD */
size_t sect_size = 0;
if (!dev->d_ops->ioctl(dev, DIOCGSECTORSIZE, &sect_size)) {
ntfs_log_debug("DIOCGSECTORSIZE sector size = %d bytes\n",
(int) sect_size);
return sect_size;
}
}
#elif defined(DKIOCGETBLOCKSIZE)
{
/* Mac OS X */
uint32_t sect_size = 0;
if (!dev->d_ops->ioctl(dev, DKIOCGETBLOCKSIZE, &sect_size)) {
ntfs_log_debug("DKIOCGETBLOCKSIZE sector size = %d bytes\n",
(int) sect_size);
return sect_size;
}
}
#else
errno = EOPNOTSUPP;
#endif

View File

@ -0,0 +1,38 @@
/*
* device_io.c - Default device io operations. Originated from the Linux-NTFS project.
*
* Copyright (c) 2003 Anton Altaparmakov
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program/include file 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 (in the main directory of the NTFS-3G
* distribution in the file COPYING); if not, write to the Free Software
* Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#ifndef NO_NTFS_DEVICE_DEFAULT_IO_OPS
#ifndef __CYGWIN32__
/* Not on Cygwin; use standard Unix style low level device operations. */
#include "unix_io.c"
#else /* __CYGWIN32__ */
/* On Cygwin; use Win32 low level device operations. */
#include "win32_io.c"
#endif /* __CYGWIN32__ */
#endif /* NO_NTFS_DEVICE_DEFAULT_IO_OPS */

File diff suppressed because it is too large Load Diff

View File

@ -1,519 +0,0 @@
/**
* ea.c - Processing of EA's
*
* This module is part of ntfs-3g library
*
* Copyright (c) 2014-2021 Jean-Pierre Andre
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program/include file 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 (in the main directory of the NTFS-3G
* distribution in the file COPYING); if not, write to the Free Software
* Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef HAVE_STDIO_H
#include <stdio.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#ifdef MAJOR_IN_MKDEV
#include <sys/mkdev.h>
#endif
#ifdef MAJOR_IN_SYSMACROS
#include <sys/sysmacros.h>
#endif
#include "types.h"
#include "param.h"
#include "layout.h"
#include "attrib.h"
#include "index.h"
#include "dir.h"
#include "ea.h"
#include "misc.h"
#include "logging.h"
#include "xattrs.h"
static const char lxdev[] = "$LXDEV";
static const char lxmod[] = "$LXMOD";
/*
* Create a needed attribute (EA or EA_INFORMATION)
*
* Returns 0 if successful,
* -1 otherwise, with errno indicating why it failed.
*/
static int ntfs_need_ea(ntfs_inode *ni, ATTR_TYPES type, int size, int flags)
{
u8 dummy;
int res;
res = 0;
if (!ntfs_attr_exist(ni,type, AT_UNNAMED,0)) {
if (!(flags & XATTR_REPLACE)) {
/*
* no needed attribute : add one,
* apparently, this does not feed the new value in
* Note : NTFS version must be >= 3
*/
if (ni->vol->major_ver >= 3) {
res = ntfs_attr_add(ni, type,
AT_UNNAMED,0,&dummy,(s64)size);
if (!res) {
NInoFileNameSetDirty(ni);
}
NInoSetDirty(ni);
} else {
errno = EOPNOTSUPP;
res = -1;
}
} else {
errno = ENODATA;
res = -1;
}
}
return (res);
}
/*
* Restore the old EA_INFORMATION or delete the current one,
* when EA cannot be updated.
*
* As this is used in the context of some other error, the caller
* is responsible for returning the proper error, and errno is
* left unchanged.
* Only double errors are logged here.
*/
static void restore_ea_info(ntfs_attr *nai, const EA_INFORMATION *old_ea_info)
{
s64 written;
int olderrno;
olderrno = errno;
if (old_ea_info) {
written = ntfs_attr_pwrite(nai, 0, sizeof(EA_INFORMATION),
old_ea_info);
if ((size_t)written != sizeof(EA_INFORMATION)) {
ntfs_log_error("Could not restore the EA_INFORMATION,"
" possible inconsistency in inode %lld\n",
(long long)nai->ni->mft_no);
}
} else {
if (ntfs_attr_rm(nai)) {
ntfs_log_error("Could not delete the EA_INFORMATION,"
" possible inconsistency in inode %lld\n",
(long long)nai->ni->mft_no);
}
}
errno = olderrno;
}
/*
* Update both EA and EA_INFORMATION
*/
static int ntfs_update_ea(ntfs_inode *ni, const char *value, size_t size,
const EA_INFORMATION *ea_info,
const EA_INFORMATION *old_ea_info)
{
ntfs_attr *na;
ntfs_attr *nai;
int res;
res = 0;
nai = ntfs_attr_open(ni, AT_EA_INFORMATION, AT_UNNAMED, 0);
if (nai) {
na = ntfs_attr_open(ni, AT_EA, AT_UNNAMED, 0);
if (na) {
/*
* Set EA_INFORMATION first, it is easier to
* restore the old value, if setting EA fails.
*/
if (ntfs_attr_pwrite(nai, 0, sizeof(EA_INFORMATION),
ea_info)
!= (s64)sizeof(EA_INFORMATION)) {
res = -errno;
} else {
if (((na->data_size > (s64)size)
&& ntfs_attr_truncate(na, size))
|| (ntfs_attr_pwrite(na, 0, size, value)
!= (s64)size)) {
res = -errno;
if (old_ea_info)
restore_ea_info(nai,
old_ea_info);
}
}
ntfs_attr_close(na);
}
ntfs_attr_close(nai);
} else {
res = -errno;
}
return (res);
}
/*
* Return the existing EA
*
* The EA_INFORMATION is not examined and the consistency of the
* existing EA is not checked.
*
* If successful, the full attribute is returned unchanged
* and its size is returned.
* If the designated buffer is too small, the needed size is
* returned, and the buffer is left unchanged.
* If there is an error, a negative value is returned and errno
* is set according to the error.
*/
int ntfs_get_ntfs_ea(ntfs_inode *ni, char *value, size_t size)
{
s64 ea_size;
void *ea_buf;
int res = 0;
if (ntfs_attr_exist(ni, AT_EA, AT_UNNAMED, 0)) {
ea_buf = ntfs_attr_readall(ni, AT_EA, (ntfschar*)NULL, 0,
&ea_size);
if (ea_buf) {
if (value && (ea_size <= (s64)size))
memcpy(value, ea_buf, ea_size);
free(ea_buf);
res = ea_size;
} else {
ntfs_log_error("Failed to read EA from inode %lld\n",
(long long)ni->mft_no);
errno = ENODATA;
res = -errno;
}
} else {
errno = ENODATA;
res = -errno;
}
return (res);
}
/*
* Set a new EA, and set EA_INFORMATION accordingly
*
* This is roughly the same as ZwSetEaFile() on Windows, however
* the "offset to next" of the last EA should not be cleared.
*
* Consistency of the new EA is first checked.
*
* EA_INFORMATION is set first, and it is restored to its former
* state if setting EA fails.
*
* Returns 0 if successful
* a negative value if an error occurred.
*/
int ntfs_set_ntfs_ea(ntfs_inode *ni, const char *value, size_t size, int flags)
{
EA_INFORMATION ea_info;
EA_INFORMATION *old_ea_info;
s64 old_ea_size;
int res;
size_t offs;
size_t nextoffs;
BOOL ok;
int ea_count;
int ea_packed;
const EA_ATTR *p_ea;
res = -1;
if (value && (size > 0)) {
/* do consistency checks */
offs = 0;
ok = TRUE;
ea_count = 0;
ea_packed = 0;
nextoffs = 0;
while (ok && (offs < size)) {
p_ea = (const EA_ATTR*)&value[offs];
nextoffs = offs + le32_to_cpu(p_ea->next_entry_offset);
/* null offset to next not allowed */
ok = (nextoffs > offs)
&& (nextoffs <= size)
&& !(nextoffs & 3)
&& p_ea->name_length
/* zero sized value are allowed */
&& ((offs + offsetof(EA_ATTR,name)
+ p_ea->name_length + 1
+ le16_to_cpu(p_ea->value_length))
<= nextoffs)
&& ((offs + offsetof(EA_ATTR,name)
+ p_ea->name_length + 1
+ le16_to_cpu(p_ea->value_length))
>= (nextoffs - 3))
&& !p_ea->name[p_ea->name_length];
/* name not checked, as chkdsk accepts any chars */
if (ok) {
if (p_ea->flags & NEED_EA)
ea_count++;
/*
* Assume ea_packed includes :
* 4 bytes for header (flags and lengths)
* + name length + 1
* + value length
*/
ea_packed += 5 + p_ea->name_length
+ le16_to_cpu(p_ea->value_length);
offs = nextoffs;
}
}
/*
* EA and REPARSE_POINT compatibility not checked any more,
* required by Windows 10, but having both may lead to
* problems with earlier versions.
*/
if (ok) {
ea_info.ea_length = cpu_to_le16(ea_packed);
ea_info.need_ea_count = cpu_to_le16(ea_count);
ea_info.ea_query_length = cpu_to_le32(nextoffs);
old_ea_size = 0;
old_ea_info = NULL;
/* Try to save the old EA_INFORMATION */
if (ntfs_attr_exist(ni, AT_EA_INFORMATION,
AT_UNNAMED, 0)) {
old_ea_info = ntfs_attr_readall(ni,
AT_EA_INFORMATION,
(ntfschar*)NULL, 0, &old_ea_size);
}
/*
* no EA or EA_INFORMATION : add them
*/
if (!ntfs_need_ea(ni, AT_EA_INFORMATION,
sizeof(EA_INFORMATION), flags)
&& !ntfs_need_ea(ni, AT_EA, 0, flags)) {
res = ntfs_update_ea(ni, value, size,
&ea_info, old_ea_info);
} else {
res = -errno;
}
if (old_ea_info)
free(old_ea_info);
} else {
errno = EINVAL;
res = -errno;
}
} else {
errno = EINVAL;
res = -errno;
}
return (res);
}
/*
* Remove the EA (including EA_INFORMATION)
*
* EA_INFORMATION is removed first, and it is restored to its former
* state if removing EA fails.
*
* Returns 0, or -1 if there is a problem
*/
int ntfs_remove_ntfs_ea(ntfs_inode *ni)
{
EA_INFORMATION *old_ea_info;
s64 old_ea_size;
int res;
ntfs_attr *na;
ntfs_attr *nai;
res = 0;
if (ni) {
/*
* open and delete the EA_INFORMATION and the EA
*/
nai = ntfs_attr_open(ni, AT_EA_INFORMATION, AT_UNNAMED, 0);
if (nai) {
na = ntfs_attr_open(ni, AT_EA, AT_UNNAMED, 0);
if (na) {
/* Try to save the old EA_INFORMATION */
old_ea_info = ntfs_attr_readall(ni,
AT_EA_INFORMATION,
(ntfschar*)NULL, 0, &old_ea_size);
res = ntfs_attr_rm(na);
NInoFileNameSetDirty(ni);
if (!res) {
res = ntfs_attr_rm(nai);
if (res && old_ea_info) {
/*
* Failed to remove the EA, try to
* restore the EA_INFORMATION
*/
restore_ea_info(nai,
old_ea_info);
}
} else {
ntfs_log_error("Failed to remove the"
" EA_INFORMATION from inode %lld\n",
(long long)ni->mft_no);
}
free(old_ea_info);
ntfs_attr_close(na);
} else {
/* EA_INFORMATION present, but no EA */
res = ntfs_attr_rm(nai);
NInoFileNameSetDirty(ni);
}
ntfs_attr_close(nai);
} else {
errno = ENODATA;
res = -1;
}
NInoSetDirty(ni);
} else {
errno = EINVAL;
res = -1;
}
return (res ? -1 : 0);
}
/*
* Check for the presence of an EA "$LXDEV" (used by WSL)
* and return its value as a device address
*
* Returns zero if successful
* -1 if failed, with errno set
*/
int ntfs_ea_check_wsldev(ntfs_inode *ni, dev_t *rdevp)
{
const EA_ATTR *p_ea;
int bufsize;
char *buf;
int lth;
int res;
int offset;
int next;
BOOL found;
struct {
le32 major;
le32 minor;
} device;
res = -EOPNOTSUPP;
bufsize = 256; /* expected to be enough */
buf = (char*)malloc(bufsize);
if (buf) {
lth = ntfs_get_ntfs_ea(ni, buf, bufsize);
/* retry if short buf */
if (lth > bufsize) {
free(buf);
bufsize = lth;
buf = (char*)malloc(bufsize);
if (buf)
lth = ntfs_get_ntfs_ea(ni, buf, bufsize);
}
}
if (buf && (lth > 0) && (lth <= bufsize)) {
offset = 0;
found = FALSE;
do {
p_ea = (const EA_ATTR*)&buf[offset];
next = le32_to_cpu(p_ea->next_entry_offset);
found = ((next > (int)(sizeof(lxdev) + sizeof(device)))
&& (p_ea->name_length == (sizeof(lxdev) - 1))
&& (p_ea->value_length
== const_cpu_to_le16(sizeof(device)))
&& !memcmp(p_ea->name, lxdev, sizeof(lxdev)));
if (!found)
offset += next;
} while (!found && (next > 0) && (offset < lth));
if (found) {
/* beware of alignment */
memcpy(&device, &p_ea->name[p_ea->name_length + 1],
sizeof(device));
*rdevp = makedev(le32_to_cpu(device.major),
le32_to_cpu(device.minor));
res = 0;
}
}
free(buf);
return (res);
}
int ntfs_ea_set_wsl_not_symlink(ntfs_inode *ni, mode_t type, dev_t dev)
{
le32 mode;
struct {
le32 major;
le32 minor;
} device;
struct EA_WSL {
struct EA_LXMOD { /* always inserted */
EA_ATTR base;
char name[sizeof(lxmod)];
char value[sizeof(mode)];
char stuff[3 & -(sizeof(lxmod) + sizeof(mode))];
} mod;
struct EA_LXDEV { /* char or block devices only */
EA_ATTR base;
char name[sizeof(lxdev)];
char value[sizeof(device)];
char stuff[3 & -(sizeof(lxdev) + sizeof(device))];
} dev;
} attr;
int len;
int res;
memset(&attr, 0, sizeof(attr));
mode = cpu_to_le32((u32)(type | 0644));
attr.mod.base.next_entry_offset
= const_cpu_to_le32(sizeof(attr.mod));
attr.mod.base.flags = 0;
attr.mod.base.name_length = sizeof(lxmod) - 1;
attr.mod.base.value_length = const_cpu_to_le16(sizeof(mode));
memcpy(attr.mod.name, lxmod, sizeof(lxmod));
memcpy(attr.mod.value, &mode, sizeof(mode));
len = sizeof(attr.mod);
if (S_ISCHR(type) || S_ISBLK(type)) {
device.major = cpu_to_le32(major(dev));
device.minor = cpu_to_le32(minor(dev));
attr.dev.base.next_entry_offset
= const_cpu_to_le32(sizeof(attr.dev));
attr.dev.base.flags = 0;
attr.dev.base.name_length = sizeof(lxdev) - 1;
attr.dev.base.value_length = const_cpu_to_le16(sizeof(device));
memcpy(attr.dev.name, lxdev, sizeof(lxdev));
memcpy(attr.dev.value, &device, sizeof(device));
len += sizeof(attr.dev);
}
res = ntfs_set_ntfs_ea(ni, (char*)&attr, len, 0);
return (res);
}

View File

@ -1,430 +0,0 @@
/**
* efs.c - Limited processing of encrypted files
*
* This module is part of ntfs-3g library
*
* Copyright (c) 2009 Martin Bene
* Copyright (c) 2009-2010 Jean-Pierre Andre
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program/include file 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 (in the main directory of the NTFS-3G
* distribution in the file COPYING); if not, write to the Free Software
* Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#ifdef HAVE_SYS_SYSMACROS_H
#include <sys/sysmacros.h>
#endif
#include "types.h"
#include "debug.h"
#include "attrib.h"
#include "inode.h"
#include "dir.h"
#include "efs.h"
#include "index.h"
#include "logging.h"
#include "misc.h"
#include "efs.h"
#include "xattrs.h"
static ntfschar logged_utility_stream_name[] = {
const_cpu_to_le16('$'),
const_cpu_to_le16('E'),
const_cpu_to_le16('F'),
const_cpu_to_le16('S'),
const_cpu_to_le16(0)
} ;
/*
* Get the ntfs EFS info into an extended attribute
*/
int ntfs_get_efs_info(ntfs_inode *ni, char *value, size_t size)
{
EFS_ATTR_HEADER *efs_info;
s64 attr_size = 0;
if (ni) {
if (ni->flags & FILE_ATTR_ENCRYPTED) {
efs_info = (EFS_ATTR_HEADER*)ntfs_attr_readall(ni,
AT_LOGGED_UTILITY_STREAM,(ntfschar*)NULL, 0,
&attr_size);
if (efs_info
&& (le32_to_cpu(efs_info->length) == attr_size)) {
if (attr_size <= (s64)size) {
if (value)
memcpy(value,efs_info,attr_size);
else {
errno = EFAULT;
attr_size = 0;
}
} else
if (size) {
errno = ERANGE;
attr_size = 0;
}
free (efs_info);
} else {
if (efs_info) {
free(efs_info);
ntfs_log_error("Bad efs_info for inode %lld\n",
(long long)ni->mft_no);
} else {
ntfs_log_error("Could not get efsinfo"
" for inode %lld\n",
(long long)ni->mft_no);
}
errno = EIO;
attr_size = 0;
}
} else {
errno = ENODATA;
ntfs_log_trace("Inode %lld is not encrypted\n",
(long long)ni->mft_no);
}
}
return (attr_size ? (int)attr_size : -errno);
}
/*
* Fix all encrypted AT_DATA attributes of an inode
*
* The fix may require making an attribute non resident, which
* requires more space in the MFT record, and may cause some
* attribute to be expelled and the full record to be reorganized.
* When this happens, the search for data attributes has to be
* reinitialized.
*
* Returns zero if successful.
* -1 if there is a problem.
*/
static int fixup_loop(ntfs_inode *ni)
{
ntfs_attr_search_ctx *ctx;
ntfs_attr *na;
ATTR_RECORD *a;
BOOL restart;
int cnt;
int maxcnt;
int res = 0;
maxcnt = 0;
do {
restart = FALSE;
ctx = ntfs_attr_get_search_ctx(ni, NULL);
if (!ctx) {
ntfs_log_error("Failed to get ctx for efs\n");
res = -1;
}
cnt = 0;
while (!restart && !res
&& !ntfs_attr_lookup(AT_DATA, NULL, 0,
CASE_SENSITIVE, 0, NULL, 0, ctx)) {
cnt++;
a = ctx->attr;
na = ntfs_attr_open(ctx->ntfs_ino, AT_DATA,
(ntfschar*)((u8*)a + le16_to_cpu(a->name_offset)),
a->name_length);
if (!na) {
ntfs_log_error("can't open DATA Attribute\n");
res = -1;
}
if (na && !(ctx->attr->flags & ATTR_IS_ENCRYPTED)) {
if (!NAttrNonResident(na)
&& ntfs_attr_make_non_resident(na, ctx)) {
/*
* ntfs_attr_make_non_resident fails if there
* is not enough space in the MFT record.
* When this happens, force making non-resident
* so that some other attribute is expelled.
*/
if (ntfs_attr_force_non_resident(na)) {
res = -1;
} else {
/* make sure there is some progress */
if (cnt <= maxcnt) {
errno = EIO;
ntfs_log_error("Multiple failure"
" making non resident\n");
res = -1;
} else {
ntfs_attr_put_search_ctx(ctx);
ctx = (ntfs_attr_search_ctx*)NULL;
restart = TRUE;
maxcnt = cnt;
}
}
}
if (!restart && !res
&& ntfs_efs_fixup_attribute(ctx, na)) {
ntfs_log_error("Error in efs fixup of AT_DATA Attribute\n");
res = -1;
}
}
if (na)
ntfs_attr_close(na);
}
} while (restart && !res);
if (ctx)
ntfs_attr_put_search_ctx(ctx);
return (res);
}
/*
* Set the efs data from an extended attribute
* Warning : the new data is not checked
* Returns 0, or -1 if there is a problem
*/
int ntfs_set_efs_info(ntfs_inode *ni, const char *value, size_t size,
int flags)
{
int res;
int written;
ntfs_attr *na;
const EFS_ATTR_HEADER *info_header;
res = 0;
if (ni && value && size) {
if (ni->flags & (FILE_ATTR_ENCRYPTED | FILE_ATTR_COMPRESSED)) {
if (ni->flags & FILE_ATTR_ENCRYPTED) {
ntfs_log_trace("Inode %lld already encrypted\n",
(long long)ni->mft_no);
errno = EEXIST;
} else {
/*
* Possible problem : if encrypted file was
* restored in a compressed directory, it was
* restored as compressed.
* TODO : decompress first.
*/
ntfs_log_error("Inode %lld cannot be encrypted and compressed\n",
(long long)ni->mft_no);
errno = EIO;
}
return -1;
}
info_header = (const EFS_ATTR_HEADER*)value;
/* make sure we get a likely efsinfo */
if (le32_to_cpu(info_header->length) != size) {
errno = EINVAL;
return (-1);
}
if (!ntfs_attr_exist(ni,AT_LOGGED_UTILITY_STREAM,
(ntfschar*)NULL,0)) {
if (!(flags & XATTR_REPLACE)) {
/*
* no logged_utility_stream attribute : add one,
* apparently, this does not feed the new value in
*/
res = ntfs_attr_add(ni,AT_LOGGED_UTILITY_STREAM,
logged_utility_stream_name,4,
(u8*)NULL,(s64)size);
} else {
errno = ENODATA;
res = -1;
}
} else {
errno = EEXIST;
res = -1;
}
if (!res) {
/*
* open and update the existing efs data
*/
na = ntfs_attr_open(ni, AT_LOGGED_UTILITY_STREAM,
logged_utility_stream_name, 4);
if (na) {
/* resize attribute */
res = ntfs_attr_truncate(na, (s64)size);
/* overwrite value if any */
if (!res && value) {
written = (int)ntfs_attr_pwrite(na,
(s64)0, (s64)size, value);
if (written != (s64)size) {
ntfs_log_error("Failed to "
"update efs data\n");
errno = EIO;
res = -1;
}
}
ntfs_attr_close(na);
} else
res = -1;
}
if (!res) {
/* Don't handle AT_DATA Attribute(s) if inode is a directory */
if (!(ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)) {
/* iterate over AT_DATA attributes */
/* set encrypted flag, truncate attribute to match padding bytes */
if (fixup_loop(ni))
return -1;
}
ni->flags |= FILE_ATTR_ENCRYPTED;
NInoSetDirty(ni);
NInoFileNameSetDirty(ni);
}
} else {
errno = EINVAL;
res = -1;
}
return (res ? -1 : 0);
}
/*
* Fixup raw encrypted AT_DATA Attribute
* read padding length from last two bytes
* truncate attribute, make non-resident,
* set data size to match padding length
* set ATTR_IS_ENCRYPTED flag on attribute
*
* Return 0 if successful
* -1 if failed (errno tells why)
*/
int ntfs_efs_fixup_attribute(ntfs_attr_search_ctx *ctx, ntfs_attr *na)
{
s64 newsize;
s64 oldsize;
le16 appended_bytes;
u16 padding_length;
ntfs_inode *ni;
BOOL close_ctx = FALSE;
if (!na) {
ntfs_log_error("no na specified for efs_fixup_attribute\n");
goto err_out;
}
if (!ctx) {
ctx = ntfs_attr_get_search_ctx(na->ni, NULL);
if (!ctx) {
ntfs_log_error("Failed to get ctx for efs\n");
goto err_out;
}
close_ctx = TRUE;
if (ntfs_attr_lookup(AT_DATA, na->name, na->name_len,
CASE_SENSITIVE, 0, NULL, 0, ctx)) {
ntfs_log_error("attr lookup for AT_DATA attribute failed in efs fixup\n");
goto err_out;
}
} else {
if (!NAttrNonResident(na)) {
ntfs_log_error("Cannot make non resident"
" when a context has been allocated\n");
goto err_out;
}
}
/* no extra bytes are added to void attributes */
oldsize = na->data_size;
if (oldsize) {
/* make sure size is valid for a raw encrypted stream */
if ((oldsize & 511) != 2) {
ntfs_log_error("Bad raw encrypted stream\n");
goto err_out;
}
/* read padding length from last two bytes of attribute */
if (ntfs_attr_pread(na, oldsize - 2, 2, &appended_bytes) != 2) {
ntfs_log_error("Error reading padding length\n");
goto err_out;
}
padding_length = le16_to_cpu(appended_bytes);
if (padding_length > 511 || padding_length > na->data_size-2) {
errno = EINVAL;
ntfs_log_error("invalid padding length %d for data_size %lld\n",
padding_length, (long long)oldsize);
goto err_out;
}
newsize = oldsize - padding_length - 2;
/*
* truncate attribute to possibly free clusters allocated
* for the last two bytes, but do not truncate to new size
* to avoid losing useful data
*/
if (ntfs_attr_truncate(na, oldsize - 2)) {
ntfs_log_error("Error truncating attribute\n");
goto err_out;
}
} else
newsize = 0;
/*
* Encrypted AT_DATA Attributes MUST be non-resident
* This has to be done after the attribute is resized, as
* resizing down to zero may cause the attribute to be made
* resident.
*/
if (!NAttrNonResident(na)
&& ntfs_attr_make_non_resident(na, ctx)) {
if (!close_ctx
|| ntfs_attr_force_non_resident(na)) {
ntfs_log_error("Error making DATA attribute non-resident\n");
goto err_out;
} else {
/*
* must reinitialize context after forcing
* non-resident. We need a context for updating
* the state, and at this point, we are sure
* the context is not used elsewhere.
*/
ntfs_attr_reinit_search_ctx(ctx);
if (ntfs_attr_lookup(AT_DATA, na->name, na->name_len,
CASE_SENSITIVE, 0, NULL, 0, ctx)) {
ntfs_log_error("attr lookup for AT_DATA attribute failed in efs fixup\n");
goto err_out;
}
}
}
ni = na->ni;
if (!na->name_len) {
ni->data_size = newsize;
ni->allocated_size = na->allocated_size;
}
NInoSetDirty(ni);
NInoFileNameSetDirty(ni);
ctx->attr->data_size = cpu_to_sle64(newsize);
if (sle64_to_cpu(ctx->attr->initialized_size) > newsize)
ctx->attr->initialized_size = ctx->attr->data_size;
ctx->attr->flags |= ATTR_IS_ENCRYPTED;
if (close_ctx)
ntfs_attr_put_search_ctx(ctx);
return (0);
err_out:
if (close_ctx && ctx)
ntfs_attr_put_search_ctx(ctx);
return (-1);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,419 +0,0 @@
/**
* ioctl.c - Processing of ioctls
*
* This module is part of ntfs-3g library
*
* Copyright (c) 2014-2019 Jean-Pierre Andre
* Copyright (c) 2014 Red Hat, Inc.
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program/include file 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 (in the main directory of the NTFS-3G
* distribution in the file COPYING); if not, write to the Free Software
* Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#ifdef HAVE_STDIO_H
#include <stdio.h>
#endif
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif
#include <syslog.h>
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef MAJOR_IN_MKDEV
#include <sys/mkdev.h>
#endif
#ifdef MAJOR_IN_SYSMACROS
#include <sys/sysmacros.h>
#endif
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#ifdef HAVE_LINUX_FS_H
#include <linux/fs.h>
#endif
#include "compat.h"
#include "debug.h"
#include "bitmap.h"
#include "attrib.h"
#include "inode.h"
#include "layout.h"
#include "volume.h"
#include "index.h"
#include "logging.h"
#include "ntfstime.h"
#include "unistr.h"
#include "dir.h"
#include "security.h"
#include "ioctl.h"
#include "misc.h"
#if defined(FITRIM) && defined(BLKDISCARD)
/* Issue a TRIM request to the underlying device for the given clusters. */
static int fstrim_clusters(ntfs_volume *vol, LCN lcn, s64 length)
{
struct ntfs_device *dev = vol->dev;
uint64_t range[2];
ntfs_log_debug("fstrim_clusters: %lld length %lld\n",
(long long) lcn, (long long) length);
range[0] = lcn << vol->cluster_size_bits;
range[1] = length << vol->cluster_size_bits;
if (dev->d_ops->ioctl(dev, BLKDISCARD, range) == -1) {
ntfs_log_debug("fstrim_one_cluster: ioctl failed: %m\n");
return -errno;
}
return 0;
}
static int read_line(const char *path, char *line, size_t max_bytes)
{
FILE *fp;
fp = fopen(path, "r");
if (fp == NULL)
return -errno;
if (fgets(line, max_bytes, fp) == NULL) {
int ret = -EIO; /* fgets doesn't set errno */
fclose(fp);
return ret;
}
fclose (fp);
return 0;
}
static int read_u64(const char *path, u64 *n)
{
char line[64];
int ret;
ret = read_line(path, line, sizeof line);
if (ret)
return ret;
if (sscanf(line, "%" SCNu64, n) != 1)
return -EINVAL;
return 0;
}
/* Find discard limits for current backing device.
*/
static int fstrim_limits(ntfs_volume *vol,
u64 *discard_alignment,
u64 *discard_granularity,
u64 *discard_max_bytes)
{
struct stat statbuf;
char path1[40]; /* holds "/sys/dev/block/%d:%d" */
char path2[40 + sizeof(path1)]; /* less than 40 bytes more than path1 */
int ret;
/* Stat the backing device. Caller has ensured it is a block device. */
if (stat(vol->dev->d_name, &statbuf) == -1) {
ntfs_log_debug("fstrim_limits: could not stat %s\n",
vol->dev->d_name);
return -errno;
}
/* For whole devices,
* /sys/dev/block/MAJOR:MINOR/discard_alignment
* /sys/dev/block/MAJOR:MINOR/queue/discard_granularity
* /sys/dev/block/MAJOR:MINOR/queue/discard_max_bytes
* will exist.
* For partitions, we also need to check the parent device:
* /sys/dev/block/MAJOR:MINOR/../queue/discard_granularity
* /sys/dev/block/MAJOR:MINOR/../queue/discard_max_bytes
*/
snprintf(path1, sizeof path1, "/sys/dev/block/%d:%d",
major(statbuf.st_rdev), minor(statbuf.st_rdev));
snprintf(path2, sizeof path2, "%s/discard_alignment", path1);
ret = read_u64(path2, discard_alignment);
if (ret) {
if (ret != -ENOENT)
return ret;
else
/* We would expect this file to exist on all
* modern kernels. But for the sake of very
* old kernels:
*/
goto not_found;
}
snprintf(path2, sizeof path2, "%s/queue/discard_granularity", path1);
ret = read_u64(path2, discard_granularity);
if (ret) {
if (ret != -ENOENT)
return ret;
else {
snprintf(path2, sizeof path2,
"%s/../queue/discard_granularity", path1);
ret = read_u64(path2, discard_granularity);
if (ret) {
if (ret != -ENOENT)
return ret;
else
goto not_found;
}
}
}
snprintf(path2, sizeof path2, "%s/queue/discard_max_bytes", path1);
ret = read_u64(path2, discard_max_bytes);
if (ret) {
if (ret != -ENOENT)
return ret;
else {
snprintf(path2, sizeof path2,
"%s/../queue/discard_max_bytes", path1);
ret = read_u64(path2, discard_max_bytes);
if (ret) {
if (ret != -ENOENT)
return ret;
else
goto not_found;
}
}
}
return 0;
not_found:
/* If we reach here then we didn't find the device. This is
* not an error, but set discard_max_bytes = 0 to indicate
* that discard is not available.
*/
*discard_alignment = 0;
*discard_granularity = 0;
*discard_max_bytes = 0;
return 0;
}
static inline LCN align_up(ntfs_volume *vol, LCN lcn, u64 granularity)
{
u64 aligned;
aligned = (lcn << vol->cluster_size_bits) + granularity - 1;
aligned -= aligned % granularity;
return (aligned >> vol->cluster_size_bits);
}
static inline u64 align_down(ntfs_volume *vol, u64 count, u64 granularity)
{
u64 aligned;
aligned = count << vol->cluster_size_bits;
aligned -= aligned % granularity;
return (aligned >> vol->cluster_size_bits);
}
#define FSTRIM_BUFSIZ 4096
/* Trim the filesystem.
*
* Free blocks between 'start' and 'start+len-1' (both byte offsets)
* are found and TRIM requests are sent to the block device. 'minlen'
* is the minimum continguous free range to discard.
*/
static int fstrim(ntfs_volume *vol, void *data, u64 *trimmed)
{
struct fstrim_range *range = data;
u64 start = range->start;
u64 len = range->len;
u64 minlen = range->minlen;
u64 discard_alignment, discard_granularity, discard_max_bytes;
u8 *buf = NULL;
LCN start_buf;
int ret;
ntfs_log_debug("fstrim: start=%llu len=%llu minlen=%llu\n",
(unsigned long long) start,
(unsigned long long) len,
(unsigned long long) minlen);
*trimmed = 0;
/* Fail if user tries to use the fstrim -o/-l/-m options.
* XXX We could fix these limitations in future.
*/
if (start != 0 || len != (uint64_t)-1) {
ntfs_log_error("fstrim: setting start or length is not supported\n");
return -EINVAL;
}
if (minlen > vol->cluster_size) {
ntfs_log_error("fstrim: minlen > cluster size is not supported\n");
return -EINVAL;
}
/* Only block devices are supported. It would be possible to
* support backing files (ie. without using loop) but the
* ioctls used to punch holes in files are completely
* different.
*/
if (!NDevBlock(vol->dev)) {
ntfs_log_error("fstrim: not supported for non-block-device\n");
return -EOPNOTSUPP;
}
ret = fstrim_limits(vol, &discard_alignment,
&discard_granularity, &discard_max_bytes);
if (ret)
return ret;
if (discard_alignment != 0) {
ntfs_log_error("fstrim: backing device is not aligned for discards\n");
return -EOPNOTSUPP;
}
if (discard_max_bytes == 0) {
ntfs_log_error("fstrim: backing device does not support discard (discard_max_bytes == 0)\n");
return -EOPNOTSUPP;
}
/* Sync the device before doing anything. */
ret = ntfs_device_sync(vol->dev);
if (ret)
return ret;
/* Read through the bitmap. */
buf = ntfs_malloc(FSTRIM_BUFSIZ);
if (buf == NULL)
return -errno;
for (start_buf = 0; start_buf < vol->nr_clusters;
start_buf += FSTRIM_BUFSIZ * 8) {
s64 count;
s64 br;
LCN end_buf, start_lcn;
/* start_buf is LCN of first cluster in the current buffer.
* end_buf is LCN of last cluster + 1 in the current buffer.
*/
end_buf = start_buf + FSTRIM_BUFSIZ*8;
if (end_buf > vol->nr_clusters)
end_buf = vol->nr_clusters;
count = (end_buf - start_buf) / 8;
br = ntfs_attr_pread(vol->lcnbmp_na, start_buf/8, count, buf);
if (br != count) {
if (br >= 0)
ret = -EIO;
else
ret = -errno;
goto free_out;
}
/* Trim the clusters in large as possible blocks, but
* not larger than discard_max_bytes, and compatible
* with the supported trim granularity.
*/
for (start_lcn = start_buf; start_lcn < end_buf; ++start_lcn) {
if (!ntfs_bit_get(buf, start_lcn-start_buf)) {
LCN end_lcn;
LCN aligned_lcn;
u64 aligned_count;
/* Cluster 'start_lcn' is not in use,
* find end of this run.
*/
end_lcn = start_lcn+1;
while (end_lcn < end_buf &&
(u64) (end_lcn-start_lcn) << vol->cluster_size_bits
< discard_max_bytes &&
!ntfs_bit_get(buf, end_lcn-start_buf))
end_lcn++;
aligned_lcn = align_up(vol, start_lcn,
discard_granularity);
if (aligned_lcn >= end_lcn)
aligned_count = 0;
else {
aligned_count =
align_down(vol,
end_lcn - aligned_lcn,
discard_granularity);
}
if (aligned_count) {
ret = fstrim_clusters(vol,
aligned_lcn, aligned_count);
if (ret)
goto free_out;
*trimmed += aligned_count
<< vol->cluster_size_bits;
}
start_lcn = end_lcn-1;
}
}
}
ret = 0;
free_out:
free(buf);
return ret;
}
#endif /* FITRIM && BLKDISCARD */
int ntfs_ioctl(ntfs_inode *ni, unsigned long cmd,
void *arg __attribute__((unused)),
unsigned int flags __attribute__((unused)), void *data)
{
int ret = 0;
switch (cmd) {
#if defined(FITRIM) && defined(BLKDISCARD)
case FITRIM:
if (!ni || !data)
ret = -EINVAL;
else {
u64 trimmed;
struct fstrim_range *range = (struct fstrim_range*)data;
ret = fstrim(ni->vol, data, &trimmed);
range->len = trimmed;
}
break;
#else
#warning Trimming not supported : FITRIM or BLKDISCARD not defined
#endif
default :
ret = -EINVAL;
break;
}
return (ret);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +0,0 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: libntfs-3g
Description: NTFS-3G Read/Write Driver Library
Version: @PACKAGE_VERSION@
Cflags: -I${includedir}
Libs: @LIBFUSE_LITE_LIBS@ -L${libdir} -lntfs-3g

View File

@ -1,2 +0,0 @@
@OUTPUT_FORMAT@
GROUP ( @rootlibdir@/libntfs-3g.so )

View File

@ -3,7 +3,7 @@
*
* Copyright (c) 2002-2005 Anton Altaparmakov
* Copyright (c) 2005 Yura Pakhuchiy
* Copyright (c) 2005-2009 Szabolcs Szakacsits
* Copyright (c) 2005-2006 Szabolcs Szakacsits
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
@ -84,21 +84,13 @@ static BOOL ntfs_check_restart_page_header(RESTART_PAGE_HEADER *rp, s64 pos)
"position in $LogFile.\n");
return FALSE;
}
/*
* We only know how to handle version 1.1 and 2.0, though
* version 2.0 is probably related to cached metadata in
* Windows 8, and we will refuse to mount.
* Nevertheless, do all the relevant checks before rejecting.
*/
if (((rp->major_ver != const_cpu_to_sle16(1))
|| (rp->minor_ver != const_cpu_to_sle16(1)))
&& ((rp->major_ver != const_cpu_to_sle16(2))
|| (rp->minor_ver != const_cpu_to_sle16(0)))) {
/* We only know how to handle version 1.1. */
if (sle16_to_cpu(rp->major_ver) != 1 ||
sle16_to_cpu(rp->minor_ver) != 1) {
ntfs_log_error("$LogFile version %i.%i is not "
"supported.\n (This driver supports version "
"1.1 and 2.0 only.)\n",
(int)sle16_to_cpu(rp->major_ver),
(int)sle16_to_cpu(rp->minor_ver));
"supported. (This driver supports version "
"1.1 only.)\n", (int)sle16_to_cpu(rp->major_ver),
(int)sle16_to_cpu(rp->minor_ver));
return FALSE;
}
/*
@ -119,7 +111,7 @@ static BOOL ntfs_check_restart_page_header(RESTART_PAGE_HEADER *rp, s64 pos)
/* Verify the position of the update sequence array. */
usa_ofs = le16_to_cpu(rp->usa_ofs);
usa_end = usa_ofs + usa_count * sizeof(u16);
if (usa_ofs < offsetof(RESTART_PAGE_HEADER, usn) ||
if (usa_ofs < sizeof(RESTART_PAGE_HEADER) ||
usa_end > NTFS_BLOCK_SIZE - sizeof(u16)) {
ntfs_log_error("$LogFile restart page specifies "
"inconsistent update sequence array offset.\n");
@ -134,7 +126,7 @@ skip_usa_checks:
*/
ra_ofs = le16_to_cpu(rp->restart_area_offset);
if (ra_ofs & 7 || (have_usa ? ra_ofs < usa_end :
ra_ofs < offsetof(RESTART_PAGE_HEADER, usn)) ||
ra_ofs < sizeof(RESTART_PAGE_HEADER)) ||
ra_ofs > logfile_system_page_size) {
ntfs_log_error("$LogFile restart page specifies "
"inconsistent restart area offset.\n");
@ -287,19 +279,9 @@ static BOOL ntfs_check_log_client_array(RESTART_PAGE_HEADER *rp)
LOG_CLIENT_RECORD *ca, *cr;
u16 nr_clients, idx;
BOOL in_free_list, idx_is_first;
u32 offset_clients;
ntfs_log_trace("Entering.\n");
/* The restart area must be fully within page */
if ((le16_to_cpu(rp->restart_area_offset) + sizeof(RESTART_AREA))
> le32_to_cpu(rp->system_page_size))
goto err_out;
ra = (RESTART_AREA*)((u8*)rp + le16_to_cpu(rp->restart_area_offset));
offset_clients = le16_to_cpu(rp->restart_area_offset)
+ le16_to_cpu(ra->client_array_offset);
/* The clients' records must begin within page */
if (offset_clients >= le32_to_cpu(rp->system_page_size))
goto err_out;
ca = (LOG_CLIENT_RECORD*)((u8*)ra +
le16_to_cpu(ra->client_array_offset));
/*
@ -318,10 +300,6 @@ check_list:
idx = le16_to_cpu(cr->next_client)) {
if (!nr_clients || idx >= le16_to_cpu(ra->log_clients))
goto err_out;
/* The client record must be fully within page */
if ((offset_clients + (idx + 1)*sizeof(LOG_CLIENT_RECORD))
> le32_to_cpu(rp->system_page_size))
goto err_out;
/* Set @cr to the current log client record. */
cr = ca + idx;
/* The first log client record must not have a prev_client. */
@ -394,14 +372,7 @@ static int ntfs_check_and_load_restart_page(ntfs_attr *log_na,
/*
* Allocate a buffer to store the whole restart page so we can multi
* sector transfer deprotect it.
* For safety, make sure this is consistent with the usa_count
* and shorter than the full log size
*/
if ((le32_to_cpu(rp->system_page_size)
> (u32)(le16_to_cpu(rp->usa_count) - 1)*NTFS_BLOCK_SIZE)
|| (le32_to_cpu(rp->system_page_size)
> le64_to_cpu(log_na->data_size)))
return (EINVAL);
trp = ntfs_malloc(le32_to_cpu(rp->system_page_size));
if (!trp)
return errno;
@ -497,7 +468,7 @@ BOOL ntfs_check_logfile(ntfs_attr *log_na, RESTART_PAGE_HEADER **rp)
u8 *kaddr = NULL;
RESTART_PAGE_HEADER *rstr1_ph = NULL;
RESTART_PAGE_HEADER *rstr2_ph = NULL;
int log_page_size, err;
int log_page_size, log_page_mask, err;
BOOL logfile_is_empty = TRUE;
u8 log_page_bits;
@ -510,6 +481,7 @@ BOOL ntfs_check_logfile(ntfs_attr *log_na, RESTART_PAGE_HEADER **rp)
if (size > (s64)MaxLogFileSize)
size = MaxLogFileSize;
log_page_size = DefaultLogPageSize;
log_page_mask = log_page_size - 1;
/*
* Use generic_ffs() instead of ffs() to enable the compiler to
* optimize log_page_size and log_page_bits into constants.
@ -683,16 +655,19 @@ BOOL ntfs_is_logfile_clean(ntfs_attr *log_na, RESTART_PAGE_HEADER *rp)
ntfs_log_trace("Entering.\n");
/* An empty $LogFile must have been clean before it got emptied. */
if (NVolLogFileEmpty(log_na->ni->vol)) {
ntfs_log_trace("$LogFile is empty\n");
ntfs_log_trace("Done. ($LogFile is empty.)\n");
return TRUE;
}
if (!rp) {
ntfs_log_error("Restart page header is NULL\n");
ntfs_log_error("Restart page header is NULL.\n");
return FALSE;
}
if (!ntfs_is_rstr_record(rp->magic) &&
!ntfs_is_chkd_record(rp->magic)) {
ntfs_log_error("Restart page buffer is invalid\n");
ntfs_log_error("Restart page buffer is invalid. This is "
"probably a bug in that the $LogFile should "
"have been consistency checked before calling "
"this function.\n");
return FALSE;
}
@ -704,13 +679,11 @@ BOOL ntfs_is_logfile_clean(ntfs_attr *log_na, RESTART_PAGE_HEADER *rp)
*/
if (ra->client_in_use_list != LOGFILE_NO_CLIENT &&
!(ra->flags & RESTART_VOLUME_IS_CLEAN)) {
ntfs_log_error("The disk contains an unclean file system (%d, "
"%d).\n", le16_to_cpu(ra->client_in_use_list),
le16_to_cpu(ra->flags));
ntfs_log_debug("Done. $LogFile indicates a dirty shutdown.\n");
return FALSE;
}
/* $LogFile indicates a clean shutdown. */
ntfs_log_trace("$LogFile indicates a clean shutdown\n");
ntfs_log_trace("Done. $LogFile indicates a clean shutdown.\n");
return TRUE;
}
@ -727,31 +700,55 @@ BOOL ntfs_is_logfile_clean(ntfs_attr *log_na, RESTART_PAGE_HEADER *rp)
*/
int ntfs_empty_logfile(ntfs_attr *na)
{
s64 pos, count;
s64 len, pos, count;
char buf[NTFS_BUF_SIZE];
ntfs_log_trace("Entering.\n");
if (NVolLogFileEmpty(na->ni->vol))
return 0;
/* The $DATA attribute of the $LogFile has to be non-resident. */
if (!NAttrNonResident(na)) {
errno = EIO;
ntfs_log_perror("Resident $LogFile $DATA attribute");
ntfs_log_perror("$LogFile $DATA attribute is resident!?!\n");
return -1;
}
/* Get length of $LogFile contents. */
len = na->data_size;
if (!len) {
ntfs_log_debug("$LogFile has zero length, no disk write "
"needed.\n");
return 0;
}
/* Read $LogFile until its end. We do this as a check for correct
length thus making sure we are decompressing the mapping pairs
array correctly and hence writing below is safe as well. */
pos = 0;
while ((count = ntfs_attr_pread(na, pos, NTFS_BUF_SIZE, buf)) > 0)
pos += count;
if (count == -1 || pos != len) {
ntfs_log_error("Amount of $LogFile data read does not "
"correspond to expected length!\n");
if (count != -1)
errno = EIO;
return -1;
}
/* Fill the buffer with 0xff's. */
memset(buf, -1, NTFS_BUF_SIZE);
/* Set the $DATA attribute. */
pos = 0;
while ((count = na->data_size - pos) > 0) {
while ((count = len - pos) > 0) {
if (count > NTFS_BUF_SIZE)
count = NTFS_BUF_SIZE;
count = ntfs_attr_pwrite(na, pos, count, buf);
if (count <= 0) {
ntfs_log_perror("Failed to reset $LogFile");
if ((count = ntfs_attr_pwrite(na, pos, count, buf)) <= 0) {
ntfs_log_perror("Failed to set the $LogFile attribute "
"value.\n");
if (count != -1)
errno = EIO;
return -1;
@ -759,7 +756,7 @@ int ntfs_empty_logfile(ntfs_attr *na)
pos += count;
}
/* Set the flag so we do not have to do it again on remount. */
NVolSetLogFileEmpty(na->ni->vol);
return 0;
}

View File

@ -2,8 +2,7 @@
* logging.c - Centralised logging. Originated from the Linux-NTFS project.
*
* Copyright (c) 2005 Richard Russon
* Copyright (c) 2005-2008 Szabolcs Szakacsits
* Copyright (c) 2010 Jean-Pierre Andre
* Copyright (c) 2005-2006 Szabolcs Szakacsits
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
@ -51,16 +50,13 @@
#define PATH_SEP '/'
#endif
#ifdef DEBUG
static int tab;
#endif
/* Some gcc 3.x, 4.[01].X crash with internal compiler error. */
#if __GNUC__ <= 3 || (__GNUC__ == 4 && __GNUC_MINOR__ <= 1)
# define BROKEN_GCC_FORMAT_ATTRIBUTE
#else
# define BROKEN_GCC_FORMAT_ATTRIBUTE __attribute__((format(printf, 6, 0)))
#endif
/* Colour prefixes and a suffix */
static const char *col_green = "\e[32m";
static const char *col_cyan = "\e[36m";
static const char *col_yellow = "\e[01;33m";
static const char *col_red = "\e[01;31m";
static const char *col_redinv = "\e[01;07;31m";
static const char *col_end = "\e[0m";
/**
* struct ntfs_logging - Control info for the logging system
@ -71,7 +67,7 @@ static int tab;
struct ntfs_logging {
u32 levels;
u32 flags;
ntfs_log_handler *handler BROKEN_GCC_FORMAT_ATTRIBUTE;
ntfs_log_handler *handler;
};
/**
@ -80,8 +76,7 @@ struct ntfs_logging {
*/
static struct ntfs_logging ntfs_log = {
#ifdef DEBUG
NTFS_LOG_LEVEL_DEBUG | NTFS_LOG_LEVEL_TRACE | NTFS_LOG_LEVEL_ENTER |
NTFS_LOG_LEVEL_LEAVE |
NTFS_LOG_LEVEL_DEBUG | NTFS_LOG_LEVEL_TRACE |
#endif
NTFS_LOG_LEVEL_INFO | NTFS_LOG_LEVEL_QUIET | NTFS_LOG_LEVEL_WARNING |
NTFS_LOG_LEVEL_ERROR | NTFS_LOG_LEVEL_PERROR | NTFS_LOG_LEVEL_CRITICAL |
@ -212,8 +207,6 @@ static FILE * ntfs_log_get_stream(u32 level)
case NTFS_LOG_LEVEL_DEBUG:
case NTFS_LOG_LEVEL_TRACE:
case NTFS_LOG_LEVEL_ENTER:
case NTFS_LOG_LEVEL_LEAVE:
case NTFS_LOG_LEVEL_WARNING:
case NTFS_LOG_LEVEL_ERROR:
case NTFS_LOG_LEVEL_CRITICAL:
@ -291,7 +284,7 @@ void ntfs_log_set_handler(ntfs_log_handler *handler)
ntfs_log.handler = handler;
#ifdef HAVE_SYSLOG_H
if (handler == ntfs_log_handler_syslog)
openlog("ntfs-3g", LOG_PID, LOG_USER);
openlog("libntfs", LOG_PID, LOG_USER);
#endif
} else
ntfs_log.handler = ntfs_log_handler_null;
@ -351,67 +344,48 @@ int ntfs_log_redirect(const char *function, const char *file,
* num Number of output characters
*/
#ifdef HAVE_SYSLOG_H
#define LOG_LINE_LEN 512
int ntfs_log_handler_syslog(const char *function __attribute__((unused)),
const char *file __attribute__((unused)),
int line __attribute__((unused)), u32 level,
void *data __attribute__((unused)),
const char *format, va_list args)
const char *file, __attribute__((unused)) int line, u32 level,
void *data __attribute__((unused)), const char *format, va_list args)
{
char logbuf[LOG_LINE_LEN];
int ret, olderr = errno;
int ret = 0;
int olderr = errno;
#ifndef DEBUG
if ((level & NTFS_LOG_LEVEL_PERROR) && errno == ENOSPC)
return 1;
#endif
ret = vsnprintf(logbuf, LOG_LINE_LEN, format, args);
if (ret < 0) {
vsyslog(LOG_NOTICE, format, args);
ret = 1;
goto out;
if ((ntfs_log.flags & NTFS_LOG_FLAG_ONLYNAME) &&
(strchr(file, PATH_SEP))) /* Abbreviate the filename */
file = strrchr(file, PATH_SEP) + 1;
#if 0 /* FIXME: Implement this all. */
if (ntfs_log.flags & NTFS_LOG_FLAG_PREFIX) /* Prefix the output */
ret += fprintf(stream, "%s", ntfs_log_get_prefix(level));
if (ntfs_log.flags & NTFS_LOG_FLAG_FILENAME) /* Source filename */
ret += fprintf(stream, "%s ", file);
if (ntfs_log.flags & NTFS_LOG_FLAG_LINE) /* Source line number */
ret += fprintf(stream, "(%d) ", line);
if ((ntfs_log.flags & NTFS_LOG_FLAG_FUNCTION) || /* Source function */
(level & NTFS_LOG_LEVEL_TRACE))
ret += fprintf(stream, "%s(): ", function);
ret += vfprintf(stream, format, args);
if (level & NTFS_LOG_LEVEL_PERROR) {
if (reason)
ret += fprintf(stream, ": %s\n", reason);
else
ret += fprintf(stream, ": %s\n", strerror(olderr));
}
if ((LOG_LINE_LEN > ret + 3) && (level & NTFS_LOG_LEVEL_PERROR)) {
strncat(logbuf, ": ", LOG_LINE_LEN - ret - 1);
strncat(logbuf, strerror(olderr), LOG_LINE_LEN - (ret + 3));
ret = strlen(logbuf);
}
syslog(LOG_NOTICE, "%s", logbuf);
out:
#endif
vsyslog(LOG_NOTICE, format, args);
ret = 1; /* FIXME: caclulate how many bytes had been written. */
errno = olderr;
return ret;
}
#endif
/*
* Early logging before the logs are redirected
*
* (not quite satisfactory : this appears before the ntfs-g banner,
* and with a different pid)
*/
void ntfs_log_early_error(const char *format, ...)
{
va_list args;
va_start(args, format);
#ifdef HAVE_SYSLOG_H
openlog("ntfs-3g", LOG_PID, LOG_USER);
ntfs_log_handler_syslog(NULL, NULL, 0,
NTFS_LOG_LEVEL_ERROR, NULL,
format, args);
#else
vfprintf(stderr,format,args);
#endif
va_end(args);
}
/**
* ntfs_log_handler_fprintf - Basic logging handler
* @function: Function in which the log line occurred
@ -436,27 +410,46 @@ void ntfs_log_early_error(const char *format, ...)
int ntfs_log_handler_fprintf(const char *function, const char *file,
int line, u32 level, void *data, const char *format, va_list args)
{
#ifdef DEBUG
int i;
#endif
int ret = 0;
int olderr = errno;
FILE *stream;
const char *col_prefix = NULL;
const char *col_suffix = NULL;
if (!data) /* Interpret data as a FILE stream. */
return 0; /* If it's NULL, we can't do anything. */
stream = (FILE*)data;
#ifdef DEBUG
if (level == NTFS_LOG_LEVEL_LEAVE) {
if (tab)
tab--;
return 0;
if (ntfs_log.flags & NTFS_LOG_FLAG_COLOUR) {
/* Pick a colour determined by the log level */
switch (level) {
case NTFS_LOG_LEVEL_DEBUG:
col_prefix = col_green;
col_suffix = col_end;
break;
case NTFS_LOG_LEVEL_TRACE:
col_prefix = col_cyan;
col_suffix = col_end;
break;
case NTFS_LOG_LEVEL_WARNING:
col_prefix = col_yellow;
col_suffix = col_end;
break;
case NTFS_LOG_LEVEL_ERROR:
case NTFS_LOG_LEVEL_PERROR:
col_prefix = col_red;
col_suffix = col_end;
break;
case NTFS_LOG_LEVEL_CRITICAL:
col_prefix = col_redinv;
col_suffix = col_end;
break;
}
}
for (i = 0; i < tab; i++)
ret += fprintf(stream, " ");
#endif
if (col_prefix)
ret += fprintf(stream, col_prefix);
if ((ntfs_log.flags & NTFS_LOG_FLAG_ONLYNAME) &&
(strchr(file, PATH_SEP))) /* Abbreviate the filename */
file = strrchr(file, PATH_SEP) + 1;
@ -471,7 +464,7 @@ int ntfs_log_handler_fprintf(const char *function, const char *file,
ret += fprintf(stream, "(%d) ", line);
if ((ntfs_log.flags & NTFS_LOG_FLAG_FUNCTION) || /* Source function */
(level & NTFS_LOG_LEVEL_TRACE) || (level & NTFS_LOG_LEVEL_ENTER))
(level & NTFS_LOG_LEVEL_TRACE))
ret += fprintf(stream, "%s(): ", function);
ret += vfprintf(stream, format, args);
@ -479,10 +472,10 @@ int ntfs_log_handler_fprintf(const char *function, const char *file,
if (level & NTFS_LOG_LEVEL_PERROR)
ret += fprintf(stream, ": %s\n", strerror(olderr));
#ifdef DEBUG
if (level == NTFS_LOG_LEVEL_ENTER)
tab++;
#endif
if (col_suffix)
ret += fprintf(stream, col_suffix);
fflush(stream);
errno = olderr;
return ret;
@ -629,6 +622,10 @@ BOOL ntfs_log_parse_option(const char *option)
} else if (strcmp(option, "--log-trace") == 0) {
ntfs_log_set_levels(NTFS_LOG_LEVEL_TRACE);
return TRUE;
} else if ((strcmp(option, "--log-colour") == 0) ||
(strcmp(option, "--log-color") == 0)) {
ntfs_log_set_flags(NTFS_LOG_FLAG_COLOUR);
return TRUE;
}
ntfs_log_debug("Unknown logging option '%s'\n", option);

File diff suppressed because it is too large Load Diff

View File

@ -1,25 +1,3 @@
/**
* misc.c : miscellaneous :
* - dealing with errors in memory allocation
*
* Copyright (c) 2008 Jean-Pierre Andre
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program/include file 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 (in the main directory of the NTFS-3G
* distribution in the file COPYING); if not, write to the Free Software
* Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
@ -27,11 +5,7 @@
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#include "types.h"
#include "misc.h"
#include "logging.h"
@ -60,18 +34,3 @@ void *ntfs_malloc(size_t size)
return p;
}
void *ntfs_realloc(void *ptr, size_t size)
{
void *p;
p = realloc(ptr, size);
if (!p)
ntfs_log_perror("Failed to realloc %lld bytes",
(long long)size);
return p;
}
void ntfs_free(void *p)
{
free(p);
}

View File

@ -2,7 +2,7 @@
* mst.c - Multi sector fixup handling code. Originated from the Linux-NTFS project.
*
* Copyright (c) 2000-2004 Anton Altaparmakov
* Copyright (c) 2006-2009 Szabolcs Szakacsits
* Copyright (c) 2006 Szabolcs Szakacsits
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
@ -31,21 +31,6 @@
#include "mst.h"
#include "logging.h"
/*
* Basic validation of a NTFS multi-sector record. The record size must be a
* multiple of the logical sector size; and the update sequence array must be
* properly aligned, of the expected length, and must end before the last le16
* in the first logical sector.
*/
static BOOL
is_valid_record(u32 size, u16 usa_ofs, u16 usa_count)
{
return size % NTFS_BLOCK_SIZE == 0 &&
usa_ofs % 2 == 0 &&
usa_count == 1 + (size / NTFS_BLOCK_SIZE) &&
usa_ofs + ((u32)usa_count * 2) <= NTFS_BLOCK_SIZE - 2;
}
/**
* ntfs_mst_post_read_fixup - deprotect multi sector transfer protected data
* @b: pointer to the data to deprotect
@ -62,8 +47,7 @@ is_valid_record(u32 size, u16 usa_ofs, u16 usa_count)
* EIO Multi sector transfer error was detected. Magic of the NTFS
* record in @b will have been set to "BAAD".
*/
int ntfs_mst_post_read_fixup_warn(NTFS_RECORD *b, const u32 size,
BOOL warn)
int ntfs_mst_post_read_fixup(NTFS_RECORD *b, const u32 size)
{
u16 usa_ofs, usa_count, usn;
u16 *usa_pos, *data_pos;
@ -72,18 +56,13 @@ int ntfs_mst_post_read_fixup_warn(NTFS_RECORD *b, const u32 size,
/* Setup the variables. */
usa_ofs = le16_to_cpu(b->usa_ofs);
usa_count = le16_to_cpu(b->usa_count);
if (!is_valid_record(size, usa_ofs, usa_count)) {
/* Decrement usa_count to get number of fixups. */
usa_count = le16_to_cpu(b->usa_count) - 1;
/* Size and alignment checks. */
if (size & (NTFS_BLOCK_SIZE - 1) || usa_ofs & 1 ||
(u32)(usa_ofs + (usa_count * 2)) > size ||
(size >> NTFS_BLOCK_SIZE_BITS) != usa_count) {
errno = EINVAL;
if (warn) {
ntfs_log_perror("%s: magic: 0x%08lx size: %ld "
" usa_ofs: %d usa_count: %u",
__FUNCTION__,
(long)le32_to_cpu(*(le32 *)b),
(long)size, (int)usa_ofs,
(unsigned int)usa_count);
}
return -1;
}
/* Position of usn in update sequence array. */
@ -103,28 +82,24 @@ int ntfs_mst_post_read_fixup_warn(NTFS_RECORD *b, const u32 size,
/*
* Check for incomplete multi sector transfer(s).
*/
while (--usa_count) {
while (usa_count--) {
if (*data_pos != usn) {
/*
* Incomplete multi sector transfer detected! )-:
* Set the magic to "BAAD" and return failure.
* Note that magic_BAAD is already converted to le32.
*/
errno = EIO;
ntfs_log_perror("Incomplete multi-sector transfer: "
"magic: 0x%08x size: %d usa_ofs: %d usa_count:"
" %d data: %d usn: %d", le32_to_cpu(*(le32 *)b), size,
usa_ofs, usa_count, *data_pos, usn);
b->magic = magic_BAAD;
errno = EIO;
return -1;
}
data_pos += NTFS_BLOCK_SIZE/sizeof(u16);
}
/* Re-setup the variables. */
usa_count = le16_to_cpu(b->usa_count);
usa_count = le16_to_cpu(b->usa_count) - 1;
data_pos = (u16*)b + NTFS_BLOCK_SIZE/sizeof(u16) - 1;
/* Fixup all sectors. */
while (--usa_count) {
while (usa_count--) {
/*
* Increment position in usa and restore original data from
* the usa into the data buffer.
@ -136,16 +111,6 @@ int ntfs_mst_post_read_fixup_warn(NTFS_RECORD *b, const u32 size,
return 0;
}
/*
* Deprotect multi sector transfer protected data
* with a warning if an error is found.
*/
int ntfs_mst_post_read_fixup(NTFS_RECORD *b, const u32 size)
{
return (ntfs_mst_post_read_fixup_warn(b,size,TRUE));
}
/**
* ntfs_mst_pre_write_fixup - apply multi sector transfer protection
* @b: pointer to the data to protect
@ -169,8 +134,7 @@ int ntfs_mst_post_read_fixup(NTFS_RECORD *b, const u32 size)
int ntfs_mst_pre_write_fixup(NTFS_RECORD *b, const u32 size)
{
u16 usa_ofs, usa_count, usn;
le16 le_usn;
le16 *usa_pos, *data_pos;
u16 *usa_pos, *data_pos;
ntfs_log_trace("Entering\n");
@ -178,20 +142,21 @@ int ntfs_mst_pre_write_fixup(NTFS_RECORD *b, const u32 size)
if (!b || ntfs_is_baad_record(b->magic) ||
ntfs_is_hole_record(b->magic)) {
errno = EINVAL;
ntfs_log_perror("%s: bad argument", __FUNCTION__);
return -1;
}
/* Setup the variables. */
usa_ofs = le16_to_cpu(b->usa_ofs);
usa_count = le16_to_cpu(b->usa_count);
if (!is_valid_record(size, usa_ofs, usa_count)) {
/* Decrement usa_count to get number of fixups. */
usa_count = le16_to_cpu(b->usa_count) - 1;
/* Size and alignment checks. */
if (size & (NTFS_BLOCK_SIZE - 1) || usa_ofs & 1 ||
(u32)(usa_ofs + (usa_count * 2)) > size ||
(size >> NTFS_BLOCK_SIZE_BITS) != usa_count) {
errno = EINVAL;
ntfs_log_perror("%s", __FUNCTION__);
return -1;
}
/* Position of usn in update sequence array. */
usa_pos = (le16*)((u8*)b + usa_ofs);
usa_pos = (u16*)((u8*)b + usa_ofs);
/*
* Cyclically increment the update sequence number
* (skipping 0 and -1, i.e. 0xffff).
@ -199,21 +164,21 @@ int ntfs_mst_pre_write_fixup(NTFS_RECORD *b, const u32 size)
usn = le16_to_cpup(usa_pos) + 1;
if (usn == 0xffff || !usn)
usn = 1;
le_usn = cpu_to_le16(usn);
*usa_pos = le_usn;
/* Position in data of first le16 that needs fixing up. */
data_pos = (le16*)b + NTFS_BLOCK_SIZE/sizeof(le16) - 1;
usn = cpu_to_le16(usn);
*usa_pos = usn;
/* Position in data of first u16 that needs fixing up. */
data_pos = (u16*)b + NTFS_BLOCK_SIZE/sizeof(u16) - 1;
/* Fixup all sectors. */
while (--usa_count) {
while (usa_count--) {
/*
* Increment the position in the usa and save the
* original data from the data buffer into the usa.
*/
*(++usa_pos) = *data_pos;
/* Apply fixup to data. */
*data_pos = le_usn;
*data_pos = usn;
/* Increment position in data as well. */
data_pos += NTFS_BLOCK_SIZE/sizeof(le16);
data_pos += NTFS_BLOCK_SIZE/sizeof(u16);
}
return 0;
}
@ -232,7 +197,7 @@ void ntfs_mst_post_write_fixup(NTFS_RECORD *b)
u16 *usa_pos, *data_pos;
u16 usa_ofs = le16_to_cpu(b->usa_ofs);
u16 usa_count = le16_to_cpu(b->usa_count);
u16 usa_count = le16_to_cpu(b->usa_count) - 1;
ntfs_log_trace("Entering\n");
@ -243,7 +208,7 @@ void ntfs_mst_post_write_fixup(NTFS_RECORD *b)
data_pos = (u16*)b + NTFS_BLOCK_SIZE/sizeof(u16) - 1;
/* Fixup all sectors. */
while (--usa_count) {
while (usa_count--) {
/*
* Increment position in usa and restore original data from
* the usa into the data buffer.

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